From a7c9a1701971470fcf966f4cbc617199a99d19fb Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Tue, 30 Sep 2025 09:53:06 +0100 Subject: [PATCH 01/36] cleaned up old files --- content/v3/de/awesome-plugins/index.md | 40 ------ content/v3/de/awesome-plugins/pdo_wrapper.md | 122 ---------------- content/v3/de/install.md | 66 --------- content/v3/de/learn.md | 90 ------------ content/v3/de/learn/api.md | 58 -------- content/v3/de/learn/frameworkinstance.md | 19 --- content/v3/de/learn/httpcaching.md | 27 ---- content/v3/de/learn/redirects.md | 13 -- content/v3/de/learn/stopping.md | 19 --- content/v3/de/learn/troubleshooting.md | 64 --------- content/v3/de/learn/variables.md | 35 ----- content/v3/de/learn/views.md | 128 ----------------- content/v3/es/awesome-plugins/index.md | 40 ------ content/v3/es/awesome-plugins/pdo_wrapper.md | 122 ---------------- content/v3/es/install.md | 66 --------- content/v3/es/learn.md | 90 ------------ content/v3/es/learn/api.md | 55 -------- content/v3/es/learn/errorhandling.md | 33 ----- content/v3/es/learn/frameworkinstance.md | 19 --- content/v3/es/learn/frameworkmethods.md | 42 ------ content/v3/es/learn/httpcaching.md | 27 ---- content/v3/es/learn/overriding.md | 29 ---- content/v3/es/learn/redirects.md | 15 -- content/v3/es/learn/stopping.md | 20 --- content/v3/es/learn/troubleshooting.md | 72 ---------- content/v3/es/learn/variables.md | 35 ----- content/v3/es/learn/views.md | 128 ----------------- content/v3/fr/awesome-plugins/index.md | 40 ------ content/v3/fr/awesome-plugins/pdo_wrapper.md | 119 ---------------- content/v3/fr/install.md | 65 --------- content/v3/fr/learn.md | 90 ------------ content/v3/fr/learn/api.md | 55 -------- content/v3/fr/learn/errorhandling.md | 36 ----- content/v3/fr/learn/frameworkinstance.md | 17 --- content/v3/fr/learn/frameworkmethods.md | 42 ------ content/v3/fr/learn/httpcaching.md | 34 ----- content/v3/fr/learn/overriding.md | 29 ---- content/v3/fr/learn/redirects.md | 15 -- content/v3/fr/learn/stopping.md | 20 --- content/v3/fr/learn/troubleshooting.md | 69 --------- content/v3/fr/learn/variables.md | 34 ----- content/v3/fr/learn/views.md | 129 ----------------- content/v3/id/awesome-plugins/pdo_wrapper.md | 119 ---------------- content/v3/id/learn.md | 90 ------------ content/v3/id/learn/api.md | 56 -------- content/v3/id/learn/troubleshooting.md | 72 ---------- content/v3/ja/awesome-plugins/index.md | 40 ------ content/v3/ja/awesome-plugins/pdo_wrapper.md | 119 ---------------- content/v3/ja/install.md | 62 --------- content/v3/ja/learn.md | 90 ------------ content/v3/ja/learn/api.md | 55 -------- content/v3/ja/learn/errorhandling.md | 33 ----- content/v3/ja/learn/frameworkinstance.md | 17 --- content/v3/ja/learn/frameworkmethods.md | 40 ------ content/v3/ja/learn/httpcaching.md | 27 ---- content/v3/ja/learn/overriding.md | 25 ---- content/v3/ja/learn/redirects.md | 13 -- content/v3/ja/learn/stopping.md | 19 --- content/v3/ja/learn/troubleshooting.md | 68 --------- content/v3/ja/learn/variables.md | 34 ----- content/v3/ja/learn/views.md | 128 ----------------- content/v3/ko/awesome-plugins/index.md | 40 ------ content/v3/ko/awesome-plugins/pdo_wrapper.md | 119 ---------------- content/v3/ko/install.md | 64 --------- content/v3/ko/learn.md | 90 ------------ content/v3/ko/learn/api.md | 56 -------- content/v3/ko/learn/errorhandling.md | 34 ----- content/v3/ko/learn/frameworkinstance.md | 17 --- content/v3/ko/learn/frameworkmethods.md | 43 ------ content/v3/ko/learn/httpcaching.md | 27 ---- content/v3/ko/learn/overriding.md | 25 ---- content/v3/ko/learn/redirects.md | 13 -- content/v3/ko/learn/stopping.md | 19 --- content/v3/ko/learn/troubleshooting.md | 68 --------- content/v3/ko/learn/variables.md | 35 ----- content/v3/ko/learn/views.md | 131 ----------------- content/v3/lv/awesome-plugins/index.md | 40 ------ content/v3/lv/awesome-plugins/pdo_wrapper.md | 119 ---------------- content/v3/lv/install.md | 65 --------- content/v3/lv/learn.md | 90 ------------ content/v3/lv/learn/api.md | 58 -------- content/v3/lv/learn/errorhandling.md | 33 ----- content/v3/lv/learn/frameworkinstance.md | 19 --- content/v3/lv/learn/frameworkmethods.md | 42 ------ content/v3/lv/learn/httpcaching.md | 35 ----- content/v3/lv/learn/overriding.md | 29 ---- content/v3/lv/learn/redirects.md | 11 -- content/v3/lv/learn/stopping.md | 20 --- content/v3/lv/learn/troubleshooting.md | 68 --------- content/v3/lv/learn/variables.md | 35 ----- content/v3/lv/learn/views.md | 139 ------------------- content/v3/pt/awesome-plugins/index.md | 40 ------ content/v3/pt/awesome-plugins/pdo_wrapper.md | 0 content/v3/pt/install.md | 65 --------- content/v3/pt/learn.md | 90 ------------ content/v3/pt/learn/api.md | 58 -------- content/v3/pt/learn/errorhandling.md | 36 ----- content/v3/pt/learn/frameworkinstance.md | 17 --- content/v3/pt/learn/frameworkmethods.md | 44 ------ content/v3/pt/learn/httpcaching.md | 27 ---- content/v3/pt/learn/overriding.md | 29 ---- content/v3/pt/learn/redirects.md | 15 -- content/v3/pt/learn/stopping.md | 20 --- content/v3/pt/learn/troubleshooting.md | 74 ---------- content/v3/pt/learn/variables.md | 35 ----- content/v3/pt/learn/views.md | 136 ------------------ content/v3/ru/awesome-plugins/index.md | 40 ------ content/v3/ru/awesome-plugins/pdo_wrapper.md | 122 ---------------- content/v3/ru/install.md | 67 --------- content/v3/ru/learn.md | 90 ------------ content/v3/ru/learn/api.md | 58 -------- content/v3/ru/learn/errorhandling.md | 36 ----- content/v3/ru/learn/frameworkinstance.md | 19 --- content/v3/ru/learn/frameworkmethods.md | 42 ------ content/v3/ru/learn/httpcaching.md | 35 ----- content/v3/ru/learn/overriding.md | 29 ---- content/v3/ru/learn/redirects.md | 14 -- content/v3/ru/learn/stopping.md | 20 --- content/v3/ru/learn/troubleshooting.md | 70 ---------- content/v3/ru/learn/variables.md | 35 ----- content/v3/ru/learn/views.md | 139 ------------------- content/v3/uk/awesome-plugins/pdo_wrapper.md | 122 ---------------- content/v3/uk/learn.md | 90 ------------ content/v3/uk/learn/api.md | 55 -------- content/v3/uk/learn/troubleshooting.md | 72 ---------- content/v3/zh/awesome-plugins/index.md | 40 ------ content/v3/zh/awesome-plugins/pdo_wrapper.md | 119 ---------------- content/v3/zh/install.md | 65 --------- content/v3/zh/learn.md | 90 ------------ content/v3/zh/learn/api.md | 55 -------- content/v3/zh/learn/errorhandling.md | 33 ----- content/v3/zh/learn/frameworkinstance.md | 17 --- content/v3/zh/learn/frameworkmethods.md | 42 ------ content/v3/zh/learn/httpcaching.md | 27 ---- content/v3/zh/learn/overriding.md | 24 ---- content/v3/zh/learn/redirects.md | 13 -- content/v3/zh/learn/stopping.md | 19 --- content/v3/zh/learn/troubleshooting.md | 68 --------- content/v3/zh/learn/variables.md | 34 ----- content/v3/zh/learn/views.md | 128 ----------------- translate_content.php | 42 ++++++ 141 files changed, 42 insertions(+), 7574 deletions(-) delete mode 100644 content/v3/de/awesome-plugins/index.md delete mode 100644 content/v3/de/awesome-plugins/pdo_wrapper.md delete mode 100644 content/v3/de/install.md delete mode 100644 content/v3/de/learn.md delete mode 100644 content/v3/de/learn/api.md delete mode 100644 content/v3/de/learn/frameworkinstance.md delete mode 100644 content/v3/de/learn/httpcaching.md delete mode 100644 content/v3/de/learn/redirects.md delete mode 100644 content/v3/de/learn/stopping.md delete mode 100644 content/v3/de/learn/troubleshooting.md delete mode 100644 content/v3/de/learn/variables.md delete mode 100644 content/v3/de/learn/views.md delete mode 100644 content/v3/es/awesome-plugins/index.md delete mode 100644 content/v3/es/awesome-plugins/pdo_wrapper.md delete mode 100644 content/v3/es/install.md delete mode 100644 content/v3/es/learn.md delete mode 100644 content/v3/es/learn/api.md delete mode 100644 content/v3/es/learn/errorhandling.md delete mode 100644 content/v3/es/learn/frameworkinstance.md delete mode 100644 content/v3/es/learn/frameworkmethods.md delete mode 100644 content/v3/es/learn/httpcaching.md delete mode 100644 content/v3/es/learn/overriding.md delete mode 100644 content/v3/es/learn/redirects.md delete mode 100644 content/v3/es/learn/stopping.md delete mode 100644 content/v3/es/learn/troubleshooting.md delete mode 100644 content/v3/es/learn/variables.md delete mode 100644 content/v3/es/learn/views.md delete mode 100644 content/v3/fr/awesome-plugins/index.md delete mode 100644 content/v3/fr/awesome-plugins/pdo_wrapper.md delete mode 100644 content/v3/fr/install.md delete mode 100644 content/v3/fr/learn.md delete mode 100644 content/v3/fr/learn/api.md delete mode 100644 content/v3/fr/learn/errorhandling.md delete mode 100644 content/v3/fr/learn/frameworkinstance.md delete mode 100644 content/v3/fr/learn/frameworkmethods.md delete mode 100644 content/v3/fr/learn/httpcaching.md delete mode 100644 content/v3/fr/learn/overriding.md delete mode 100644 content/v3/fr/learn/redirects.md delete mode 100644 content/v3/fr/learn/stopping.md delete mode 100644 content/v3/fr/learn/troubleshooting.md delete mode 100644 content/v3/fr/learn/variables.md delete mode 100644 content/v3/fr/learn/views.md delete mode 100644 content/v3/id/awesome-plugins/pdo_wrapper.md delete mode 100644 content/v3/id/learn.md delete mode 100644 content/v3/id/learn/api.md delete mode 100644 content/v3/id/learn/troubleshooting.md delete mode 100644 content/v3/ja/awesome-plugins/index.md delete mode 100644 content/v3/ja/awesome-plugins/pdo_wrapper.md delete mode 100644 content/v3/ja/install.md delete mode 100644 content/v3/ja/learn.md delete mode 100644 content/v3/ja/learn/api.md delete mode 100644 content/v3/ja/learn/errorhandling.md delete mode 100644 content/v3/ja/learn/frameworkinstance.md delete mode 100644 content/v3/ja/learn/frameworkmethods.md delete mode 100644 content/v3/ja/learn/httpcaching.md delete mode 100644 content/v3/ja/learn/overriding.md delete mode 100644 content/v3/ja/learn/redirects.md delete mode 100644 content/v3/ja/learn/stopping.md delete mode 100644 content/v3/ja/learn/troubleshooting.md delete mode 100644 content/v3/ja/learn/variables.md delete mode 100644 content/v3/ja/learn/views.md delete mode 100644 content/v3/ko/awesome-plugins/index.md delete mode 100644 content/v3/ko/awesome-plugins/pdo_wrapper.md delete mode 100644 content/v3/ko/install.md delete mode 100644 content/v3/ko/learn.md delete mode 100644 content/v3/ko/learn/api.md delete mode 100644 content/v3/ko/learn/errorhandling.md delete mode 100644 content/v3/ko/learn/frameworkinstance.md delete mode 100644 content/v3/ko/learn/frameworkmethods.md delete mode 100644 content/v3/ko/learn/httpcaching.md delete mode 100644 content/v3/ko/learn/overriding.md delete mode 100644 content/v3/ko/learn/redirects.md delete mode 100644 content/v3/ko/learn/stopping.md delete mode 100644 content/v3/ko/learn/troubleshooting.md delete mode 100644 content/v3/ko/learn/variables.md delete mode 100644 content/v3/ko/learn/views.md delete mode 100644 content/v3/lv/awesome-plugins/index.md delete mode 100644 content/v3/lv/awesome-plugins/pdo_wrapper.md delete mode 100644 content/v3/lv/install.md delete mode 100644 content/v3/lv/learn.md delete mode 100644 content/v3/lv/learn/api.md delete mode 100644 content/v3/lv/learn/errorhandling.md delete mode 100644 content/v3/lv/learn/frameworkinstance.md delete mode 100644 content/v3/lv/learn/frameworkmethods.md delete mode 100644 content/v3/lv/learn/httpcaching.md delete mode 100644 content/v3/lv/learn/overriding.md delete mode 100644 content/v3/lv/learn/redirects.md delete mode 100644 content/v3/lv/learn/stopping.md delete mode 100644 content/v3/lv/learn/troubleshooting.md delete mode 100644 content/v3/lv/learn/variables.md delete mode 100644 content/v3/lv/learn/views.md delete mode 100644 content/v3/pt/awesome-plugins/index.md delete mode 100644 content/v3/pt/awesome-plugins/pdo_wrapper.md delete mode 100644 content/v3/pt/install.md delete mode 100644 content/v3/pt/learn.md delete mode 100644 content/v3/pt/learn/api.md delete mode 100644 content/v3/pt/learn/errorhandling.md delete mode 100644 content/v3/pt/learn/frameworkinstance.md delete mode 100644 content/v3/pt/learn/frameworkmethods.md delete mode 100644 content/v3/pt/learn/httpcaching.md delete mode 100644 content/v3/pt/learn/overriding.md delete mode 100644 content/v3/pt/learn/redirects.md delete mode 100644 content/v3/pt/learn/stopping.md delete mode 100644 content/v3/pt/learn/troubleshooting.md delete mode 100644 content/v3/pt/learn/variables.md delete mode 100644 content/v3/pt/learn/views.md delete mode 100644 content/v3/ru/awesome-plugins/index.md delete mode 100644 content/v3/ru/awesome-plugins/pdo_wrapper.md delete mode 100644 content/v3/ru/install.md delete mode 100644 content/v3/ru/learn.md delete mode 100644 content/v3/ru/learn/api.md delete mode 100644 content/v3/ru/learn/errorhandling.md delete mode 100644 content/v3/ru/learn/frameworkinstance.md delete mode 100644 content/v3/ru/learn/frameworkmethods.md delete mode 100644 content/v3/ru/learn/httpcaching.md delete mode 100644 content/v3/ru/learn/overriding.md delete mode 100644 content/v3/ru/learn/redirects.md delete mode 100644 content/v3/ru/learn/stopping.md delete mode 100644 content/v3/ru/learn/troubleshooting.md delete mode 100644 content/v3/ru/learn/variables.md delete mode 100644 content/v3/ru/learn/views.md delete mode 100644 content/v3/uk/awesome-plugins/pdo_wrapper.md delete mode 100644 content/v3/uk/learn.md delete mode 100644 content/v3/uk/learn/api.md delete mode 100644 content/v3/uk/learn/troubleshooting.md delete mode 100644 content/v3/zh/awesome-plugins/index.md delete mode 100644 content/v3/zh/awesome-plugins/pdo_wrapper.md delete mode 100644 content/v3/zh/install.md delete mode 100644 content/v3/zh/learn.md delete mode 100644 content/v3/zh/learn/api.md delete mode 100644 content/v3/zh/learn/errorhandling.md delete mode 100644 content/v3/zh/learn/frameworkinstance.md delete mode 100644 content/v3/zh/learn/frameworkmethods.md delete mode 100644 content/v3/zh/learn/httpcaching.md delete mode 100644 content/v3/zh/learn/overriding.md delete mode 100644 content/v3/zh/learn/redirects.md delete mode 100644 content/v3/zh/learn/stopping.md delete mode 100644 content/v3/zh/learn/troubleshooting.md delete mode 100644 content/v3/zh/learn/variables.md delete mode 100644 content/v3/zh/learn/views.md diff --git a/content/v3/de/awesome-plugins/index.md b/content/v3/de/awesome-plugins/index.md deleted file mode 100644 index ef8a1d41..00000000 --- a/content/v3/de/awesome-plugins/index.md +++ /dev/null @@ -1,40 +0,0 @@ -# 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. - -- [Wruczek/PHP-File-Cache](/awesome-plugins/php-file-cache) - Leichte, einfache und eigenständige PHP-In-File-Caching-Klasse - -## Debugging - -Debugging ist entscheidend, wenn Sie in Ihrer lokalen Umgebung entwickeln. Es gibt einige Plugins, die Ihr Debugging-Erlebnis verbessern können. - -- [tracy/tracy](/awesome-plugins/tracy) - Dies ist ein voll ausgestatteter Fehlerbehandlungsmechanismus, der mit Flight verwendet werden kann. Es verfügt über mehrere Panels, die Ihnen beim Debuggen Ihrer Anwendung helfen können. Es ist auch sehr einfach zu erweitern und eigene Panels hinzuzufügen. -- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Wird mit dem [Tracy](/awesome-plugins/tracy) Fehlerbehandler verwendet, fügt dieses Plugin einige zusätzliche Panels hinzu, die speziell für das Debuggen von Flight-Projekten hilfreich sind. - -## 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. - -- [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Offizieller Flight PDO Wrapper, der zum Kern gehört. Dies ist ein einfacher Wrapper, der den Prozess des Schreibens von Abfragen und deren Ausführung vereinfacht. Es ist kein ORM. -- [flightphp/active-record](/awesome-plugins/active-record) - Offizielles Flight ActiveRecord ORM/Mapper. Tolle kleine Bibliothek zum einfachen Abrufen und Speichern von Daten in Ihrer Datenbank. - -## 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. - -- [Ghostff/Session](/awesome-plugins/session) - PHP-Session-Manager (nicht blockierend, Flash, Segment, Sitzungsverschlüsselung). Verwendet PHP open_ssl für die optionale Verschlüsselung/Entschlüsselung von Sitzungsdaten. - -## 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. - -- [flightphp/core View](/learn#views) - Dies ist eine sehr einfache Templating-Engine, die zum Kern gehört. Es wird nicht empfohlen, sie zu verwenden, wenn Sie mehr als ein paar Seiten in Ihrem Projekt haben. -- [latte/latte](/awesome-plugins/latte) - Latte ist eine voll ausgestattete Templating-Engine, die sehr einfach zu verwenden ist und sich näher an der PHP-Syntax als Twig oder Smarty anfühlt. Es ist auch sehr einfach zu erweitern und eigene Filter und Funktionen hinzuzufügen. - -## Mitwirken - -Haben Sie ein Plugin, das Sie teilen möchten? Senden Sie einen Pull-Request, um es der Liste hinzuzufügen! \ No newline at end of file diff --git a/content/v3/de/awesome-plugins/pdo_wrapper.md b/content/v3/de/awesome-plugins/pdo_wrapper.md deleted file mode 100644 index 72eae648..00000000 --- a/content/v3/de/awesome-plugins/pdo_wrapper.md +++ /dev/null @@ -1,122 +0,0 @@ -# PdoWrapper PDO Helper Klasse - -Flight wird mit einer Hilfsklasse für PDO geliefert. Es ermöglicht Ihnen, Ihre Datenbank leicht abzufragen -mit all dem vorbereiteten / ausführen / fetchAll () Wahnsinn. Es vereinfacht erheblich, wie Sie können -Ihre Datenbank abfragen. Jedes Zeilenergebnis wird als Flight Collection-Klasse zurückgegeben, die -ermöglicht es Ihnen, auf Ihre Daten über Array-Syntax oder Objektsyntax zuzugreifen. - -## Registrieren der PDO Helper Klasse - -```php -// 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, so dass alle normalen PDO-Methoden verfügbar sind. Die folgenden Methoden werden hinzugefügt, um das Abfragen der Datenbank zu erleichtern: - -### `runQuery(string $sql, array $params = []): PDOStatement` -Verwenden Sie dies für INSERTS, UPDATES oder wenn Sie planen, ein SELECT in einer Schleife zu verwenden - -```php -$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 - -```php -$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 - -```php -$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 - -```php -$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 `IN()` Syntax -Hierfür gibt es auch ein hilfreiches 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 dafür, wie das aussehen könnte: - -```php -$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 - -```php -// Beispielroute und wie Sie diesen Wrapper verwenden würden -Flight::route('/benutzer', function () { - // Holen Sie sich alle Benutzer - $users = Flight::db()->fetchAll('SELECT * FROM users'); - - // Streamen Sie alle Benutzer - $statement = Flight::db()->runQuery('SELECT * FROM users'); - while ($user = $statement->fetch()) { - echo $user['name']; - // oder echo $user->name; - } - - // Holen Sie sich einen einzelnen Benutzer - $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); - - // Holen Sie sich einen einzelnen Wert - $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); - - // Besondere IN()-Syntax zur Unterstützung (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']); - - // Fügen Sie einen neuen Benutzer ein - Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']); - $insert_id = Flight::db()->lastInsertId(); - - // Aktualisieren Sie einen Benutzer - Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]); - - // Löschen eines Benutzers - Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]); - - // Abrufen der Anzahl der betroffenen Zeilen - $statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']); - $affected_rows = $statement->rowCount(); - -}); -``` \ No newline at end of file diff --git a/content/v3/de/install.md b/content/v3/de/install.md deleted file mode 100644 index 53def8a9..00000000 --- a/content/v3/de/install.md +++ /dev/null @@ -1,66 +0,0 @@ -# Installation - -## Lade die Dateien herunter. - -Wenn Sie [Composer](https://getcomposer.org) verwenden, können Sie den folgenden Befehl ausführen: - -```bash -composer require flightphp/core -``` - -ODER Sie können die [Dateien herunterladen](https://github.com/flightphp/core/archive/master.zip) - direkt und sie in Ihr Webverzeichnis extrahieren. - -## Konfigurieren Sie Ihren Webserver. - -### Apache -Für Apache bearbeiten Sie Ihre `.htaccess`-Datei wie folgt: - -```apacheconf -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: - -```apacheconf -RewriteEngine On -RewriteRule ^(.*)$ index.php -``` - -### Nginx - -Für Nginx fügen Sie Folgendes zu Ihrer Serverdeklaration hinzu: - -```nginx -server { - location / { - try_files $uri $uri/ /index.php; - } -} -``` - -## Erstellen Sie Ihre `index.php`-Datei. - -```php -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. \ No newline at end of file diff --git a/content/v3/de/learn/httpcaching.md b/content/v3/de/learn/httpcaching.md deleted file mode 100644 index d2175e17..00000000 --- a/content/v3/de/learn/httpcaching.md +++ /dev/null @@ -1,27 +0,0 @@ -# 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. - -```php -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: - -```php -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. \ No newline at end of file diff --git a/content/v3/de/learn/redirects.md b/content/v3/de/learn/redirects.md deleted file mode 100644 index 31ce7f26..00000000 --- a/content/v3/de/learn/redirects.md +++ /dev/null @@ -1,13 +0,0 @@ -# Weiterleitungen - -Sie können die aktuelle Anfrage umleiten, indem Sie die `redirect` Methode verwenden und eine neue URL übergeben: - -```php -Flight::redirect('/neuer/standort'); -``` - -Standardmäßig sendet Flight einen HTTP-Statuscode 303. Sie können optional einen benutzerdefinierten Code setzen: - -```php -Flight::redirect('/neuer/standort', 401); -``` \ No newline at end of file diff --git a/content/v3/de/learn/stopping.md b/content/v3/de/learn/stopping.md deleted file mode 100644 index fb17914e..00000000 --- a/content/v3/de/learn/stopping.md +++ /dev/null @@ -1,19 +0,0 @@ -# Anhalten - -Sie können das Framework jederzeit durch Aufrufen der `halt` Methode stoppen: - -```php -Flight::halt(); -``` - -Sie können auch einen optionalen `HTTP`-Statuscode und eine Nachricht angeben: - -```php -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: - -```php -Flight::stop(); -``` \ No newline at end of file diff --git a/content/v3/de/learn/troubleshooting.md b/content/v3/de/learn/troubleshooting.md deleted file mode 100644 index 2e79ad4e..00000000 --- a/content/v3/de/learn/troubleshooting.md +++ /dev/null @@ -1,64 +0,0 @@ -# Fehlerbehebung - -Diese Seite hilft Ihnen bei der Fehlerbehebung von häufig auftretenden Problemen, auf die Sie bei der Verwendung von Flight stoßen könnten. - -## Häufige Probleme - -### 404 Nicht gefunden oder unerwartetes Routenverhalten - -Wenn Sie einen 404-Nicht gefunden Fehler sehen (aber Sie schwören, dass er wirklich da ist und es sich nicht um einen Tippfehler handelt), könnte dies tatsächlich ein Problem sein, wenn Sie einen Wert in Ihrem Routen-Endpunkt zurückgeben, anstatt ihn einfach auszugeben. Der Grund dafür ist beabsichtigt, könnte aber einige Entwickler überraschen. - -```php -Flight::route('/hallo', function(){ - // Dies könnte einen 404 Nicht gefunden Fehler verursachen - return 'Hallo Welt'; -}); - -// Was Sie wahrscheinlich wollen -Flight::route('/hallo', function(){ - echo 'Hallo Welt'; -}); -``` - -Der Grund dafür liegt in einem speziellen Mechanismus, der in den Router eingebaut ist und die Rückgabewerte als Anweisung für "zur nächsten Route gehen" behandelt. Das Verhalten ist im [Routing](/learn/routing#passing) Abschnitt dokumentiert. - -### Klasse nicht gefunden (Autoloading funktioniert nicht) - -Dafür könnte es einige Gründe geben, warum dies nicht passiert. Unten sind einige Beispiele aufgeführt, aber stellen Sie sicher, dass Sie auch den [Autoloading](/learn/autoloading) Abschnitt überprüfen. - -#### Falscher Dateiname -Am häufigsten ist, dass der Klassenname nicht mit dem Dateinamen übereinstimmt. - -Wenn Sie eine Klasse namens `MeineKlasse` haben, sollte die Datei `MeineKlasse.php` genannt werden. Wenn Sie eine Klasse namens `MeineKlasse` haben und die Datei `meineklasse.php` genannt wird, kann der Autoloader sie nicht finden. - -#### Falscher Namespace -Wenn Sie Namespaces verwenden, sollte der Namespace mit der Verzeichnisstruktur übereinstimmen. - -```php -// Code - -// Wenn Ihr MyController im app/controllers Verzeichnis ist und benannt ist -// dann funktioniert dies nicht. -Flight::route('/hallo', 'MeinController->hallo'); - -// Sie müssen eine dieser Optionen auswählen -Flight::route('/hallo', 'app\controllers\MeinController->hallo'); -// oder wenn Sie eine Verwendungserklärung oben haben - -use app\controllers\MeinController; - -Flight::route('/hallo', [ MeinController::class, 'hallo' ]); -// kann auch geschrieben werden -Flight::route('/hallo', MeinController::class.'->hallo'); -// auch... -Flight::route('/hallo', [ 'app\controllers\MeinController', 'hallo' ]); -``` - -#### `path()` nicht definiert - -Im Skelett-App ist dies im `config.php` File definiert, aber damit Ihre Klassen gefunden werden, müssen Sie sicherstellen, dass die `path()` Methode definiert ist (wahrscheinlich zum Stammverzeichnis Ihres Verzeichnisses), bevor Sie versuchen, sie zu verwenden. - -```php -// Fügen Sie einen Pfad zum Autoloader hinzu -Flight::path(__DIR__.'/../'); -``` \ No newline at end of file diff --git a/content/v3/de/learn/variables.md b/content/v3/de/learn/variables.md deleted file mode 100644 index ee7ba9c1..00000000 --- a/content/v3/de/learn/variables.md +++ /dev/null @@ -1,35 +0,0 @@ -# Variablen - -Flight ermöglicht es Ihnen, Variablen zu speichern, damit sie überall in Ihrer Anwendung verwendet werden können. - -```php -// 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: - -```php -if (Flight::has('id')) { - // Mach etwas -} -``` - -Sie können eine Variable löschen, indem Sie Folgendes tun: - -```php -// Löscht die id-Variable -Flight::clear('id'); - -// Löscht alle Variablen -Flight::clear(); -``` - -Flight verwendet auch Variablen für Konfigurationszwecke. - -```php -Flight::set('flight.log_errors', true); -``` \ No newline at end of file diff --git a/content/v3/de/learn/views.md b/content/v3/de/learn/views.md deleted file mode 100644 index 3902c276..00000000 --- a/content/v3/de/learn/views.md +++ /dev/null @@ -1,128 +0,0 @@ -# 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: - -```php -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: - -```php -Hallo, ! -``` - -Die Ausgabe wäre: - -``` -Hallo, Bob! -``` - -Sie können auch manuell Ansichtsvariablen festlegen, indem Sie die Methode `set` verwenden: - -```php -Flight::view()->set('name', 'Bob'); -``` - -Die Variable `name` ist nun in allen Ihren Ansichten verfügbar. Sie können also einfach Folgendes tun: - -```php -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: - -```php -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. - -```php -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: - -```php -Flight::render('layout', ['title' => 'Startseite']); -``` - -Wenn die Template-Dateien wie folgt aussehen: - -`header.php`: - -```php -

-``` - -`body.php`: - -```php -
-``` - -`layout.php`: - -```php - - - <?= $title ?> - - - - - - -``` - -Die Ausgabe wäre: -```html - - - Startseite - - -

Hallo

-
Welt
- - -``` - -## 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](http://www.smarty.net/) Template-Engine für Ihre Ansichten: - -```php -// 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: - -```php -Flight::map('render', function(string $template, array $data): void { - Flight::view()->assign($data); - Flight::view()->display($template); -}); -``` \ No newline at end of file diff --git a/content/v3/es/awesome-plugins/index.md b/content/v3/es/awesome-plugins/index.md deleted file mode 100644 index bffdb1c6..00000000 --- a/content/v3/es/awesome-plugins/index.md +++ /dev/null @@ -1,40 +0,0 @@ -# Increíbles complementos - -Flight es increíblemente extensible. Hay varios complementos que se pueden utilizar para añadir funcionalidad a tu aplicación Flight. Algunos son oficialmente compatibles con el Equipo de Flight y otros son bibliotecas micro/lite para ayudarte a comenzar. - -## Caché - -La caché es una excelente manera de acelerar tu aplicación. Hay varias bibliotecas de caché que se pueden utilizar con Flight. - -- [Wruczek/PHP-File-Cache](/increibles-complementos/php-file-cache) - Clase de caché en archivo PHP ligera, simple y autónoma - -## Depuración - -La depuración es crucial cuando estás desarrollando en tu entorno local. Hay algunos complementos que pueden mejorar tu experiencia de depuración. - -- [tracy/tracy](/increibles-complementos/tracy) - Este es un manejador de errores con todas las funciones que se puede utilizar con Flight. Tiene varios paneles que pueden ayudarte a depurar tu aplicación. También es muy fácil de ampliar y agregar tus propios paneles. -- [flightphp/tracy-extensions](/increibles-complementos/tracy-extensions) - Utilizado con el manejador de errores [Tracy](/increibles-complementos/tracy), este complemento añade algunos paneles adicionales para ayudar con la depuración específicamente para proyectos de Flight. - -## Bases de datos - -Las bases de datos son el núcleo de la mayoría de las aplicaciones. Así es como almacenas y recuperas datos. Algunas bibliotecas de bases de datos son simplemente envoltorios para escribir consultas y otras son ORM completos. - -- [flightphp/core PdoWrapper](/increibles-complementos/pdo-wrapper) - Envoltorio oficial Flight PDO que forma parte del núcleo. Este es un envoltorio simple para ayudar a simplificar el proceso de escribir y ejecutar consultas. No es un ORM. -- [flightphp/active-record](/increibles-complementos/active-record) - ORM/Mapper oficial de Flight ActiveRecord. Excelente pequeña biblioteca para recuperar y almacenar datos fácilmente en tu base de datos. - -## Sesión - -Las sesiones no son realmente útiles para las API, pero para desarrollar una aplicación web, las sesiones pueden ser cruciales para mantener el estado e información de inicio de sesión. - -- [Ghostff/Session](/increibles-complementos/session) - Administrador de sesiones de PHP (no bloqueante, flash, segmento, cifrado de sesiones). Utiliza PHP open_ssl para cifrar/descifrar opcionalmente los datos de sesión. - -## Plantillas - -Las plantillas son esenciales para cualquier aplicación web con un UI. Hay varios motores de plantillas que se pueden utilizar con Flight. - -- [flightphp/core View](/learn#views) - Este es un motor de plantillas muy básico que forma parte del núcleo. No se recomienda su uso si tienes más de un par de páginas en tu proyecto. -- [latte/latte](/increibles-complementos/latte) - Latte es un motor de plantillas completo que es muy fácil de usar y se siente más cercano a una sintaxis PHP que Twig o Smarty. También es muy fácil de ampliar y agregar tus propios filtros y funciones. - -## Contribuir - -¿Tienes un complemento que te gustaría compartir? ¡Envía una solicitud de extracción para añadirlo a la lista! \ No newline at end of file diff --git a/content/v3/es/awesome-plugins/pdo_wrapper.md b/content/v3/es/awesome-plugins/pdo_wrapper.md deleted file mode 100644 index 87dc5f5a..00000000 --- a/content/v3/es/awesome-plugins/pdo_wrapper.md +++ /dev/null @@ -1,122 +0,0 @@ -# Clase de ayuda PdoWrapper PDO - -Flight viene con una clase de ayuda para PDO. Le permite consultar fácilmente su base de datos -con toda la locura de preparar/ejecutar/obtenerTodo(). Simplifica en gran medida cómo puede -consultar su base de datos. Cada resultado de fila se devuelve como una clase Flight Collection -que le permite acceder a sus datos mediante la sintaxis de matriz o la sintaxis de objeto. - -## Registrando la Clase de Ayuda PDO - -```php -// Registrar la clase de ayuda PDO -Flight::register('db', \flight\database\PdoWrapper::class, ['mysql:host=localhost;dbname=cool_db_name', 'usuario', 'contraseña', [ - 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 - ] -]); -``` - -## Uso -Este objeto extiende PDO, por lo que todos los métodos normales de PDO están disponibles. Los siguientes métodos se agregan para facilitar la consulta a la base de datos: - -### `runQuery(string $sql, array $params = []): PDOStatement` -Úselo para INSERTS, UPDATES o si planea usar un SELECT en un bucle while - -```php -$db = Flight::db(); -$statement = $db->runQuery("SELECT * FROM table WHERE something = ?", [ $algo ]); -while($row = $statement->fetch()) { - // ... -} - -// O escribir en la base de datos -$db->runQuery("INSERT INTO table (nombre) VALUES (?)", [ $nombre ]); -$db->runQuery("UPDATE table SET nombre = ? WHERE id = ?", [ $nombre, $id ]); -``` - -### `fetchField(string $sql, array $params = []): mixed` -Extrae el primer campo de la consulta - -```php -$db = Flight::db(); -$count = $db->fetchField("SELECT COUNT(*) FROM table WHERE something = ?", [ $algo ]); -``` - -### `fetchRow(string $sql, array $params = []): array` -Extrae una fila de la consulta - -```php -$db = Flight::db(); -$row = $db->fetchRow("SELECT id, nombre FROM table WHERE id = ?", [ $id ]); -echo $row['nombre']; -// o -echo $row->nombre; -``` - -### `fetchAll(string $sql, array $params = []): array` -Extrae todas las filas de la consulta - -```php -$db = Flight::db(); -$rows = $db->fetchAll("SELECT id, nombre FROM table WHERE something = ?", [ $algo ]); -foreach($rows as $row) { - echo $row['nombre']; - // o - echo $row->nombre; -} -``` - -## Nota para la sintaxis de `IN()` -Esto también tiene un envoltorio útil para las declaraciones `IN()`. Simplemente puede pasar un signo de interrogación como marcador de posición para `IN()` y luego un array de valores. Aquí hay un ejemplo de cómo podría verse eso: - -```php -$db = Flight::db(); -$nombre = 'Bob'; -$ids_compañía = [1,2,3,4,5]; -$rows = $db->fetchAll("SELECT id, nombre FROM table WHERE nombre = ? AND company_id IN (?)", [ $nombre, $ids_compañía ]); -``` - -## Ejemplo Completo - -```php -// Ruta de ejemplo y cómo usar este envoltorio -Flight::route('/usuarios', function () { - // Obtener todos los usuarios - $usuarios = Flight::db()->fetchAll('SELECT * FROM users'); - - // Transmitir todos los usuarios - $declaración = Flight::db()->runQuery('SELECT * FROM users'); - while ($usuario = $declaración->fetch()) { - echo $usuario['nombre']; - // o echo $usuario->nombre; - } - - // Obtener un usuario único - $usuario = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); - - // Obtener un valor único - $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); - - // Sintaxis especial de IN() para ayudar (asegúrese de que IN esté en mayúsculas) - $usuarios = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); - // también se podría hacer esto - $usuarios = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [ '1,2,3,4,5']); - - // Insertar un nuevo usuario - Flight::db()->runQuery("INSERT INTO users (nombre, email) VALUES (?, ?)", ['Bob', 'bob@example.com']); - $id_insertado = Flight::db()->lastInsertId(); - - // Actualizar un usuario - Flight::db()->runQuery("UPDATE users SET nombre = ? WHERE id = ?", ['Bob', 123]); - - // Eliminar un usuario - Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]); - - // Obtener el número de filas afectadas - $declaración = Flight::db()->runQuery("UPDATE users SET nombre = ? WHERE nombre = ?", ['Bob', 'Sally']); - $filas_afectadas = $declaración->rowCount(); - -}); -``` \ No newline at end of file diff --git a/content/v3/es/install.md b/content/v3/es/install.md deleted file mode 100644 index 469b73b3..00000000 --- a/content/v3/es/install.md +++ /dev/null @@ -1,66 +0,0 @@ -# Instalación - -## Descargar los archivos. - -Si estás utilizando [Composer](https://getcomposer.org), puedes ejecutar el siguiente comando: - -```bash -composer require flightphp/core -``` - -O puedes [descargar los archivos](https://github.com/flightphp/core/archive/master.zip) - directamente y extraerlos en tu directorio web. - -## Configurar tu Servidor Web. - -### Apache -Para Apache, edita tu archivo `.htaccess` con lo siguiente: - -```apacheconf -RewriteEngine On -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule ^(.*)$ index.php [QSA,L] -``` - -> **Nota**: Si necesitas usar flight en un subdirectorio, añade la línea -> `RewriteBase /subdir/` justo después de `RewriteEngine On`. - -> **Nota**: Si deseas proteger todos los archivos del servidor, como un archivo de base de datos o env. -> Agrega esto en tu archivo `.htaccess`: - -```apacheconf -RewriteEngine On -RewriteRule ^(.*)$ index.php -``` - -### Nginx - -Para Nginx, agrega lo siguiente a la declaración de tu servidor: - -```nginx -server { - location / { - try_files $uri $uri/ /index.php; - } -} -``` - -## Crea tu archivo `index.php`. - -```php -getTraceAsString(); -}); -``` - -Por defecto, los errores no se registran en el servidor web. Puede habilitar esto cambiando la configuración: - -```php -Flight::set('flight.log_errors', true); -``` - -## No Encontrado - -Cuando una URL no se puede encontrar, Flight llama al método `notFound`. El comportamiento predeterminado es enviar una respuesta de `HTTP 404 Not Found` con un mensaje simple. - -Puede anular este comportamiento según sus necesidades: - -```php -Flight::map('notFound', function () { - // Manejar no encontrado -}); -``` \ No newline at end of file diff --git a/content/v3/es/learn/frameworkinstance.md b/content/v3/es/learn/frameworkinstance.md deleted file mode 100644 index c28cc1a9..00000000 --- a/content/v3/es/learn/frameworkinstance.md +++ /dev/null @@ -1,19 +0,0 @@ -# Instancia del Framework - -En lugar de ejecutar Flight como una clase estática global, puedes opcionalmente ejecutarlo -como una instancia de objeto. - -```php -require 'flight/autoload.php'; - -$app = Flight::app(); - -$app->route('/', function () { - echo '¡hola mundo!'; -}); - -$app->start(); -``` - -Así que en lugar de llamar al método estático, llamarías al método de instancia con -el mismo nombre en el objeto Engine. \ No newline at end of file diff --git a/content/v3/es/learn/frameworkmethods.md b/content/v3/es/learn/frameworkmethods.md deleted file mode 100644 index 9ca07b58..00000000 --- a/content/v3/es/learn/frameworkmethods.md +++ /dev/null @@ -1,42 +0,0 @@ -# Métodos del Framework - -Flight está diseñado para ser fácil de usar y entender. Lo siguiente es el conjunto completo -de métodos para el framework. Consiste en métodos centrales, que son métodos estáticos regulares, -y métodos extensibles, que son métodos asignados que pueden ser filtrados -o anulados. - -## Métodos Centrales - -```php -Flight::map(string $nombre, callable $retorno, bool $pasar_ruta = false) // Crea un método personalizado para el framework. -Flight::register(string $nombre, string $clase, array $params = [], ?callable $retorno = null) // Registra una clase a un método del framework. -Flight::before(string $nombre, callable $retorno) // Agrega un filtro antes de un método del framework. -Flight::after(string $nombre, callable $retorno) // Agrega un filtro después de un método del framework. -Flight::path(string $ruta) // Agrega una ruta para la carga automática de clases. -Flight::get(string $clave) // Obtiene una variable. -Flight::set(string $clave, mixed $valor) // Establece una variable. -Flight::has(string $clave) // Verifica si una variable está establecida. -Flight::clear(array|string $clave = []) // Borra una variable. -Flight::init() // Inicializa el framework a sus ajustes predeterminados. -Flight::app() // Obtiene la instancia del objeto de la aplicación -``` - -## Métodos Extensibles - -```php -Flight::start() // Inicia el framework. -Flight::stop() // Detiene el framework y envía una respuesta. -Flight::halt(int $codigo = 200, string $mensaje = '') // Detiene el framework con un código de estado opcional y mensaje. -Flight::route(string $patrón, callable $retorno, bool $pasar_ruta = false) // Asigna un patrón de URL a un retorno. -Flight::group(string $patrón, callable $retorno) // Crea agrupaciones para URLs, el patrón debe ser una cadena. -Flight::redirect(string $url, int $codigo) // Redirige a otra URL. -Flight::render(string $archivo, array $datos, ?string $clave = null) // Renderiza un archivo de plantilla. -Flight::error(Throwable $error) // Envía una respuesta HTTP 500. -Flight::notFound() // Envía una respuesta HTTP 404. -Flight::etag(string $id, string $tipo = 'string') // Realiza almacenamiento en caché HTTP ETag. -Flight::lastModified(int $tiempo) // Realiza almacenamiento en caché HTTP de Última Modificación. -Flight::json(mixed $datos, int $codigo = 200, bool $codificar = true, string $charset = 'utf8', int $opción) // Envía una respuesta JSON. -Flight::jsonp(mixed $datos, string $parametro = 'jsonp', int $codigo = 200, bool $codificar = true, string $charset = 'utf8', int $opción) // Envía una respuesta JSONP. -``` - -Cualquier método personalizado añadido con `map` y `register` también puede ser filtrado. \ No newline at end of file diff --git a/content/v3/es/learn/httpcaching.md b/content/v3/es/learn/httpcaching.md deleted file mode 100644 index 9978c7c5..00000000 --- a/content/v3/es/learn/httpcaching.md +++ /dev/null @@ -1,27 +0,0 @@ -# Caché HTTP - -Flight proporciona soporte incorporado para el almacenamiento en caché a nivel HTTP. Si se cumple la condición de caché, Flight devolverá una respuesta HTTP `304 No modificado`. La próxima vez que el cliente solicite el mismo recurso, se le pedirá que utilice su versión en caché local. - -## Última modificación - -Puedes utilizar el método `lastModified` y pasar un sello de tiempo UNIX para establecer la fecha y hora en que se modificó por última vez una página. El cliente seguirá utilizando su caché hasta que se cambie el valor de última modificación. - -```php -Flight::route('/noticias', function () { - Flight::lastModified(1234567890); - echo 'Este contenido se almacenará en caché.'; -}); -``` - -## ETag - -La caché `ETag` es similar a `Última modificación`, excepto que puedes especificar cualquier identificación que desees para el recurso: - -```php -Flight::route('/noticias', function () { - Flight::etag('mi-identificador-único'); - echo 'Este contenido se almacenará en caché.'; -}); -``` - -Ten en cuenta que llamar a `lastModified` o `etag` establecerá y comprobará el valor de caché. Si el valor de caché es el mismo entre las solicitudes, Flight enviará inmediatamente una respuesta `HTTP 304` y detendrá el procesamiento. \ No newline at end of file diff --git a/content/v3/es/learn/overriding.md b/content/v3/es/learn/overriding.md deleted file mode 100644 index 19d3e391..00000000 --- a/content/v3/es/learn/overriding.md +++ /dev/null @@ -1,29 +0,0 @@ -# Anulando - -Flight te permite anular su funcionalidad predeterminada para adaptarla a tus propias necesidades, -sin necesidad de modificar ningún código. - -Por ejemplo, cuando Flight no puede encontrar una URL que coincida con una ruta, invoca el método `notFound` -que envía una respuesta genérica de `HTTP 404`. Puedes anular este comportamiento -utilizando el método `map`: - -```php -Flight::map('notFound', function() { - // Mostrar página de error 404 personalizada - include 'errors/404.html'; -}); -``` - -Flight también te permite reemplazar componentes principales del framework. -Por ejemplo, puedes reemplazar la clase Router predeterminada con tu propia clase personalizada: - -```php -// Registra tu clase personalizada -Flight::register('router', MyRouter::class); - -// Cuando Flight carga la instancia del enrutador, cargará tu clase -$myrouter = Flight::router(); -``` - -Sin embargo, los métodos del framework como `map` y `register` no se pueden anular. -Obtendrás un error si intentas hacerlo. \ No newline at end of file diff --git a/content/v3/es/learn/redirects.md b/content/v3/es/learn/redirects.md deleted file mode 100644 index ea06814f..00000000 --- a/content/v3/es/learn/redirects.md +++ /dev/null @@ -1,15 +0,0 @@ -# Redirecciones - -Puedes redirigir la solicitud actual utilizando el método `redirect` y pasando -una nueva URL: - -```php -Flight::redirect('/nueva/ubicacion'); -``` - -Por defecto, Flight envía un código de estado HTTP 303. Opcionalmente, puedes establecer un -código personalizado: - -```php -Flight::redirect('/nueva/ubicacion', 401); -``` \ No newline at end of file diff --git a/content/v3/es/learn/stopping.md b/content/v3/es/learn/stopping.md deleted file mode 100644 index 3b354440..00000000 --- a/content/v3/es/learn/stopping.md +++ /dev/null @@ -1,20 +0,0 @@ -# Detener - -Puedes detener el marco de trabajo en cualquier momento llamando al método `halt`: - -```php -Flight::halt(); -``` - -También puedes especificar un código de estado `HTTP` opcional y un mensaje: - -```php -Flight::halt(200, 'Vuelvo enseguida...'); -``` - -Llamar a `halt` descartará cualquier contenido de respuesta hasta ese punto. Si deseas detener -el marco de trabajo y generar la respuesta actual, utiliza el método `stop`: - -```php -Flight::stop(); -``` \ No newline at end of file diff --git a/content/v3/es/learn/troubleshooting.md b/content/v3/es/learn/troubleshooting.md deleted file mode 100644 index 0c611871..00000000 --- a/content/v3/es/learn/troubleshooting.md +++ /dev/null @@ -1,72 +0,0 @@ -# Resolución de Problemas - -Esta página te ayudará a solucionar problemas comunes que puedes encontrar al usar Flight. - -## Problemas Comunes - -### 404 No Encontrado o Comportamiento de Ruta Inesperado - -Si ves un error 404 No Encontrado (pero juras por tu vida que realmente está ahí y no es un error tipográfico) esto realmente podría ser un problema con -que estás devolviendo un valor en el punto final de tu ruta en lugar de simplemente hacer un eco. La razón de esto es intencional pero podría sorprender a algunos desarrolladores. - -```php - -Flight::route('/hello', function(){ - // Esto podría causar un error 404 No Encontrado - return '¡Hola Mundo!'; -}); - -// Lo que probablemente deseas -Flight::route('/hello', function(){ - echo '¡Hola Mundo!'; -}); - -``` - -La razón de esto es debido a un mecanismo especial incorporado en el enrutador que maneja la salida de retorno como un solo "ir a la siguiente ruta". -Puedes ver el comportamiento documentado en la sección [Enrutamiento](/learn/routing#passing). - -### Clase No Encontrada (la carga automática no funciona) - -Podría haber un par de razones por las que esto no está sucediendo. A continuación se muestran algunos ejemplos, pero asegúrate de revisar también la sección de [carga automática](/learn/autoloading). - -#### Nombre de Archivo Incorrecto -Lo más común es que el nombre de la clase no coincida con el nombre del archivo. - -Si tienes una clase llamada `MiClase` entonces el archivo debería llamarse `MiClase.php`. Si tienes una clase llamada `MiClase` y el archivo se llama `miclase.php` -entonces el cargador automático no podrá encontrarlo. - -#### Namespace Incorrecto -Si estás utilizando espacios de nombres (namespaces), entonces el namespace debe coincidir con la estructura de directorios. - -```php -// código - -// si tu MyController está en el directorio app/controllers y tiene un espacio de nombres -// esto no funcionará. -Flight::route('/hello', 'MyController->hello'); - -// deberías elegir una de estas opciones -Flight::route('/hello', 'app\controllers\MiControlador->hello'); -// o si tienes una declaración use arriba - -use app\controllers\MiControlador; - -Flight::route('/hello', [ MiControlador::class, 'hello' ]); -// también puede escribirse -Flight::route('/hello', MiControlador::class.'->hello'); -// también... -Flight::route('/hello', [ 'app\controllers\MiControlador', 'hello' ]); -``` - -#### `path()` no definido - -En la aplicación esquelética, esto está definido dentro del archivo `config.php`, pero para que tus clases se encuentren, debes asegurarte de que el método `path()` -esté definido (probablemente en la raíz de tu directorio) antes de intentar usarlo. - -```php - -// Agregar una ruta al cargador automático -Flight::path(__DIR__.'/../'); - -``` \ No newline at end of file diff --git a/content/v3/es/learn/variables.md b/content/v3/es/learn/variables.md deleted file mode 100644 index 1648c6c7..00000000 --- a/content/v3/es/learn/variables.md +++ /dev/null @@ -1,35 +0,0 @@ -# Variables - -Flight permite guardar variables para que puedan ser utilizadas en cualquier lugar de tu aplicación. - -```php -// Guarda tu variable -Flight::set('id', 123); - -// En otro lugar de tu aplicación -$id = Flight::get('id'); -``` - -Para verificar si una variable ha sido establecida, puedes hacer lo siguiente: - -```php -if (Flight::has('id')) { - // Haz algo -} -``` - -Puedes limpiar una variable haciendo: - -```php -// Elimina la variable id -Flight::clear('id'); - -// Elimina todas las variables -Flight::clear(); -``` - -Flight también utiliza variables con propósitos de configuración. - -```php -Flight::set('flight.log_errors', true); -``` \ No newline at end of file diff --git a/content/v3/es/learn/views.md b/content/v3/es/learn/views.md deleted file mode 100644 index 9f818e54..00000000 --- a/content/v3/es/learn/views.md +++ /dev/null @@ -1,128 +0,0 @@ -# Vistas - -Flight proporciona algunas funcionalidades básicas de plantillas de forma predeterminada. Para mostrar una vista de plantilla llame al método `render` con el nombre del archivo de plantilla y datos de plantilla opcionales: - -```php -Flight::render('hello.php', ['name' => 'Bob']); -``` - -Los datos de plantilla que pase se inyectan automáticamente en la plantilla y se pueden hacer referencia como una variable local. Los archivos de plantilla son simplemente archivos PHP. Si el contenido del archivo de plantilla `hello.php` es: - -```php -¡Hola, ! -``` - -La salida sería: - -``` -¡Hola, Bob! -``` - -También puede configurar manualmente variables de vista utilizando el método `set`: - -```php -Flight::view()->set('name', 'Bob'); -``` - -La variable `name` ahora está disponible en todas sus vistas. Entonces simplemente puede hacer: - -```php -Flight::render('hello'); -``` - -Tenga en cuenta que al especificar el nombre de la plantilla en el método render, puede omitir la extensión `.php`. - -Por defecto, Flight buscará un directorio `views` para los archivos de plantilla. Puede establecer una ruta alternativa para sus plantillas configurando lo siguiente: - -```php -Flight::set('flight.views.path', '/ruta/a/vistas'); -``` - -## Diseños - -Es común que los sitios web tengan un solo archivo de plantilla de diseño con contenido intercambiable. Para renderizar contenido que se utilizará en un diseño, puede pasar un parámetro opcional al método `render`. - -```php -Flight::render('header', ['heading' => 'Hola'], 'headerContent'); -Flight::render('body', ['body' => 'Mundo'], 'bodyContent'); -``` - -Su vista tendrá variables guardadas llamadas `headerContent` y `bodyContent`. Luego puede renderizar su diseño haciendo: - -```php -Flight::render('layout', ['title' => 'Página de inicio']); -``` - -Si los archivos de plantilla se ven así: - -`header.php`: - -```php -

-``` - -`body.php`: - -```php -
-``` - -`layout.php`: - -```php - - - <?= $title ?> - - - - - - -``` - -La salida sería: -```html - - - Página de inicio - - -

Hola

-
Mundo
- - -``` - -## Vistas Personalizadas - -Flight le permite cambiar el motor de vista predeterminado simplemente registrando su propia clase de vista. Así es como utilizaría el [Smarty](http://www.smarty.net/) motor de plantillas para sus vistas: - -```php -// Cargar biblioteca Smarty -require './Smarty/libs/Smarty.class.php'; - -// Registrar Smarty como clase de vista -// También pase una función de devolución de llamada para configurar Smarty al cargar -Flight::register('view', Smarty::class, [], function (Smarty $smarty) { - $smarty->setTemplateDir('./templates/'); - $smarty->setCompileDir('./templates_c/'); - $smarty->setConfigDir('./config/'); - $smarty->setCacheDir('./cache/'); -}); - -// Asignar datos de la plantilla -Flight::view()->assign('name', 'Bob'); - -// Mostrar la plantilla -Flight::view()->display('hello.tpl'); -``` - -Por completitud, también debería anular el método de renderizado predeterminado de Flight: - -```php -Flight::map('render', function(string $template, array $data): void { - Flight::view()->assign($data); - Flight::view()->display($template); -}); -``` \ No newline at end of file diff --git a/content/v3/fr/awesome-plugins/index.md b/content/v3/fr/awesome-plugins/index.md deleted file mode 100644 index f6a76c19..00000000 --- a/content/v3/fr/awesome-plugins/index.md +++ /dev/null @@ -1,40 +0,0 @@ -# Super plugins - -Flight est incroyablement extensible. Il existe un certain nombre de plugins qui peuvent être utilisés pour ajouter des fonctionnalités à votre application Flight. Certains sont officiellement pris en charge par l'équipe Flight et d'autres sont des bibliothèques micro/lite pour vous aider à démarrer. - -## Mise en cache - -La mise en cache est un excellent moyen d'accélérer votre application. Il existe un certain nombre de bibliothèques de mise en cache qui peuvent être utilisées avec Flight. - -- [Wruczek/PHP-File-Cache](/awesome-plugins/php-file-cache) - Classe de mise en cache PHP légère, simple et autonome - -## Débogage - -Le débogage est crucial lorsque vous développez dans votre environnement local. Il existe quelques plugins qui peuvent améliorer votre expérience de débogage. - -- [tracy/tracy](/awesome-plugins/tracy) - Il s'agit d'un gestionnaire d'erreurs complet qui peut être utilisé avec Flight. Il dispose de plusieurs panneaux qui peuvent vous aider à déboguer votre application. Il est également très facile à étendre et à ajouter vos propres panneaux. -- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Utilisé avec le gestionnaire d'erreurs [Tracy](/awesome-plugins/tracy), ce plugin ajoute quelques panneaux supplémentaires pour aider au débogage spécifiquement pour les projets Flight. - -## Bases de données - -Les bases de données sont essentielles pour la plupart des applications. C'est ainsi que vous stockez et récupérez des données. Certaines bibliothèques de bases de données ne sont que des enveloppes pour écrire des requêtes et d'autres sont des ORM complets. - -- [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Wrapper PDO Flight officiel faisant partie du noyau. Il s'agit d'une enveloppe simple pour simplifier le processus d'écriture de requêtes et de les exécuter. Ce n'est pas un ORM. -- [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord Flight officiel. Excellente petite bibliothèque pour récupérer et stocker facilement des données dans votre base de données. - -## Session - -Les sessions ne sont pas vraiment utiles pour les API mais pour le développement d'une application web, les sessions peuvent être cruciales pour maintenir l'état et les informations de connexion. - -- [Ghostff/Session](/awesome-plugins/session) - Gestionnaire de sessions PHP (non bloquant, flash, segment, chiffrement de session). Utilise PHP open_ssl pour le chiffrement/déchiffrement facultatif des données de session. - -## Modèles - -Les modèles sont essentiels pour toute application web avec une interface utilisateur. Il existe un certain nombre de moteurs de modèles qui peuvent être utilisés avec Flight. - -- [flightphp/core View](/learn#views) - Il s'agit d'un moteur de modèles très basique faisant partie du noyau. Il n'est pas recommandé de l'utiliser si vous avez plus de quelques pages dans votre projet. -- [latte/latte](/awesome-plugins/latte) - Latte est un moteur de modèles complet et très facile à utiliser qui se rapproche plus d'une syntaxe PHP que Twig ou Smarty. Il est également très facile à étendre et à ajouter vos propres filtres et fonctions. - -## Contribution - -Vous avez un plugin que vous aimeriez partager? Soumettez une pull request pour l'ajouter à la liste! \ No newline at end of file diff --git a/content/v3/fr/awesome-plugins/pdo_wrapper.md b/content/v3/fr/awesome-plugins/pdo_wrapper.md deleted file mode 100644 index 8090edf3..00000000 --- a/content/v3/fr/awesome-plugins/pdo_wrapper.md +++ /dev/null @@ -1,119 +0,0 @@ -# Classe d'aide PdoWrapper PDO - -Flight est livré avec une classe d'aide pour PDO. Il vous permet d'interroger facilement votre base de données avec toute la bizarrerie préparée/execute/fetchAll(). Cela simplifie grandement la façon dont vous pouvez interroger votre base de données. Chaque résultat de ligne est renvoyé sous forme de classe Collection de Flight qui vous permet d'accéder à vos données via une syntaxe de tableau ou une syntaxe d'objet. - -## Enregistrer la classe d'aide PDO - -```php -// Enregistrer la classe d'aide PDO -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 - ] -]); -``` - -## Utilisation -Cet objet étend PDO, donc toutes les méthodes normales de PDO sont disponibles. Les méthodes suivantes sont ajoutées pour faciliter l'interrogation de la base de données : - -### `runQuery(string $sql, array $params = []): PDOStatement` -Utilisez ceci pour les INSERT, les UPDATES, ou si vous envisagez d'utiliser un SELECT dans une boucle while - -```php -$db = Flight::db(); -$statement = $db->runQuery("SELECT * FROM table WHERE something = ?", [ $something ]); -while($row = $statement->fetch()) { - // ... -} - -// Ou pour écrire dans la base de données -$db->runQuery("INSERT INTO table (name) VALUES (?)", [ $name ]); -$db->runQuery("UPDATE table SET name = ? WHERE id = ?", [ $name, $id ]); -``` - -### `fetchField(string $sql, array $params = []): mixed` -Extraie le premier champ de la requête - -```php -$db = Flight::db(); -$count = $db->fetchField("SELECT COUNT(*) FROM table WHERE something = ?", [ $something ]); -``` - -### `fetchRow(string $sql, array $params = []): array` -Récupère une ligne de la requête - -```php -$db = Flight::db(); -$row = $db->fetchRow("SELECT id, name FROM table WHERE id = ?", [ $id ]); -echo $row['name']; -// or -echo $row->name; -``` - -### `fetchAll(string $sql, array $params = []): array` -Récupère toutes les lignes de la requête - -```php -$db = Flight::db(); -$rows = $db->fetchAll("SELECT id, name FROM table WHERE something = ?", [ $something ]); -foreach($rows as $row) { - echo $row['name']; - // or - echo $row->name; -} -``` - -## Remarque avec la syntaxe `IN()` -Il existe également un wrapper utile pour les déclarations `IN()`. Vous pouvez simplement passer un point d'interrogation unique en guise de paramètre pour `IN()` puis un tableau de valeurs. Voici un exemple de ce à quoi cela pourrait ressembler : - -```php -$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 ]); -``` - -## Exemple complet - -```php -// Exemple de route et comment vous utiliseriez ce wrapper -Flight::route('/utilisateurs', function () { - // Obtenir tous les utilisateurs - $users = Flight::db()->fetchAll('SELECT * FROM users'); - - // Diffuser tous les utilisateurs - $statement = Flight::db()->runQuery('SELECT * FROM users'); - while ($user = $statement->fetch()) { - echo $user['name']; - // ou echo $user->name; - } - - // Obtenir un seul utilisateur - $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); - - // Obtenir une seule valeur - $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); - - // Syntaxe spéciale IN() pour aider (assurez-vous que IN est en majuscules) - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); - // vous pourriez aussi faire ceci - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [ '1,2,3,4,5']); - - // Insérer un nouvel utilisateur - Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']); - $insert_id = Flight::db()->lastInsertId(); - - // Mettre à jour un utilisateur - Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]); - - // Supprimer un utilisateur - Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]); - - // Obtenir le nombre de lignes affectées - $statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']); - $affected_rows = $statement->rowCount(); - -}); -``` \ No newline at end of file diff --git a/content/v3/fr/install.md b/content/v3/fr/install.md deleted file mode 100644 index aa1fc4e5..00000000 --- a/content/v3/fr/install.md +++ /dev/null @@ -1,65 +0,0 @@ -# Installation - -## Téléchargement des fichiers. - -Si vous utilisez [Composer](https://getcomposer.org), vous pouvez exécuter la commande suivante : - -```bash -composer require flightphp/core -``` - -OU vous pouvez [télécharger les fichiers](https://github.com/flightphp/core/archive/master.zip) directement et les extraire vers votre répertoire web. - -## Configuration de votre serveur Web. - -### Apache -Pour Apache, modifiez votre fichier `.htaccess` avec ce qui suit : - -```apacheconf -RewriteEngine On -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule ^(.*)$ index.php [QSA,L] -``` - -> **Remarque** : Si vous devez utiliser flight dans un sous-répertoire, ajoutez la ligne -> `RewriteBase /sous-repertoire/` juste après `RewriteEngine On`. - -> **Remarque** : Si vous souhaitez protéger tous les fichiers serveur, comme un fichier de base de données ou d'environnement. -> Ajoutez ceci à votre fichier `.htaccess` : - -```apacheconf -RewriteEngine On -RewriteRule ^(.*)$ index.php -``` - -### Nginx - -Pour Nginx, ajoutez ce qui suit à votre déclaration du serveur : - -```nginx -serveur { - location / { - try_files $uri $uri/ /index.php; - } -} -``` - -## Créez votre fichier `index.php`. - -```php -getTraceAsString(); -}); -``` - -Par défaut, les erreurs ne sont pas enregistrées sur le serveur web. Vous pouvez activer cela -en modifiant la configuration: - -```php -Flight::set('flight.log_errors', true); -``` - -## Non trouvé - -Lorsqu'une URL ne peut être trouvée, Flight appelle la méthode `notFound`. Le comportement par défaut -est d'envoyer une réponse `HTTP 404 Non trouvé` avec un message simple. - -Vous pouvez remplacer ce comportement pour vos propres besoins: - -```php -Flight::map('notFound', function () { - // Gérer non trouvé -}); -``` \ No newline at end of file diff --git a/content/v3/fr/learn/frameworkinstance.md b/content/v3/fr/learn/frameworkinstance.md deleted file mode 100644 index c941f8b0..00000000 --- a/content/v3/fr/learn/frameworkinstance.md +++ /dev/null @@ -1,17 +0,0 @@ -# Instance de Framework - -Au lieu d'exécuter Flight en tant que classe statique globale, vous pouvez éventuellement l'exécuter en tant qu'instance d'objet. - -```php -require 'flight/autoload.php'; - -$app = Flight::app(); - -$app->route('/', function () { - echo 'hello world!'; -}); - -$app->start(); -``` - -Donc, au lieu d'appeler la méthode statique, vous appelleriez la méthode d'instance avec le même nom sur l'objet Engine. \ No newline at end of file diff --git a/content/v3/fr/learn/frameworkmethods.md b/content/v3/fr/learn/frameworkmethods.md deleted file mode 100644 index 43b9af7a..00000000 --- a/content/v3/fr/learn/frameworkmethods.md +++ /dev/null @@ -1,42 +0,0 @@ -# Méthodes du Cadre - -Flight est conçu pour être facile à utiliser et à comprendre. Ce qui suit est l'ensemble complet -des méthodes du cadre. Il se compose de méthodes centrales, qui sont des méthodes statiques régulières, -et de méthodes extensibles, qui sont des méthodes mappées qui peuvent être filtrées -ou remplacées. - -## Méthodes Principales - -```php -Flight::map(string $name, callable $callback, bool $pass_route = false) // Crée une méthode de cadre personnalisée. -Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // Enregistre une classe à une méthode de cadre. -Flight::before(string $name, callable $callback) // Ajoute un filtre avant une méthode de cadre. -Flight::after(string $name, callable $callback) // Ajoute un filtre après une méthode de cadre. -Flight::path(string $path) // Ajoute un chemin pour le chargement automatique des classes. -Flight::get(string $key) // Obtient une variable. -Flight::set(string $key, mixed $value) // Définit une variable. -Flight::has(string $key) // Vérifie si une variable est définie. -Flight::clear(array|string $key = []) // Efface une variable. -Flight::init() // Initialise le cadre à ses réglages par défaut. -Flight::app() // Obtient l'instance de l'objet d'application -``` - -## Méthodes Extensibles - -```php -Flight::start() // Lance le cadre. -Flight::stop() // Arrête le cadre et envoie une réponse. -Flight::halt(int $code = 200, string $message = '') // Arrête le cadre avec un code d'état et un message facultatif. -Flight::route(string $pattern, callable $callback, bool $pass_route = false) // Associe un modèle d'URL à un rappel. -Flight::group(string $pattern, callable $callback) // Crée un regroupement pour les URL, le modèle doit être une chaîne de caractères. -Flight::redirect(string $url, int $code) // Redirige vers une autre URL. -Flight::render(string $file, array $data, ?string $key = null) // Rend un fichier de modèle. -Flight::error(Throwable $error) // Envoie une réponse HTTP 500. -Flight::notFound() // Envoie une réponse HTTP 404. -Flight::etag(string $id, string $type = 'string') // Effectue une mise en cache HTTP ETag. -Flight::lastModified(int $time) // Effectue une mise en cache HTTP modifiée récemment. -Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Envoie une réponse JSON. -Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Envoie une réponse JSONP. -``` - -Toutes les méthodes personnalisées ajoutées avec `map` et `register` peuvent également être filtrées. \ No newline at end of file diff --git a/content/v3/fr/learn/httpcaching.md b/content/v3/fr/learn/httpcaching.md deleted file mode 100644 index 77777026..00000000 --- a/content/v3/fr/learn/httpcaching.md +++ /dev/null @@ -1,34 +0,0 @@ -# Mise en cache HTTP - -Flight offre une prise en charge intégrée pour la mise en cache au niveau HTTP. Si la condition de mise en cache -est remplie, Flight renverra une réponse HTTP `304 Non modifié`. La prochaine fois que -le client demande la même ressource, il sera invité à utiliser sa version mise en cache localement. - -## Dernière modification - -Vous pouvez utiliser la méthode `lastModified` et transmettre un horodatage UNIX pour définir la date -et l'heure à laquelle une page a été modifiée pour la dernière fois. Le client continuera d'utiliser sa mise en cache jusqu'à ce que -que la valeur de la dernière modification soit modifiée. - -```php -Flight::route('/actualites', function () { - Flight::lastModified(1234567890); - echo 'Ce contenu sera mis en cache.'; -}); -``` - -## ETag - -La mise en cache `ETag` est similaire à `Dernière modification`, sauf que vous pouvez spécifier n'importe quel identifiant -que vous souhaitez pour la ressource : - -```php -Flight::route('/actualites', function () { - Flight::etag('mon-identifiant-unique'); - echo 'Ce contenu sera mis en cache.'; -}); -``` - -Gardez à l'esprit que l'appel à `lastModified` ou `etag` définira et vérifiera à la fois -la valeur de la mise en cache. Si la valeur de mise en cache est la même entre les demandes, Flight enverra immédiatement -une réponse `HTTP 304` et arrêtera le traitement. \ No newline at end of file diff --git a/content/v3/fr/learn/overriding.md b/content/v3/fr/learn/overriding.md deleted file mode 100644 index 63968e38..00000000 --- a/content/v3/fr/learn/overriding.md +++ /dev/null @@ -1,29 +0,0 @@ -# Substitution - -Flight vous permet de substituer sa fonctionnalité par défaut pour répondre à vos propres besoins, -sans avoir à modifier aucun code. - -Par exemple, lorsque Flight ne peut pas faire correspondre une URL à une route, il invoque la méthode `notFound` -qui envoie une réponse générique `HTTP 404`. Vous pouvez substituer ce comportement -en utilisant la méthode `map` : - -```php -Flight::map('notFound', function() { - // Afficher une page d'erreur 404 personnalisée - include 'errors/404.html'; -}); -``` - -Flight vous permet également de remplacer les composants principaux du framework. -Par exemple, vous pouvez remplacer la classe Router par défaut par votre propre classe personnalisée : - -```php -// Enregistrer votre classe personnalisée -Flight::register('router', MaClasseRouter::class); - -// Lorsque Flight charge l'instance du routeur, il chargera votre classe -$monrouteur = Flight::router(); -``` - -Cependant, les méthodes du framework telles que `map` et `register` ne peuvent pas être substituées. Vous obtiendrez -une erreur si vous essayez de le faire. \ No newline at end of file diff --git a/content/v3/fr/learn/redirects.md b/content/v3/fr/learn/redirects.md deleted file mode 100644 index a48767e8..00000000 --- a/content/v3/fr/learn/redirects.md +++ /dev/null @@ -1,15 +0,0 @@ -# Redirection - -Vous pouvez rediriger la requête actuelle en utilisant la méthode `redirect` et en passant -une nouvelle URL : - -```php -Flight::redirect('/nouvel/emplacement'); -``` - -Par défaut, Flight envoie un code d'état HTTP 303. Vous pouvez éventuellement définir un -code personnalisé : - -```php -Flight::redirect('/nouvel/emplacement', 401); -``` \ No newline at end of file diff --git a/content/v3/fr/learn/stopping.md b/content/v3/fr/learn/stopping.md deleted file mode 100644 index a18acaf3..00000000 --- a/content/v3/fr/learn/stopping.md +++ /dev/null @@ -1,20 +0,0 @@ -## Arrêt - -Vous pouvez arrêter le cadre à tout moment en appelant la méthode `halt`: - -```php -Flight::halt(); -``` - -Vous pouvez également spécifier un code d'état `HTTP` et un message facultatif: - -```php -Flight::halt(200, 'Je reviens bientôt...'); -``` - -Appeler `halt` permettra de supprimer tout contenu de réponse jusqu'à ce point. Si vous souhaitez arrêter -le cadre et afficher la réponse actuelle, utilisez la méthode `stop`: - -```php -Flight::stop(); -``` \ No newline at end of file diff --git a/content/v3/fr/learn/troubleshooting.md b/content/v3/fr/learn/troubleshooting.md deleted file mode 100644 index 3fa3c910..00000000 --- a/content/v3/fr/learn/troubleshooting.md +++ /dev/null @@ -1,69 +0,0 @@ -# Dépannage - -Cette page vous aidera à résoudre les problèmes courants que vous pourriez rencontrer lors de l'utilisation de Flight. - -## Problèmes Courants - -### 404 Non Trouvé ou Comportement de Route Inattendu - -Si vous voyez une erreur 404 Non Trouvé (mais vous jurez sur votre vie qu'elle est vraiment là et ce n'est pas une faute de frappe), en fait il pourrait s'agir d'un problème avec le fait de renvoyer une valeur dans votre point de terminaison de route au lieu de simplement l'afficher. La raison de ceci est intentionnelle mais pourrait surprendre certains développeurs. - -```php - -Flight::route('/bonjour', function(){ - // Cela pourrait provoquer une erreur 404 Non Trouvée - return 'Bonjour le monde'; -}); - -// Ce que vous voulez probablement -Flight::route('/bonjour', function(){ - echo 'Bonjour le monde'; -}); - -``` - -La raison de ceci est due à un mécanisme spécial intégré dans le routeur qui gère la sortie retournée comme un signal pour "passer à la route suivante". -Vous pouvez voir le comportement documenté dans la section [Routing](/learn/routing#passing). - -### Classe Non Trouvée (chargement automatique ne fonctionne pas) - -Il pourrait y avoir plusieurs raisons pour que cela ne se produise pas. Voici quelques exemples, mais assurez-vous également de consulter la section sur le [chargement automatique](/learn/autoloading). - -#### Nom de Fichier Incorrect -Le plus courant est que le nom de la classe ne correspond pas au nom du fichier. - -Si vous avez une classe nommée `MaClasse`, alors le fichier devrait être nommé `MaClasse.php`. Si vous avez une classe nommée `MaClasse` et que le fichier est nommé `maclasse.php`, alors le chargeur automatique ne pourra pas le trouver. - -#### Espace de Noms Incorrect -Si vous utilisez des espaces de noms, alors l'espace de noms doit correspondre à la structure des répertoires. - -```php -// code - -// si votre MyController est dans le répertoire app/controllers et qu'il est namespaced -// cela ne fonctionnera pas. -Flight::route('/bonjour', 'MyController->bonjour'); - -// vous devrez choisir l'une de ces options -Flight::route('/bonjour', 'app\controllers\MyController->bonjour'); -// ou si vous avez une déclaration use en haut - -use app\controllers\MyController; - -Flight::route('/bonjour', [ MyController::class, 'bonjour' ]); -// peut également être écrit -Flight::route('/bonjour', MyController::class.'->bonjour'); -// aussi... -Flight::route('/bonjour', [ 'app\controllers\MyController', 'bonjour' ]); -``` - -#### `path()` non défini - -Dans l'application squelette, cela est défini à l'intérieur du fichier `config.php`, mais pour que vos classes soient trouvées, vous devez vous assurer que la méthode `path()` est définie (probablement à la racine de votre répertoire) avant d'essayer de l'utiliser. - -```php - -// Ajouter un chemin à l'autoload -Flight::path(__DIR__.'/../'); - -``` \ No newline at end of file diff --git a/content/v3/fr/learn/variables.md b/content/v3/fr/learn/variables.md deleted file mode 100644 index ff900ab2..00000000 --- a/content/v3/fr/learn/variables.md +++ /dev/null @@ -1,34 +0,0 @@ -# Variables - -Flight permet de sauvegarder des variables afin qu'elles puissent être utilisées n'importe où dans votre application. - -```php -// Sauvegardez votre variable -Flight::set('id', 123); - -// Ailleurs dans votre application -$id = Flight::get('id'); -``` -Pour vérifier si une variable a été définie, vous pouvez faire : - -```php -if (Flight::has('id')) { - // Faire quelque chose -} -``` - -Vous pouvez effacer une variable en faisant : - -```php -// Efface la variable id -Flight::clear('id'); - -// Efface toutes les variables -Flight::clear(); -``` - -Flight utilise également des variables à des fins de configuration. - -```php -Flight::set('flight.log_errors', true); -``` \ No newline at end of file diff --git a/content/v3/fr/learn/views.md b/content/v3/fr/learn/views.md deleted file mode 100644 index 8c82d3aa..00000000 --- a/content/v3/fr/learn/views.md +++ /dev/null @@ -1,129 +0,0 @@ -## Vues - -Flight fournit par défaut quelques fonctionnalités de base de templating. Pour afficher un template de vue, appelez la méthode `render` avec le nom du fichier template et des données de template optionnelles : - -```php -Flight::render('hello.php', ['name' => 'Bob']); -``` - -Les données de template que vous transmettez sont automatiquement injectées dans le template et peuvent être référencées comme une variable locale. Les fichiers de template sont simplement des fichiers PHP. Si le contenu du fichier template `hello.php` est : - -```php -Hello, ! -``` - -La sortie serait : - -``` -Hello, Bob! -``` - -Vous pouvez également définir manuellement des variables de vue en utilisant la méthode set : - -```php -Flight::view()->set('name', 'Bob'); -``` - -La variable `name` est désormais disponible dans toutes vos vues. Vous pouvez simplement faire : - -```php -Flight::render('hello'); -``` - -Notez que lors de la spécification du nom du template dans la méthode render, vous pouvez omettre l'extension `.php`. - -Par défaut, Flight recherchera un répertoire `views` pour les fichiers de template. Vous pouvez définir un chemin alternatif pour vos templates en configurant ce qui suit : - -```php -Flight::set('flight.views.path', '/chemin/vers/views'); -``` - -## Mises en page - -Il est courant pour les sites web d'avoir un seul fichier de template de mise en page avec un contenu interchangeable. Pour afficher le contenu à utiliser dans une mise en page, vous pouvez transmettre un paramètre optionnel à la méthode `render`. - -```php -Flight::render('header', ['heading' => 'Hello'], 'headerContent'); -Flight::render('body', ['body' => 'World'], 'bodyContent'); -``` - -Votre vue aura ensuite des variables enregistrées appelées `headerContent` et `bodyContent`. Vous pouvez ensuite afficher votre mise en page en faisant : - -```php -Flight::render('layout', ['title' => 'Page d\'accueil']); -``` - -Si les fichiers de template ressemblent à ceci : - -`header.php` : - -```php -

-``` - -`body.php` : - -```php -
-``` - -`layout.php` : - -```php - - - <?= $title ?> - - - - - - -``` - -La sortie serait : - -```html - - - Page d'accueil - - -

Hello

-
World
- - -``` - -## Vues Personnalisées - -Flight vous permet de remplacer simplement le moteur de vue par défaut en enregistrant votre propre classe de vue. Voici comment vous utiliseriez le moteur de template [Smarty](http://www.smarty.net/) pour vos vues : - -```php -// Charger la bibliothèque Smarty -require './Smarty/libs/Smarty.class.php'; - -// Enregistrer Smarty en tant que classe de vue -// Transmettre également une fonction de rappel pour configurer Smarty au chargement -Flight::register('view', Smarty::class, [], function (Smarty $smarty) { - $smarty->setTemplateDir('./templates/'); - $smarty->setCompileDir('./templates_c/'); - $smarty->setConfigDir('./config/'); - $smarty->setCacheDir('./cache/'); -}); - -// Assigner des données de template -Flight::view()->assign('name', 'Bob'); - -// Afficher le template -Flight::view()->display('hello.tpl'); -``` - -Pour plus de complétude, vous devriez également remplacer la méthode de rendu par défaut de Flight : - -```php -Flight::map('render', function(string $template, array $data): void { - Flight::view()->assign($data); - Flight::view()->display($template); -}); -``` \ No newline at end of file diff --git a/content/v3/id/awesome-plugins/pdo_wrapper.md b/content/v3/id/awesome-plugins/pdo_wrapper.md deleted file mode 100644 index dc4f87d4..00000000 --- a/content/v3/id/awesome-plugins/pdo_wrapper.md +++ /dev/null @@ -1,119 +0,0 @@ -# Kelas Pembantu PDO PdoWrapper - -Flight hadir dengan kelas pembantu untuk PDO. Kelas ini memungkinkan Anda untuk dengan mudah melakukan kueri ke basis data Anda dengan semua persiapan/eksekusi/fetchAll() yang membingungkan. Ini sangat menyederhanakan cara Anda dapat melakukan kueri ke basis data Anda. Setiap hasil baris dikembalikan sebagai kelas Koleksi Flight yang memungkinkan Anda mengakses data Anda melalui sintaks array atau sintaks objek. - -## Mendaftar Kelas Pembantu PDO - -```php -// Daftarkan kelas pembantu PDO -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 - ] -]); -``` - -## Penggunaan -Objek ini memperluas PDO sehingga semua metode PDO normal tersedia. Metode berikut ditambahkan untuk mempermudah kueri ke basis data: - -### `runQuery(string $sql, array $params = []): PDOStatement` -Gunakan ini untuk INSERTS, UPDATES, atau jika Anda berencana menggunakan SELECT dalam loop while - -```php -$db = Flight::db(); -$statement = $db->runQuery("SELECT * FROM table WHERE something = ?", [ $something ]); -while($row = $statement->fetch()) { - // ... -} - -// Atau menulis ke basis data -$db->runQuery("INSERT INTO table (name) VALUES (?)", [ $name ]); -$db->runQuery("UPDATE table SET name = ? WHERE id = ?", [ $name, $id ]); -``` - -### `fetchField(string $sql, array $params = []): mixed` -Mengambil field pertama dari kueri - -```php -$db = Flight::db(); -$count = $db->fetchField("SELECT COUNT(*) FROM table WHERE something = ?", [ $something ]); -``` - -### `fetchRow(string $sql, array $params = []): array` -Mengambil satu baris dari kueri - -```php -$db = Flight::db(); -$row = $db->fetchRow("SELECT id, name FROM table WHERE id = ?", [ $id ]); -echo $row['name']; -// atau -echo $row->name; -``` - -### `fetchAll(string $sql, array $params = []): array` -Mengambil semua baris dari kueri - -```php -$db = Flight::db(); -$rows = $db->fetchAll("SELECT id, name FROM table WHERE something = ?", [ $something ]); -foreach($rows as $row) { - echo $row['name']; - // atau - echo $row->name; -} -``` - -## Catatan dengan sintaks `IN()` -Ini juga memiliki pembungkus yang berguna untuk pernyataan `IN()`. Anda cukup memasukkan tanda tanya tunggal sebagai placeholder untuk `IN()` dan kemudian array nilai. Berikut adalah contoh seperti apa itu: - -```php -$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 ]); -``` - -## Contoh Lengkap - -```php -// Contoh rute dan cara Anda akan menggunakan pembungkus ini -Flight::route('/users', function () { - // Dapatkan semua pengguna - $users = Flight::db()->fetchAll('SELECT * FROM users'); - - // Streaming semua pengguna - $statement = Flight::db()->runQuery('SELECT * FROM users'); - while ($user = $statement->fetch()) { - echo $user['name']; - // atau echo $user->name; - } - - // Dapatkan satu pengguna - $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); - - // Dapatkan satu nilai - $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); - - // Sintaks IN() khusus untuk membantu (pastikan IN ditulis dengan huruf kapital) - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); - // Anda juga dapat melakukan ini - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [ '1,2,3,4,5']); - - // Memasukkan pengguna baru - Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']); - $insert_id = Flight::db()->lastInsertId(); - - // Memperbarui pengguna - Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]); - - // Menghapus pengguna - Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]); - - // Dapatkan jumlah baris yang terpengaruh - $statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']); - $affected_rows = $statement->rowCount(); - -}); -``` \ No newline at end of file diff --git a/content/v3/id/learn.md b/content/v3/id/learn.md deleted file mode 100644 index 95b61ea0..00000000 --- a/content/v3/id/learn.md +++ /dev/null @@ -1,90 +0,0 @@ -# Pelajari Tentang Flight - -Flight adalah kerangka kerja yang cepat, sederhana, dan dapat diperluas untuk PHP. Ini sangat serbaguna dan dapat digunakan untuk membangun jenis aplikasi web apa pun. -Ini dibuat dengan prinsip kesederhanaan dan ditulis dengan cara yang mudah dipahami dan digunakan. - -## 🚀 Pengalaman AI & Pengembang dengan Flight - -Flight tidak hanya cepat dan sederhana—ini juga dirancang untuk membantu Anda mengkode lebih cerdas dan menyelesaikan lebih banyak tugas, terutama dengan bantuan alat AI modern. Baik Anda menggunakan asisten pengkodean yang didukung AI, mengotomatiskan tugas-tugas berulang, atau hanya ingin meningkatkan produktivitas, jejak kecil Flight dan struktur yang langsung membuatnya menyenangkan untuk digunakan bersama alur kerja devex dan AI terbaru. - -- **Pengkodean Dengan Bantuan AI:** Flight bekerja dengan baik dengan asisten pengkodean AI, memungkinkan Anda membuat kerangka, merombak, dan membangun fitur lebih cepat dari sebelumnya. -- **Prototyping Lebih Cepat:** Cepat mulai ide-ide baru dan iterasi dengan bantuan alat AI—Flight tidak akan menghalangi Anda. -- **Integrasikan API AI:** Jika Anda ingin terhubung ke layanan AI atau menambahkan fitur pintar, Flight membuatnya mudah, tetapi Anda tidak perlu menjadi ahli AI untuk mendapatkan manfaatnya. - -Penasaran bagaimana memulai? [Jelajahi panduan AI & DevEx kami](/learn/ai) untuk tips, alat, dan contoh dunia nyata tentang cara bekerja lebih cepat dan lebih cerdas dengan Flight! - -## Konsep Penting Kerangka Kerja - -##### [Mengapa Kerangka Kerja?](/learn/why-frameworks) - -Berikut adalah artikel singkat tentang mengapa Anda harus menggunakan kerangka kerja. Ini adalah ide bagus untuk memahami manfaat menggunakan kerangka kerja sebelum Anda mulai menggunakannya. - -Selain itu, tutorial yang sangat bagus telah dibuat oleh [@lubiana](https://git.php.fail/lubiana). Meskipun tidak membahas detail tentang Flight secara khusus, -panduan ini akan membantu Anda memahami beberapa konsep utama seputar kerangka kerja dan mengapa mereka bermanfaat untuk digunakan. -Anda dapat menemukan tutorial [di sini](https://git.php.fail/lubiana/no-framework-tutorial/src/branch/master/README.md). - -##### [Flight Dibandingkan dengan Kerangka Kerja Lain](/learn/flight-vs-another-framework) -Jika Anda bermigrasi dari kerangka kerja lain seperti Laravel, Slim, Fat-Free, atau Symfony ke Flight, halaman ini akan membantu Anda memahami perbedaan antara keduanya. - -## Topik Inti - -##### [AI & Pengalaman Pengembang](/learn/ai) -Pelajari bagaimana Flight bekerja dengan alat AI dan alur kerja pengembang modern untuk membantu Anda mengkode lebih cepat dan lebih cerdas. - -##### [Autoloading](/learn/autoloading) - -Pelajari cara autoload kelas Anda sendiri dalam aplikasi Anda. - -##### [Routing](/learn/routing) - -Pelajari cara mengelola rute untuk aplikasi web Anda. Ini juga mencakup pengelompokan rute, parameter rute, dan middleware. - -##### [Middleware](/learn/middleware) - -Pelajari cara menggunakan middleware untuk menyaring permintaan dan respons dalam aplikasi Anda. - -##### [Permintaan](/learn/requests) - -Pelajari cara menangani permintaan dan respons dalam aplikasi Anda. - -##### [Respons](/learn/responses) - -Pelajari cara mengirim respons ke pengguna Anda. - -##### [Peristiwa](/learn/events) - -Pelajari cara menggunakan sistem peristiwa untuk menambahkan peristiwa khusus ke aplikasi Anda. - -##### [Template HTML](/learn/templates) - -Pelajari cara menggunakan mesin tampilan bawaan untuk merender template HTML Anda. - -##### [Keamanan](/learn/security) - -Pelajari cara mengamankan aplikasi Anda dari ancaman keamanan umum. - -##### [Konfigurasi](/learn/configuration) - -Pelajari cara mengonfigurasi kerangka kerja untuk aplikasi Anda. - -##### [Memperluas Flight](/learn/extending) - -Pelajari cara memperluas kerangka kerja dengan menambahkan metode dan kelas Anda sendiri. - -##### [Peristiwa dan Penyaringan](/learn/filtering) - -Pelajari cara menggunakan sistem peristiwa untuk menambahkan hook ke metode Anda dan metode kerangka kerja internal. - -##### [Kontainer Injeksi Ketergantungan](/learn/dependency-injection-container) - -Pelajari cara menggunakan kontainer injeksi ketergantungan (DIC) untuk mengelola ketergantungan aplikasi Anda. - -##### [API Kerangka Kerja](/learn/api) - -Pelajari tentang metode inti kerangka kerja. - -##### [Migrasi ke v3](/learn/migrating-to-v3) -Kesesuaian mundur sebagian besar dipertahankan, tetapi ada beberapa perubahan yang harus Anda ketahui saat bermigrasi dari v2 ke v3. - -##### [Penyelesaian Masalah](/learn/troubleshooting) -Ada beberapa masalah umum yang mungkin Anda hadapi saat menggunakan Flight. Halaman ini akan membantu Anda menyelesaikan masalah tersebut. \ No newline at end of file diff --git a/content/v3/id/learn/api.md b/content/v3/id/learn/api.md deleted file mode 100644 index 4fbc4e4d..00000000 --- a/content/v3/id/learn/api.md +++ /dev/null @@ -1,56 +0,0 @@ -# Metode API Framework - -Flight dirancang untuk mudah digunakan dan dipahami. Berikut adalah -set lengkap metode untuk framework. Ini terdiri dari metode inti, yang merupakan metode statis biasa, dan metode yang dapat diperluas, yang merupakan metode yang dipetakan yang dapat disaring atau ditimpa. - -## Metode Inti - -Metode-metode ini adalah inti dari framework dan tidak dapat ditimpa. - -```php -Flight::map(string $name, callable $callback, bool $pass_route = false) // Membuat metode framework khusus. -Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // Mendaftarkan kelas ke metode framework. -Flight::unregister(string $name) // Menghapus pendaftaran kelas pada metode framework. -Flight::before(string $name, callable $callback) // Menambahkan filter sebelum metode framework. -Flight::after(string $name, callable $callback) // Menambahkan filter setelah metode framework. -Flight::path(string $path) // Menambahkan jalur untuk memuat kelas secara otomatis. -Flight::get(string $key) // Mengambil variabel yang disetel oleh Flight::set(). -Flight::set(string $key, mixed $value) // Menyetel variabel dalam mesin Flight. -Flight::has(string $key) // Memeriksa apakah sebuah variabel disetel. -Flight::clear(array|string $key = []) // Menghapus sebuah variabel. -Flight::init() // Menginisialisasi framework ke pengaturan defaultnya. -Flight::app() // Mengambil instance objek aplikasi. -Flight::request() // Mengambil instance objek permintaan. -Flight::response() // Mengambil instance objek respons. -Flight::router() // Mengambil instance objek router. -Flight::view() // Mengambil instance objek tampilan. -``` - -## Metode yang Dapat Diperluas - -```php -Flight::start() // Memulai framework. -Flight::stop() // Menghentikan framework dan mengirimkan respons. -Flight::halt(int $code = 200, string $message = '') // Menghentikan framework dengan kode status dan pesan opsional. -Flight::route(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Memetakan pola URL ke callback. -Flight::post(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Memetakan pola URL permintaan POST ke callback. -Flight::put(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Memetakan pola URL permintaan PUT ke callback. -Flight::patch(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Memetakan pola URL permintaan PATCH ke callback. -Flight::delete(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Memetakan pola URL permintaan DELETE ke callback. -Flight::group(string $pattern, callable $callback) // Membuat pengelompokan untuk URL, pola harus berupa string. -Flight::getUrl(string $name, array $params = []) // Menghasilkan URL berdasarkan alias rute. -Flight::redirect(string $url, int $code) // Mengalihkan ke URL lain. -Flight::download(string $filePath) // Mengunduh sebuah file. -Flight::render(string $file, array $data, ?string $key = null) // Merender file template. -Flight::error(Throwable $error) // Mengirimkan respons HTTP 500. -Flight::notFound() // Mengirimkan respons HTTP 404. -Flight::etag(string $id, string $type = 'string') // Melakukan caching HTTP ETag. -Flight::lastModified(int $time) // Melakukan caching HTTP terakhir dimodifikasi. -Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Mengirimkan respons JSON. -Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Mengirimkan respons JSONP. -Flight::jsonHalt(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Mengirimkan respons JSON dan menghentikan framework. -Flight::onEvent(string $event, callable $callback) // Mendaftarkan pendengar acara. -Flight::triggerEvent(string $event, ...$args) // Memicu sebuah acara. -``` - -Metode kustom apa pun yang ditambahkan dengan `map` dan `register` juga dapat disaring. Untuk contoh tentang bagaimana memetakan metode ini, lihat panduan [Memperluas Flight](/learn/extending). \ No newline at end of file diff --git a/content/v3/id/learn/troubleshooting.md b/content/v3/id/learn/troubleshooting.md deleted file mode 100644 index 13d2dff0..00000000 --- a/content/v3/id/learn/troubleshooting.md +++ /dev/null @@ -1,72 +0,0 @@ -# Pemecahan Masalah - -Halaman ini akan membantu Anda memecahkan masalah umum yang mungkin Anda temui saat menggunakan Flight. - -## Masalah Umum - -### 404 Tidak Ditemukan atau Perilaku Rute Tak Terduga - -Jika Anda melihat kesalahan 404 Tidak Ditemukan (tetapi Anda bersumpah bahwa itu benar-benar ada dan bukan kesalahan ketik) ini sebenarnya bisa menjadi masalah -dengan Anda yang mengembalikan nilai di titik akhir rute Anda alih-alih hanya mencetaknya. Alasan untuk ini adalah disengaja tetapi bisa mengganggu beberapa pengembang. - -```php - -Flight::route('/hello', function(){ - // Ini mungkin menyebabkan kesalahan 404 Tidak Ditemukan - return 'Hello World'; -}); - -// Apa yang mungkin Anda inginkan -Flight::route('/hello', function(){ - echo 'Hello World'; -}); - -``` - -Alasan untuk ini adalah karena mekanisme khusus yang dibangun ke dalam router yang menangani keluaran pengembalian sebagai sinyal untuk "melanjutkan ke rute berikutnya". -Anda dapat melihat perilaku ini didokumentasikan di bagian [Routing](/learn/routing#passing). - -### Kelas Tidak Ditemukan (autoloading tidak bekerja) - -Ada beberapa alasan mengapa ini tidak terjadi. Di bawah ini adalah beberapa contoh tetapi pastikan Anda juga memeriksa bagian [autoloading](/learn/autoloading). - -#### Nama File yang Salah -Yang paling umum adalah bahwa nama kelas tidak cocok dengan nama file. - -Jika Anda memiliki kelas bernama `MyClass` maka file tersebut harus dinamai `MyClass.php`. Jika Anda memiliki kelas bernama `MyClass` dan file tersebut dinamai `myclass.php` -maka autoloader tidak akan dapat menemukannya. - -#### Namespace yang Salah -Jika Anda menggunakan namespace, maka namespace harus cocok dengan struktur direktori. - -```php -// kode - -// jika MyController Anda berada di direktori app/controllers dan memiliki namespace -// ini tidak akan berfungsi. -Flight::route('/hello', 'MyController->hello'); - -// Anda perlu memilih salah satu dari opsi ini -Flight::route('/hello', 'app\controllers\MyController->hello'); -// atau jika Anda memiliki pernyataan use di atas - -use app\controllers\MyController; - -Flight::route('/hello', [ MyController::class, 'hello' ]); -// juga bisa ditulis -Flight::route('/hello', MyController::class.'->hello'); -// juga... -Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); -``` - -#### `path()` tidak didefinisikan - -Dalam aplikasi kerangka kerja, ini didefinisikan di dalam file `config.php`, tetapi agar kelas Anda dapat ditemukan, Anda perlu memastikan bahwa metode `path()` -didefinisikan (kemungkinan ke root direktori Anda) sebelum Anda mencoba menggunakannya. - -```php - -// Tambahkan path ke autoloader -Flight::path(__DIR__.'/../'); - -``` \ No newline at end of file diff --git a/content/v3/ja/awesome-plugins/index.md b/content/v3/ja/awesome-plugins/index.md deleted file mode 100644 index b03aaee0..00000000 --- a/content/v3/ja/awesome-plugins/index.md +++ /dev/null @@ -1,40 +0,0 @@ -# すばらしいプラグイン - -Flightは非常に拡張可能です。Flightアプリケーションに機能を追加するために使用できるプラグインがいくつかあります。いくつかはFlightチームによって公式にサポートされており、他には開始を手助けするためのミクロ/ライトライブラリがあります。 - -## キャッシュ - -キャッシュはアプリケーションの高速化に役立つ方法です。Flightと使用できるキャッシュライブラリがいくつかあります。 - -- [Wruczek/PHP-File-Cache](/awesome-plugins/php-file-cache) - 軽量でシンプルなPHPファイル内キャッシュクラス - -## デバッグ - -開発を行うローカル環境ではデバッグが重要です。いくつかのプラグインを使用するとデバッグ体験を向上させることができます。 - -- [tracy/tracy](/awesome-plugins/tracy) - Flightと使用できるフル機能のエラーハンドラ。アプリケーションのデバッグに役立ついくつかのパネルがあります。また、容易に拡張して独自のパネルを追加できます。 -- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) エラーハンドラと共に使用し、Flightプロジェクトのデバッグを支援する追加パネルが含まれています。 - -## データベース - -データベースはほとんどのアプリケーションの中心です。これによりデータの保存と取得が可能になります。一部のデータベースライブラリはクエリの記述や実行を簡素化するラッパーであり、一部は完全なORMです。 - -- [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Flightの公式PDOラッパーで、コアの一部です。クエリの記述と実行のプロセスを簡単にするためのシンプルなラッパーです。ORMではありません。 -- [flightphp/active-record](/awesome-plugins/active-record) - Flightの公式ActiveRecord ORM/Mapper。データの簡単な取得と保存に適した優れたライブラリ。 - -## セッション - -APIにはあまり役立たないが、Webアプリケーションの構築にはセッションが状態とログイン情報の維持に重要です。 - -- [Ghostff/Session](/awesome-plugins/session) - PHPセッションマネージャー(非同期、フラッシュ、セグメント、セッション暗号化)。セッションデータの暗号化/復号化のためにPHP open_sslを使用します。 - -## テンプレーティング - -テンプレートはUIを持つWebアプリケーションにとって重要です。Flightと使用できるいくつかのテンプレートエンジンがあります。 - -- [flightphp/core View](/learn#views) - コアの一部である非常に基本的なテンプレートエンジンです。プロジェクト内に複数のページがある場合は推奨されません。 -- [latte/latte](/awesome-plugins/latte) - PHP構文に近い感覚で非常に使いやすい完全機能のテンプレートエンジンです。TwigやSmartyよりも簡単に拡張して独自のフィルターや関数を追加できます。 - -## 貢献 - -共有したいプラグインがありますか?リストに追加するためにプルリクエストを送信してください! \ No newline at end of file diff --git a/content/v3/ja/awesome-plugins/pdo_wrapper.md b/content/v3/ja/awesome-plugins/pdo_wrapper.md deleted file mode 100644 index 2dc11156..00000000 --- a/content/v3/ja/awesome-plugins/pdo_wrapper.md +++ /dev/null @@ -1,119 +0,0 @@ -# PdoWrapper PDO ヘルパークラス - -Flight には PDO 用のヘルパークラスが付属しています。これにより、準備/実行/fetchAll() の混乱を簡単にクエリすることができます。データベースのクエリが大幅に簡素化されます。各行の結果は Flight Collection クラスとして返され、配列構文またはオブジェクト構文を使用してデータにアクセスできます。 - -## PDO ヘルパークラスの登録 - -```php -// PDO ヘルパークラスを登録します -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 - ] -]); -``` - -## 使用法 -このオブジェクトは PDO を拡張しているため、通常の PDO メソッドをすべて使用できます。データベースのクエリをより簡単にするために次のメソッドが追加されています: - -### `runQuery(string $sql, array $params = []): PDOStatement` -INSERT や UPDATE に使用したり、SELECT を while ループで使用する予定がある場合に使用します。 - -```php -$db = Flight::db(); -$statement = $db->runQuery("SELECT * FROM table WHERE something = ?", [ $something ]); -while($row = $statement->fetch()) { - // ... -} - -// またはデータベースに書き込む場合 -$db->runQuery("INSERT INTO table (name) VALUES (?)", [ $name ]); -$db->runQuery("UPDATE table SET name = ? WHERE id = ?", [ $name, $id ]); -``` - -### `fetchField(string $sql, array $params = []): mixed` -クエリから最初のフィールドを取得します - -```php -$db = Flight::db(); -$count = $db->fetchField("SELECT COUNT(*) FROM table WHERE something = ?", [ $something ]); -``` - -### `fetchRow(string $sql, array $params = []): array` -クエリから1行を取得します - -```php -$db = Flight::db(); -$row = $db->fetchRow("SELECT id, name FROM table WHERE id = ?", [ $id ]); -echo $row['name']; -// または -echo $row->name; -``` - -### `fetchAll(string $sql, array $params = []): array` -クエリからすべての行を取得します - -```php -$db = Flight::db(); -$rows = $db->fetchAll("SELECT id, name FROM table WHERE something = ?", [ $something ]); -foreach($rows as $row) { - echo $row['name']; - // または - echo $row->name; -} -``` - -## `IN()` 構文について -`IN()` ステートメント用の便利なラッパーもあります。`IN()` のプレースホルダーとして単一のクエスチョンマークを渡し、その後に値の配列を単純に渡すことができます。以下はその例です: - -```php -$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 ]); -``` - -## 完全な例 - -```php -// 例として、このラッパーを使用する方法とルートを示します -Flight::route('/users', function () { - // すべてのユーザーを取得 - $users = Flight::db()->fetchAll('SELECT * FROM users'); - - // すべてのユーザーを表示 - $statement = Flight::db()->runQuery('SELECT * FROM users'); - while ($user = $statement->fetch()) { - echo $user['name']; - // または echo $user->name; - } - - // 単一のユーザーを取得 - $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); - - // 単一の値を取得 - $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); - - // 進行補助として IN() 構文を使用します (IN が大文字であることを確認してください) - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); - // またはこのようにもできます - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [ '1,2,3,4,5']); - - // 新しいユーザーを挿入します - Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']); - $insert_id = Flight::db()->lastInsertId(); - - // ユーザーを更新します - Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]); - - // ユーザーを削除します - Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]); - - // 影響を受けた行数を取得します - $statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']); - $affected_rows = $statement->rowCount(); - -}); -``` \ No newline at end of file diff --git a/content/v3/ja/install.md b/content/v3/ja/install.md deleted file mode 100644 index 92b04f15..00000000 --- a/content/v3/ja/install.md +++ /dev/null @@ -1,62 +0,0 @@ -# インストール - -## ファイルをダウンロードします。 - -もし[Composer](https://getcomposer.org)を使用している場合、次のコマンドを実行できます: - -```bash -composer require flightphp/core -``` - -または、[ファイルをダウンロード](https://github.com/flightphp/core/archive/master.zip)して、それらをウェブディレクトリに直接展開することもできます。 - -## ウェブサーバを構成します。 - -### Apache -Apacheを使用する場合、`.htaccess`ファイルを以下のように編集してください: - -```apacheconf -RewriteEngine On -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule ^(.*)$ index.php [QSA,L] -``` - -> **注意**: サブディレクトリでflightを使用する必要がある場合は、`RewriteEngine On`の直後に行を追加してください: `RewriteBase /subdir/`。 - -> **注意**: データベースや環境ファイルなどのすべてのサーバファイルを保護する必要がある場合は、`.htaccess`ファイルに以下を追加してください: - -```apacheconf -RewriteEngine On -RewriteRule ^(.*)$ index.php -``` - -### Nginx -Nginxを使用する場合、以下をサーバ定義に追加してください: - -```nginx -server { - location / { - try_files $uri $uri/ /index.php; - } -} -``` - -## `index.php`ファイルを作成します。 - -```php -getTraceAsString(); -}); -``` - -デフォルトでは、エラーはウェブサーバーに記録されません。これを有効にすることでログを取得できます: - -```php -Flight::set('flight.log_errors', true); -``` - -## 見つかりません - -URL が見つからない場合、Flight は `notFound` メソッドを呼び出します。デフォルトの動作は、簡単なメッセージを含む `HTTP 404 Not Found` 応答を送信することです。 - -独自のニーズに合わせてこの動作を上書きすることができます: - -```php -Flight::map('notFound', function () { - // 見つからない場合の処理 -}); -``` \ No newline at end of file diff --git a/content/v3/ja/learn/frameworkinstance.md b/content/v3/ja/learn/frameworkinstance.md deleted file mode 100644 index b3a978d3..00000000 --- a/content/v3/ja/learn/frameworkinstance.md +++ /dev/null @@ -1,17 +0,0 @@ -# フレームワークのインスタンス - -Flightをグローバルな静的クラスとして実行する代わりに、オブジェクトのインスタンスとして実行することもできます。 - -```php -require 'flight/autoload.php'; - -$app = Flight::app(); - -$app->route('/', function () { - echo 'hello world!'; -}); - -$app->start(); -``` - -静的なメソッドを呼び出す代わりに、同じ名前のインスタンスメソッドをEngineオブジェクトで呼び出すことになります。 \ No newline at end of file diff --git a/content/v3/ja/learn/frameworkmethods.md b/content/v3/ja/learn/frameworkmethods.md deleted file mode 100644 index 8500ae37..00000000 --- a/content/v3/ja/learn/frameworkmethods.md +++ /dev/null @@ -1,40 +0,0 @@ -# フレームワークのメソッド - -Flightは使いやすく理解しやすいように設計されています。以下はフレームワークの完全なメソッドセットです。 -コアメソッドには、通常の静的メソッドであるコアメソッドと、フィルタリングやオーバーライドが可能なマップされたメソッドである拡張メソッドが含まれています。 - -## コアメソッド - -```php -Flight::map(string $name, callable $callback, bool $pass_route = false) // カスタムフレームワークメソッドを作成します。 -Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // クラスをフレームワークメソッドに登録します。 -Flight::before(string $name, callable $callback) // フレームワークメソッドの前にフィルタを追加します。 -Flight::after(string $name, callable $callback) // フレームワークメソッドの後にフィルタを追加します。 -Flight::path(string $path) // クラスの自動読み込み用のパスを追加します。 -Flight::get(string $key) // 変数を取得します。 -Flight::set(string $key, mixed $value) // 変数を設定します。 -Flight::has(string $key) // 変数が設定されているかどうかを確認します。 -Flight::clear(array|string $key = []) // 変数をクリアします。 -Flight::init() // フレームワークをデフォルト設定に初期化します。 -Flight::app() // アプリケーションオブジェクトのインスタンスを取得します。 -``` - -## 拡張メソッド - -```php -Flight::start() // フレームワークを開始します。 -Flight::stop() // フレームワークを停止してレスポンスを送信します。 -Flight::halt(int $code = 200, string $message = '') // オプションのステータスコードとメッセージでフレームワークを停止します。 -Flight::route(string $pattern, callable $callback, bool $pass_route = false) // URLパターンをコールバックにマップします。 -Flight::group(string $pattern, callable $callback) // URLのグループを作成します。パターンは文字列でなければなりません。 -Flight::redirect(string $url, int $code) // 別のURLにリダイレクトします。 -Flight::render(string $file, array $data, ?string $key = null) // テンプレートファイルをレンダリングします。 -Flight::error(Throwable $error) // HTTP 500レスポンスを送信します。 -Flight::notFound() // HTTP 404レスポンスを送信します。 -Flight::etag(string $id, string $type = 'string') // ETag HTTPキャッシュを実行します。 -Flight::lastModified(int $time) // 最終変更日HTTPキャッシュを実行します。 -Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // JSONレスポンスを送信します。 -Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // JSONPレスポンスを送信します。 -``` - -`map`と`register`で追加された任意のカスタムメソッドもフィルタリングできます。 \ No newline at end of file diff --git a/content/v3/ja/learn/httpcaching.md b/content/v3/ja/learn/httpcaching.md deleted file mode 100644 index 613fc810..00000000 --- a/content/v3/ja/learn/httpcaching.md +++ /dev/null @@ -1,27 +0,0 @@ -# HTTP キャッシング - -Flight は HTTP レベルのキャッシングを組み込みでサポートしています。キャッシングの条件を満たすと、Flight は HTTP `304 Not Modified` のレスポンスを返します。クライアントが同じリソースを次にリクエストするときは、ローカルにキャッシュされたバージョンを使用するよう促されます。 - -## Last-Modified - -`lastModified` メソッドを使用して、UNIX タイムスタンプを渡すことでページが最後に変更された日時を設定できます。クライアントは最終変更日時の値が変更されるまで、キャッシュを引き続き使用します。 - -```php -Flight::route('/news', function () { - Flight::lastModified(1234567890); - echo 'このコンテンツはキャッシュされます。'; -}); -``` - -## ETag - -`ETag` キャッシングは `Last-Modified` と似ていますが、リソースに任意の ID を指定できます: - -```php -Flight::route('/news', function () { - Flight::etag('my-unique-id'); - echo 'このコンテンツはキャッシュされます。'; -}); -``` - -`lastModified` または `etag` のいずれかを呼び出すと、キャッシュの値が設定されてチェックされます。リクエスト間でキャッシュの値が同じ場合、Flight は直ちに `HTTP 304` レスポンスを送信して処理を停止します。 \ No newline at end of file diff --git a/content/v3/ja/learn/overriding.md b/content/v3/ja/learn/overriding.md deleted file mode 100644 index 6d9298d8..00000000 --- a/content/v3/ja/learn/overriding.md +++ /dev/null @@ -1,25 +0,0 @@ -# オーバーライド - -Flightは、コードを変更することなく、独自のニーズに合わせてデフォルトの機能をオーバーライドできるようにします。 - -たとえば、FlightがURLをルートにマッチさせられない場合、`notFound`メソッドが呼び出され、一般的な `HTTP 404` レスポンスが送信されます。この動作を以下のようにオーバーライドできます: - -```php -Flight::map('notFound', function() { - // カスタム404ページを表示 - include 'errors/404.html'; -}); -``` - -Flightはまた、フレームワークのコアコンポーネントを置換することを許可します。 -たとえば、デフォルトのRouterクラスを独自のカスタムクラスで置き換えることができます: - -```php -// カスタムクラスを登録 -Flight::register('router', MyRouter::class); - -// FlightがRouterインスタンスをロードするとき、あなたのクラスがロードされます -$myrouter = Flight::router(); -``` - -`map`や`register`などのフレームワークのメソッドはオーバーライドできません。これを試みるとエラーが発生します。 \ No newline at end of file diff --git a/content/v3/ja/learn/redirects.md b/content/v3/ja/learn/redirects.md deleted file mode 100644 index ae782268..00000000 --- a/content/v3/ja/learn/redirects.md +++ /dev/null @@ -1,13 +0,0 @@ -# リダイレクト - -`redirect` メソッドを使用して、新しい URL を指定して現在のリクエストをリダイレクトできます: - -```php -Flight::redirect('/new/location'); -``` - -Flight はデフォルトで HTTP 303 ステータスコードを送信します。オプションでカスタムコードを設定できます: - -```php -Flight::redirect('/new/location', 401); -``` \ No newline at end of file diff --git a/content/v3/ja/learn/stopping.md b/content/v3/ja/learn/stopping.md deleted file mode 100644 index ae24cd7f..00000000 --- a/content/v3/ja/learn/stopping.md +++ /dev/null @@ -1,19 +0,0 @@ -# 停止 - -フレームワークを`halt`メソッドを呼び出すことでいつでも停止できます: - -```php -Flight::halt(); -``` - -オプションで`HTTP`ステータスコードとメッセージを指定することもできます: - -```php -Flight::halt(200, 'Be right back...'); -``` - -`halt`を呼び出すと、その時点までのレスポンスコンテンツが破棄されます。フレームワークを停止して現在のレスポンスを出力するには、`stop`メソッドを使用してください: - -```php -Flight::stop(); -``` \ No newline at end of file diff --git a/content/v3/ja/learn/troubleshooting.md b/content/v3/ja/learn/troubleshooting.md deleted file mode 100644 index d0da8c0e..00000000 --- a/content/v3/ja/learn/troubleshooting.md +++ /dev/null @@ -1,68 +0,0 @@ -# トラブルシューティング - -このページでは、Flightを使用している際に遭遇するかもしれない一般的な問題のトラブルシューティングを支援します。 - -## 一般的な問題 - -### 404 Not Found または予期しないルートの動作 - -404 Not Found エラーが表示される場合(しかし、それが実際に存在していることを誓って、タイプミスではないと主張する場合)、実際にはこれは、単にそれをエコーするのではなく、ルートエンドポイントで値を返すことが問題である可能性があります。これは意図的に行われている理由ですが、開発者の一部には忍び込む可能性があります。 - -```php - -Flight::route('/hello', function(){ - // これが 404 Not Found エラーの原因となる可能性があります - return 'Hello World'; -}); - -// おそらく望む動作 -Flight::route('/hello', function(){ - echo 'Hello World'; -}); - -``` - -これは、ルーターに組み込まれている特別なメカニズムのために行われます。このメカニズムは、戻り出力を単一の「次のルートに移動する」として処理します。この動作は[Routing](/learn/routing#passing)セクションで文書化されています。 - -### クラスが見つかりません(オートローディングが機能していない) - -これにはいくつかの理由が考えられます。以下にいくつかの例を示しますが、[autoloading](/learn/autoloading)セクションも確認してください。 - -#### ファイル名が間違っています -最も一般的なのは、クラス名がファイル名と一致していないことです。 - -クラス名が `MyClass` の場合、ファイル名は `MyClass.php` とする必要があります。クラス名が `MyClass` でファイル名が `myclass.php` の場合、オートローダーはそれを見つけることができません。 - -#### 名前空間が正しくありません -名前空間を使用している場合、名前空間はディレクトリ構造と一致している必要があります。 - -```php -// コード - -// もし MyController が app/controllers ディレクトリにあり、名前空間が付いている場合 -// この方法は機能しません。 -Flight::route('/hello', 'MyController->hello'); - -// 以下のオプションのいずれかを選択する必要があります -Flight::route('/hello', 'app\controllers\MyController->hello'); -// または先頭に use 文がある場合 - -use app\controllers\MyController; - -Flight::route('/hello', [ MyController::class, 'hello' ]); -// また、以下のように記述することもできます -Flight::route('/hello', MyController::class.'->hello'); -// また... -Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); -``` - -#### `path()` が定義されていません - -スケルトンアプリでは、これは `config.php` ファイル内で定義されていますが、クラスを見つけるためには、使用する前に `path()` メソッドが定義されていることを確認する必要があります(おそらくディレクトリのルートに)。 - -```php - -// オートローダーにパスを追加 -Flight::path(__DIR__.'/../'); - -``` \ No newline at end of file diff --git a/content/v3/ja/learn/variables.md b/content/v3/ja/learn/variables.md deleted file mode 100644 index df437364..00000000 --- a/content/v3/ja/learn/variables.md +++ /dev/null @@ -1,34 +0,0 @@ -# 変数 - -Flight は、変数を保存してアプリケーション内のどこでも使用できるようにします。 - -```php -// あなたの変数を保存する -Flight::set('id', 123); - -// アプリケーションの別の場所で -$id = Flight::get('id'); -``` -変数が設定されているかどうかを確認するには、次のようにします。 - -```php -if (Flight::has('id')) { - // 何かを実行 -} -``` - -変数をクリアするには、次のようにします。 - -```php -// id 変数をクリア -Flight::clear('id'); - -// すべての変数をクリア -Flight::clear(); -``` - -Flight は設定目的で変数も使用します。 - -```php -Flight::set('flight.log_errors', true); -``` \ No newline at end of file diff --git a/content/v3/ja/learn/views.md b/content/v3/ja/learn/views.md deleted file mode 100644 index e2a57d8f..00000000 --- a/content/v3/ja/learn/views.md +++ /dev/null @@ -1,128 +0,0 @@ -# ビュー - -Flightは、デフォルトでいくつかの基本的なテンプレーティング機能を提供します。ビューテンプレートを表示するには、`render`メソッドをテンプレートファイルの名前とオプションのテンプレートデータで呼び出します: - -```php -Flight::render('hello.php', ['name' => 'Bob']); -``` - -渡すテンプレートデータは、自動的にテンプレートに注入され、ローカル変数のように参照できます。テンプレートファイルは単純なPHPファイルです。`hello.php`テンプレートファイルの内容が次のような場合: - -```php -Hello, ! -``` - -出力は次のようになります: - -``` -Hello, Bob! -``` - -また、`set`メソッドを使用してビュー変数を手動で設定することもできます: - -```php -Flight::view()->set('name', 'Bob'); -``` - -変数`name`は今やすべてのビューで利用可能です。したがって、次のように簡単にできます: - -```php -Flight::render('hello'); -``` - -`render`メソッド内でテンプレートの名前を指定する際に、`.php`拡張子を省略することができることに注意してください。 - -デフォルトでは、Flightはテンプレートファイルのために `views` ディレクトリを参照します。テンプレートの代替パスを設定するためには、次の設定を行います: - -```php -Flight::set('flight.views.path', '/path/to/views'); -``` - -## レイアウト - -ウェブサイトには、入れ替わるコンテンツを持つ単一のレイアウトテンプレートファイルを持つことが一般的です。レイアウトにレンダリングするコンテンツを渡すには、`render`メソッドにオプションのパラメータを渡すことができます。 - -```php -Flight::render('header', ['heading' => 'Hello'], 'headerContent'); -Flight::render('body', ['body' => 'World'], 'bodyContent'); -``` - -その後、ビューには `headerContent` と `bodyContent` という名前の保存された変数があります。次に、次のようにしてレイアウトをレンダリングできます: - -```php -Flight::render('layout', ['title' => 'Home Page']); -``` - -テンプレートファイルが次のようになっている場合: - -`header.php`: - -```php -

-``` - -`body.php`: - -```php -
-``` - -`layout.php`: - -```php - - - <?= $title ?> - - - - - - -``` - -出力は次のようになります: -```html - - - Home Page - - -

Hello

-
World
- - -``` - -## カスタムビュー - -Flightを使用すると、独自のビュークラスを登録するだけでデフォルトのビューエンジンを切り替えることができます。ビューに[Smarty](http://www.smarty.net/)テンプレートエンジンを使用する方法は次の通りです: - -```php -// Smartyライブラリの読み込み -require './Smarty/libs/Smarty.class.php'; - -// ビュークラスとしてSmartyを登録 -// Smartyをロード時に構成するためのコールバック関数も渡す -Flight::register('view', Smarty::class, [], function (Smarty $smarty) { - $smarty->setTemplateDir('./templates/'); - $smarty->setCompileDir('./templates_c/'); - $smarty->setConfigDir('./config/'); - $smarty->setCacheDir('./cache/'); -}); - -// テンプレートデータを割り当てる -Flight::view()->assign('name', 'Bob'); - -// テンプレートを表示 -Flight::view()->display('hello.tpl'); -``` - -完全性を期すために、Flightのデフォルトの`render`メソッドもオーバーライドする必要があります: - -```php -Flight::map('render', function(string $template, array $data): void { - Flight::view()->assign($data); - Flight::view()->display($template); -}); -``` \ No newline at end of file diff --git a/content/v3/ko/awesome-plugins/index.md b/content/v3/ko/awesome-plugins/index.md deleted file mode 100644 index 917bf814..00000000 --- a/content/v3/ko/awesome-plugins/index.md +++ /dev/null @@ -1,40 +0,0 @@ -# 멋진 플러그인들 - -Flight는 믿을 수 없을 만큼 확장 가능합니다. Flight 애플리케이션에 기능을 추가할 수 있는 여러 플러그인이 있습니다. 일부는 Flight 팀에서 공식적으로 지원하고 있고, 다른 것들은 시작하기를 도와주는 마이크로/라이트 라이브러리입니다. - -## 캐싱 - -캐싱은 애플리케이션을 빠르게 만드는 좋은 방법입니다. Flight와 함께 사용할 수 있는 여러 캐싱 라이브러리가 있습니다. - -- [Wruczek/PHP-File-Cache](/awesome-plugins/php-file-cache) - 가벼우며 간단하며 독립적인 PHP in-file 캐싱 클래스 - -## 디버깅 - -로컬 환경에서 개발할 때 디버깅은 중요합니다. 몇 가지 플러그인을 이용하여 디버깅 경험을 높일 수 있습니다. - -- [tracy/tracy](/awesome-plugins/tracy) - 이는 Flight와 함께 사용할 수 있는 완전한 기능을 갖춘 에러 핸들러입니다. 여러 패널을 제공하여 애플리케이션 디버깅을 도와줍니다. 또한 매우 쉽게 확장하고 자체 패널을 추가할 수 있습니다. -- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) 에러 핸들러와 함께 사용되며, 이 플러그인은 Flight 프로젝트를 위해 디버깅을 돕는 몇 가지 추가 패널을 제공합니다. - -## 데이터베이스 - -데이터베이스는 대부분의 애플리케이션의 핵심입니다. 데이터를 저장하고 검색하는 방법입니다. 일부 데이터베이스 라이브러리는 단순히 쿼리를 작성하고 실행하는 래퍼일 뿐이며, 일부는 전체 ORM입니다. - -- [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - 핵심 부분인 공식 Flight PDO 래퍼입니다. 이것은 쿼리 작성 및 실행 프로세스를 단순화하기 위한 간단한 래퍼입니다. ORM이 아닙니다. -- [flightphp/active-record](/awesome-plugins/active-record) - 공식 Flight ActiveRecord ORM/Mapper입니다. 데이터를 쉽게 검색하고 저장할 수 있는 훌륭한 작은 라이브러리입니다. - -## 세션 - -세션은 API에는 그리 유용하지 않지만, 웹 애플리케이션을 구축할 때, 상태 및 로그인 정보를 유지하는 데 필수적일 수 있습니다. - -- [Ghostff/Session](/awesome-plugins/session) - PHP 세션 관리자 (비차단, 플래시, 세그먼트, 세션 암호화). PHP open_ssl을 사용하여 세션 데이터의 선택적 암호화/복호화를 수행합니다. - -## 템플릿 - -템플릿은 UI가 있는 모든 웹 애플리케이션의 핵심입니다. Flight와 함께 사용할 수 있는 여러 템플릿 엔진이 있습니다. - -- [flightphp/core View](/learn#views) - 핵심의 매우 기본적인 템플릿 엔진입니다. 프로젝트에 여러 페이지가 있는 경우 권장되지 않습니다. -- [latte/latte](/awesome-plugins/latte) - Latte는 매우 쉽게 사용할 수 있으며 PHP 구문에 더 가까운 템플릿 엔진입니다. Twig나 Smarty보다 확장하고 자체 필터와 함수를 추가하기도 매우 쉽습니다. - -## 기여 - -공유하고 싶은 플러그인이 있나요? 이것을 목록에 추가하려면 풀 리퀘스트를 제출하세요! \ No newline at end of file diff --git a/content/v3/ko/awesome-plugins/pdo_wrapper.md b/content/v3/ko/awesome-plugins/pdo_wrapper.md deleted file mode 100644 index 65c19a1d..00000000 --- a/content/v3/ko/awesome-plugins/pdo_wrapper.md +++ /dev/null @@ -1,119 +0,0 @@ -# PdoWrapper PDO 도우미 클래스 - -Flight은 PDO를 위한 도우미 클래스와 함께 제공됩니다. 이를 통해 데이터베이스를 쉽게 쿼리할 수 있으며, 모든 준비/실행/fetchAll() 관련 기능이 포함되어 있습니다. 데이터베이스 쿼리를 간단하게 만들어줍니다. 각 행 결과는 Flight Collection 클래스로 반환되며, 배열 구문이나 객체 구문을 사용하여 데이터에 액세스할 수 있습니다. - -## PDO 도우미 클래스 등록 - -```php -// PDO 도우미 클래스 등록 -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 - ] -]); -``` - -## 사용법 -이 객체는 PDO를 확장하므로 모든 일반 PDO 메서드를 사용할 수 있습니다. 데이터베이스 쿼리를 보다 쉽게 만들기 위해 다음 메서드가 추가되었습니다: - -### `runQuery(string $sql, array $params = []): PDOStatement` -INSERT, UPDATE 또는 while 루프에서 SELECT를 사용할 경우에 사용합니다 - -```php -$db = Flight::db(); -$statement = $db->runQuery("SELECT * FROM table WHERE something = ?", [ $something ]); -while($row = $statement->fetch()) { - // ... -} - -// 또는 데이터베이스에 쓰기 -$db->runQuery("INSERT INTO table (name) VALUES (?)", [ $name ]); -$db->runQuery("UPDATE table SET name = ? WHERE id = ?", [ $name, $id ]); -``` - -### `fetchField(string $sql, array $params = []): mixed` -쿼리에서 첫 번째 필드를 가져옵니다 - -```php -$db = Flight::db(); -$count = $db->fetchField("SELECT COUNT(*) FROM table WHERE something = ?", [ $something ]); -``` - -### `fetchRow(string $sql, array $params = []): array` -쿼리에서 한 행을 가져옵니다 - -```php -$db = Flight::db(); -$row = $db->fetchRow("SELECT id, name FROM table WHERE id = ?", [ $id ]); -echo $row['name']; -// 또는 -echo $row->name; -``` - -### `fetchAll(string $sql, array $params = []): array` -쿼리에서 모든 행을 가져옵니다 - -```php -$db = Flight::db(); -$rows = $db->fetchAll("SELECT id, name FROM table WHERE something = ?", [ $something ]); -foreach($rows as $row) { - echo $row['name']; - // 또는 - echo $row->name; -} -``` - -## `IN()` 구문과 관련된 참고 사항 -이 도우미에는 `IN()` 문을 위한 유용한 래퍼도 포함되어 있습니다. `IN()`에 대한 플레이스홀더로 물음표 하나만 전달하고 값을 배열로 전달할 수 있습니다. 이를 이용하면 다음과 같이 보일 수 있습니다: - -```php -$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 ]); -``` - -## 전체 예제 - -```php -// 예제 경로 및 이 래퍼를 사용하는 방법 -Flight::route('/users', function () { - // 모든 사용자 가져오기 - $users = Flight::db()->fetchAll('SELECT * FROM users'); - - // 모든 사용자 스트림 - $statement = Flight::db()->runQuery('SELECT * FROM users'); - while ($user = $statement->fetch()) { - echo $user['name']; - // 또는 echo $user->name; - } - - // 단일 사용자 가져오기 - $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); - - // 단일 값 가져오기 - $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); - - // 도움이 되는 IN() 구문 (IN이 대문자인지 확인해주세요) - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); - // 아래와 같이도 할 수 있습니다 - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [ '1,2,3,4,5']); - - // 새로운 사용자 삽입 - Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']); - $insert_id = Flight::db()->lastInsertId(); - - // 사용자 업데이트 - Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]); - - // 사용자 삭제 - Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]); - - // 영향 받은 행 수 가져오기 - $statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']); - $affected_rows = $statement->rowCount(); - -}); -``` \ No newline at end of file diff --git a/content/v3/ko/install.md b/content/v3/ko/install.md deleted file mode 100644 index 5bbd6276..00000000 --- a/content/v3/ko/install.md +++ /dev/null @@ -1,64 +0,0 @@ -# 설치 - -## 파일 다운로드 - -만약 [Composer](https://getcomposer.org)를 사용하고 있다면, 다음 명령어를 실행할 수 있습니다: - -```bash -composer require flightphp/core -``` - -또는 파일을 직접 [다운로드](https://github.com/flightphp/core/archive/master.zip)하여 웹 디렉토리에 압축을 푸십시오. - -## 웹서버 구성 - -### Apache -Apache를 위해, 다음과 같이 `.htaccess` 파일을 편집하십시오: - -```apacheconf -RewriteEngine On -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule ^(.*)$ index.php [QSA,L] -``` - -> **참고**: flight를 하위 디렉토리에서 사용해야 한다면, `RewriteEngine On` 다음에 줄을 추가하세요. -> `RewriteBase /subdir/` - -> **참고**: db 또는 환경 파일과 같은 모든 서버 파일을 보호해야 한다면, 아래 내용을 `.htaccess` 파일에 넣으십시오: - -```apacheconf -RewriteEngine On -RewriteRule ^(.*)$ index.php -``` - -### Nginx - -Nginx를 위해, 다음을 서버 선언에 추가하십시오: - -```nginx -server { - location / { - try_files $uri $uri/ /index.php; - } -} -``` - -## `index.php` 파일 생성 - -```php -getTraceAsString(); -}); -``` - -기본적으로 오류는 웹 서버에 기록되지 않습니다. 이를 활성화하여 변경할 수 있습니다: - -```php -Flight::set('flight.log_errors', true); -``` - -## 찾을 수 없음 - -URL을 찾을 수 없을 때, Flight는 `notFound` 메서드를 호출합니다. -기본 동작은 간단한 메시지와 함께 `HTTP 404 찾을 수 없음` 응답을 보내는 것입니다. - -사용자 정의로이 동작을 재정의 할 수 있습니다: - -```php -Flight::map('notFound', function () { - // 찾을 수 없음 처리 -}); -``` \ No newline at end of file diff --git a/content/v3/ko/learn/frameworkinstance.md b/content/v3/ko/learn/frameworkinstance.md deleted file mode 100644 index a75feab1..00000000 --- a/content/v3/ko/learn/frameworkinstance.md +++ /dev/null @@ -1,17 +0,0 @@ -# 프레임워크 인스턴스 - -글로벌 정적 클래스로 Flight를 실행하는 대신 선택적으로 객체 인스턴스로 실행할 수 있습니다. - -```php -require 'flight/autoload.php'; - -$app = Flight::app(); - -$app->route('/', function () { - echo '안녕 세계!'; -}); - -$app->start(); -``` - -정적 메서드를 호출하는 대신 Engine 객체의 동일한 이름을 가진 인스턴스 메서드를 호출합니다. \ No newline at end of file diff --git a/content/v3/ko/learn/frameworkmethods.md b/content/v3/ko/learn/frameworkmethods.md deleted file mode 100644 index c2cdc2f4..00000000 --- a/content/v3/ko/learn/frameworkmethods.md +++ /dev/null @@ -1,43 +0,0 @@ -```ko -# 프레임워크 메소드 - -Flight은 사용하기 쉽고 이해하기 쉽게 설계되었습니다. 다음은 프레임워크의 완전한 -메소드 세트입니다. 이는 일반적인 정적 메소드인 코어 메소드와 필터링하거나 재정의할 수 있는 -매핑된 메소드인 확장 가능한 메소드로 구성되어 있습니다. - -## 코어 메소드 - -```php -Flight::map(string $name, callable $callback, bool $pass_route = false) // 사용자 정의 프레임워크 메소드를 생성합니다. -Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // 클래스를 프레임워크 메소드에 등록합니다. -Flight::before(string $name, callable $callback) // 프레임워크 메소드 앞에 필터를 추가합니다. -Flight::after(string $name, callable $callback) // 프레임워크 메소드 뒤에 필터를 추가합니다. -Flight::path(string $path) // 클래스의 자동로딩을 위한 경로를 추가합니다. -Flight::get(string $key) // 변수를 가져옵니다. -Flight::set(string $key, mixed $value) // 변수를 설정합니다. -Flight::has(string $key) // 변수가 설정되어 있는지 확인합니다. -Flight::clear(array|string $key = []) // 변수를 지웁니다. -Flight::init() // 프레임워크를 기본 설정으로 초기화합니다. -Flight::app() // 어플리케이션 객체 인스턴스를 가져옵니다. -``` - -## 확장 가능한 메소드 - -```php -Flight::start() // 프레임워크를 시작합니다. -Flight::stop() // 프레임워크를 중지하고 응답을 보냅니다. -Flight::halt(int $code = 200, string $message = '') // 선택적 상태 코드와 메시지로 프레임워크를 중지합니다. -Flight::route(string $pattern, callable $callback, bool $pass_route = false) // URL 패턴을 콜백에 매핑합니다. -Flight::group(string $pattern, callable $callback) // URL을 위한 그룹을 만듭니다. 패턴은 문자열이어야 합니다. -Flight::redirect(string $url, int $code) // 다른 URL로 리다이렉트합니다. -Flight::render(string $file, array $data, ?string $key = null) // 템플릿 파일을 렌더링합니다. -Flight::error(Throwable $error) // HTTP 500 응답을 보냅니다. -Flight::notFound() // HTTP 404 응답을 보냅니다. -Flight::etag(string $id, string $type = 'string') // ETag HTTP 캐싱을 수행합니다. -Flight::lastModified(int $time) // 마지막으로 수정된 HTTP 캐싱을 수행합니다. -Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // JSON 응답을 보냅니다. -Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // JSONP 응답을 보냅니다. -``` - -`map` 및 `register`로 추가된 사용자 정의 메소드는 필터링할 수도 있습니다. -``` \ No newline at end of file diff --git a/content/v3/ko/learn/httpcaching.md b/content/v3/ko/learn/httpcaching.md deleted file mode 100644 index e9b6e479..00000000 --- a/content/v3/ko/learn/httpcaching.md +++ /dev/null @@ -1,27 +0,0 @@ -# HTTP 캐싱 - -Flight은 HTTP 레벨 캐싱을 내장 지원합니다. 캐싱 조건이 충족되면, Flight은 HTTP `304 Not Modified` 응답을 반환합니다. 클라이언트가 동일한 리소스를 요청할 때, 그들은 로컬로 캐시된 버전을 사용하라는 메시지를 받게 됩니다. - -## Last-Modified - -`lastModified` 메서드를 사용하여 UNIX 타임스탬프를 전달하여 페이지가 마지막으로 수정된 날짜와 시간을 설정할 수 있습니다. 클라이언트는 마지막 수정 값이 변경될 때까지 캐시를 계속 사용합니다. - -```php -Flight::route('/news', function () { - Flight::lastModified(1234567890); - echo '이 컨텐츠는 캐시될 것입니다.'; -}); -``` - -## ETag - -`ETag` 캐싱은 `Last-Modified`와 유사하지만 리소스에 대해 원하는 아이디를 지정할 수 있습니다: - -```php -Flight::route('/news', function () { - Flight::etag('my-unique-id'); - echo '이 컨텐츠는 캐시될 것입니다.'; -}); -``` - -`lastModified` 또는 `etag` 중 하나를 호출하면 캐시 값을 설정하고 확인합니다. 요청 사이에 캐시 값이 동일하면, Flight은 즉시 `HTTP 304` 응답을 보내고 처리를 중지합니다. \ No newline at end of file diff --git a/content/v3/ko/learn/overriding.md b/content/v3/ko/learn/overriding.md deleted file mode 100644 index 93142d36..00000000 --- a/content/v3/ko/learn/overriding.md +++ /dev/null @@ -1,25 +0,0 @@ -# 재정의 - -Flight는 코드를 수정하지 않고도 기본 기능을 사용자 정의하여 필요에 맞게 재정의할 수 있도록 합니다. - -예를 들어, Flight가 URL을 경로에 매핑할 수 없는 경우, `notFound` 메서드를 호출하여 일반적인 `HTTP 404` 응답을 보냅니다. 이 동작은 `map` 메서드를 사용하여 재정의할 수 있습니다: - -```php -Flight::map('notFound', function() { - // 사용자 정의 404 페이지 표시 - include 'errors/404.html'; -}); -``` - -또한 Flight는 프레임워크의 핵심 구성 요소를 교체할 수 있도록 합니다. -예를 들어 기본 Router 클래스를 사용자 정의 클래스로 교체할 수 있습니다: - -```php -// 사용자 정의 클래스를 등록 -Flight::register('router', MyRouter::class); - -// Flight가 Router 인스턴스를 로드할 때, 사용자 정의 클래스가 로드됩니다 -$myrouter = Flight::router(); -``` - -그러나 `map` 및 `register`와 같은 프레임워크 메서드는 재정의할 수 없습니다. 이를 시도하면 오류가 발생합니다. \ No newline at end of file diff --git a/content/v3/ko/learn/redirects.md b/content/v3/ko/learn/redirects.md deleted file mode 100644 index 3fd6ba93..00000000 --- a/content/v3/ko/learn/redirects.md +++ /dev/null @@ -1,13 +0,0 @@ -# 리다이렉트 - -새 URL을 전달하여 `redirect` 메서드를 사용하여 현재 요청을 리다이렉트할 수 있습니다: - -```php -Flight::redirect('/new/location'); -``` - -기본적으로 Flight는 HTTP 303 상태 코드를 보냅니다. 선택적으로 사용자 정의 코드를 설정할 수 있습니다: - -```php -Flight::redirect('/new/location', 401); -``` \ No newline at end of file diff --git a/content/v3/ko/learn/stopping.md b/content/v3/ko/learn/stopping.md deleted file mode 100644 index 2b551913..00000000 --- a/content/v3/ko/learn/stopping.md +++ /dev/null @@ -1,19 +0,0 @@ -# 중지 - -`halt` 메소드를 호출하여 언제든지 프레임워크를 중지할 수 있습니다: - -```php -Flight::halt(); -``` - -선택적으로 `HTTP` 상태 코드와 메시지를 지정할 수도 있습니다: - -```php -Flight::halt(200, '잠시 후에 돌아오겠습니다...'); -``` - -`halt`를 호출하면 해당 시점까지의 모든 응답 내용이 폐기됩니다. 프레임워크를 중지하고 현재 응답을 출력하려면 `stop` 메소드를 사용하세요: - -```php -Flight::stop(); -``` \ No newline at end of file diff --git a/content/v3/ko/learn/troubleshooting.md b/content/v3/ko/learn/troubleshooting.md deleted file mode 100644 index 7181bb09..00000000 --- a/content/v3/ko/learn/troubleshooting.md +++ /dev/null @@ -1,68 +0,0 @@ -# 문제 해결 - -이 페이지는 Flight를 사용할 때 마주칠 수 있는 일반적인 문제를 해결하는 데 도움이 될 것입니다. - -## 일반적인 문제 - -### 404 Not Found 또는 예기치 않은 경로 동작 - -404 Not Found 오류를 보고 있다면(하지만 정말 있고 오타가 아니라고 맹세한다면) 실제로는 route 끝점에서 값을 반환하는 것보다 그냥 출력하는 것이 문제가 될 수 있습니다. 그 이유는 의도적이지만 개발자들에겐 뜻밖의 문제가 될 수 있습니다. - -```php - -Flight::route('/hello', function(){ - // 이것이 404 Not Found 오류를 일으킬 수 있음 - return 'Hello World'; -}); - -// 아마 원하던 것 -Flight::route('/hello', function(){ - echo 'Hello World'; -}); - -``` - -이 이유는 라우터에 내장된 특별한 메커니즘 때문입니다. 이 메커니즘은 반환 값을 다음 route로 "이동"으로 처리합니다. 이 동작은 [Routing](/learn/routing#passing) 섹션에서 문서화된 대로 확인할 수 있습니다. - -### 클래스를 찾을 수 없음 (자동로딩이 작동하지 않음) - -이 문제가 발생하지 않는 이유는 몇 가지가 있을 수 있습니다. 아래에는 일부 예가 나와 있지만 반드시 [autoloading](/learn/autoloading) 섹션도 확인해야 합니다. - -#### 잘못된 파일 이름 -가장 일반적인 이유는 클래스 이름이 파일 이름과 일치하지 않는 경우입니다. - -`MyClass`라는 클래스가 있다면 파일 이름은 `MyClass.php`이어야 합니다. `MyClass`라는 클래스가 있고 파일 이름이 `myclass.php`인 경우에는 오토로더가 해당 파일을 찾지 못할 것입니다. - -#### 잘못된 네임스페이스 -네임스페이스를 사용하는 경우 네임스페이스는 디렉토리 구조와 일치해야 합니다. - -```php -// 코드 - -// 만약 MyController가 app/controllers 디렉토리에 있고 네임스페이스가 있는 경우 -// 이 방식은 작동하지 않습니다. -Flight::route('/hello', 'MyController->hello'); - -// 다음 중 하나를 선택해야 합니다 -Flight::route('/hello', 'app\controllers\MyController->hello'); -// 또는 위쪽에 use 문이 있는 경우 - -use app\controllers\MyController; - -Flight::route('/hello', [ MyController::class, 'hello' ]); -// 또한 다음과 같이 작성할 수 있음 -Flight::route('/hello', MyController::class.'->hello'); -// 그리고... -Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); -``` - -#### `path()`가 정의되지 않음 - -스켈레톤 앱에서 이 기능은 `config.php` 파일 내에서 정의되어 있지만 클래스를 찾기 위해서는 `path()` 메소드가 정의되어 있는지 확인해야 합니다(아마도 디렉토리 루트에). - -```php - -// 오토로더에 경로 추가 -Flight::path(__DIR__.'/../'); - -``` \ No newline at end of file diff --git a/content/v3/ko/learn/variables.md b/content/v3/ko/learn/variables.md deleted file mode 100644 index 5157ec4e..00000000 --- a/content/v3/ko/learn/variables.md +++ /dev/null @@ -1,35 +0,0 @@ -# 변수 - -Flight은 애플리케이션 내의 어디에서나 사용할 수 있도록 변수를 저장할 수 있게 해줍니다. - -```php -// 변수 저장하기 -Flight::set('id', 123); - -// 애플리케이션의 다른 곳에서 -$id = Flight::get('id'); -``` - -변수가 설정되었는지 확인하려면 다음을 수행할 수 있습니다: - -```php -if (Flight::has('id')) { - // 무언가를 수행 -} -``` - -다음을 수행하여 변수를 지울 수 있습니다: - -```php -// id 변수 지우기 -Flight::clear('id'); - -// 모든 변수 지우기 -Flight::clear(); -``` - -Flight은 구성 목적으로도 변수를 사용합니다. - -```php -Flight::set('flight.log_errors', true); -``` \ No newline at end of file diff --git a/content/v3/ko/learn/views.md b/content/v3/ko/learn/views.md deleted file mode 100644 index e6ab158e..00000000 --- a/content/v3/ko/learn/views.md +++ /dev/null @@ -1,131 +0,0 @@ -# 뷰(Views) - -Flight는 기본적인 템플릿 기능을 제공합니다. 뷰 -템플릿을 표시하려면 템플릿 파일의 이름과 선택적인 -템플릿 데이터를 사용하여 `render` 메소드를 호출하십시오: - -```php -Flight::render('hello.php', ['name' => 'Bob']); -``` - -전달한 템플릿 데이터는 자동으로 템플릿에 주입되며 -로컬 변수처럼 참조할 수 있습니다. 템플릿 파일은 단순히 PHP 파일입니다. `hello.php` 템플릿 파일의 내용이 다음과 같다면: - -```php -Hello, ! -``` - -출력은 다음과 같을 것입니다: - -``` -Hello, Bob! -``` - -뷰 변수를 수동으로 설정할 수도 있습니다. - -```php -Flight::view()->set('name', 'Bob'); -``` - -변수 `name`은 이제 모든 뷰에서 사용할 수 있습니다. 따라서 다음과 같이 할 수 있습니다: - -```php -Flight::render('hello'); -``` - -`render` 메소드에서 템플릿 이름을 지정할 때 `.php` 확장자를 생략할 수 있음을 유의하십시오. - -Flight는 기본적으로 템플릿 파일을 위해 `views` 디렉토리를 찾습니다. 다음 구성을 설정하여 템플릿의 대체 경로를 설정할 수 있습니다: - -```php -Flight::set('flight.views.path', '/path/to/views'); -``` - -## 레이아웃(Layouts) - -웹 사이트에 단일 레이아웃 템플릿 파일이 있는 것이 일반적입니다. 레이아웃에 사용할 콘텐츠를 렌더링하려면 `render` 메소드에 선택적 매개변수를 전달할 수 있습니다. - -```php -Flight::render('header', ['heading' => 'Hello'], 'headerContent'); -Flight::render('body', ['body' => 'World'], 'bodyContent'); -``` - -그럼 뷰는 `headerContent`와 `bodyContent` 라는 변수로 저장되어 있을 것입니다. 그럼 다음과 같이 레이아웃을 렌더링할 수 있습니다: - -```php -Flight::render('layout', ['title' => 'Home Page']); -``` - -다음과 같은 템플릿 파일이 있다면: - -`header.php`: - -```php -

-``` - -`body.php`: - -```php -
-``` - -`layout.php`: - -```php - - - <?= $title ?> - - - - - - -``` - -출력은 다음과 같을 것입니다: -```html - - - Home Page - - -

Hello

-
World
- - -``` - -## 사용자 정의 뷰(Custom Views) - -Flight를 통해 기본 뷰 엔진을 간단히 교체할 수 있습니다. 여기서는 [Smarty](http://www.smarty.net/) 템플릿 엔진을 뷰로 사용하는 방법을 보여드리겠습니다: - -```php -// Smarty 라이브러리 로드 -require './Smarty/libs/Smarty.class.php'; - -// 뷰 클래스로 Smarty 등록 -// 또한 로드 시 Smarty를 구성하는 콜백 함수를 전달합니다 -Flight::register('view', Smarty::class, [], function (Smarty $smarty) { - $smarty->setTemplateDir('./templates/'); - $smarty->setCompileDir('./templates_c/'); - $smarty->setConfigDir('./config/'); - $smarty->setCacheDir('./cache/'); -}); - -// 템플릿 데이터 할당 -Flight::view()->assign('name', 'Bob'); - -// 템플릿 표시 -Flight::view()->display('hello.tpl'); -``` - -완전성을 위해 Flight의 기본 `render` 메소드를 재정의해야 합니다: - -```php -Flight::map('render', function(string $template, array $data): void { - Flight::view()->assign($data); - Flight::view()->display($template); -}); -``` \ No newline at end of file diff --git a/content/v3/lv/awesome-plugins/index.md b/content/v3/lv/awesome-plugins/index.md deleted file mode 100644 index e2b3f772..00000000 --- a/content/v3/lv/awesome-plugins/index.md +++ /dev/null @@ -1,40 +0,0 @@ -# Lieliskie spraudņi - -Flight ir ļoti paplašināms. Ir daudz spraudņu, kas var tikt izmantoti, lai pievienotu funkcionalitāti jūsu Flight lietojumprogrammai. Daži no tiem oficiāli tiek atbalstīti no Flight komandas, savukārt citi ir mikro/lite bibliotēkas, lai palīdzētu jums sākt. - -## Kešošana - -Kešošana ir lieliska veids, kā paātrināt jūsu lietojumprogrammu. Ir daudz kešošanas bibliotēku, kas var tikt izmantotas ar Flight. - -- [Wruczek/PHP-File-Cache](/awesome-plugins/php-file-cache) - Gaiša, vienkārša un neatkarīga PHP faila kešošanas klase - -## Dīversija - -Dīversija ir būtiska, kad jūs izstrādājat savā lokālajā vide. Ir daži spraudņi, kas var uzlabot jūsu dīversijas pieredzi. - -- [tracy/tracy](/awesome-plugins/tracy) - Tā ir pilna funkcionāla kļūdu apstrāde, kas var tikt izmantota ar Flight. Tā disponē ar daudzām paneļu, kas var palīdzēt jums novērst jūsu lietojumprogrammas kļūdas. To ir arī ļoti viegli paplašināt un pievienot savus paneļus. -- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Lietots ar [Tracy](/awesome-plugins/tracy) kļūdu apstrādātāju, šis spraudnis pievieno dažus papildu paneļus, lai palīdzētu ar dīversijas konkrēti Flight projektos. - -## Datubāzes - -Datubāzes ir vairumam lietojumprogrammu pamats. Tā ir veids, kā saglabāt un atgūt datus. Dažas datubāzu bibliotēkas vienkārši ir wrapperi, lai rakstītu vaicājumus, bet dažas ir pilnvērtīgi ORM. - -- [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Oficiālais Flight PDO apvalks, kas ir daļa no kodola. Šis ir vienkāršs apvalks, lai palīdzētu vienkāršot vaicājumu rakstīšanas un izpildes procesu. Tas nav ORM. -- [flightphp/active-record](/awesome-plugins/active-record) - Oficiālais Flight ActiveRecord ORM/Mapper. Lieliska maza bibliotēka, lai viegli atgūtu un saglabātu datus jūsu datubāzē. - -## Sesija - -Sesijas nav īsti noderīgas API, bet, lai izveidotu tīmekļa lietojumprogrammu, sesijas var būt būtiskas, lai saglabātu stāvokli un pieteikšanās informāciju. - -- [Ghostff/Session](/awesome-plugins/session) - PHP sesiju pārvaldītājs (nebloķējošs, flash, segments, sesijas šifrēšana). Izmanto PHP open_ssl sesiju datu izvēlēti šifrēt/šifrēt. - -## Templēšana - -Templēšana ir būtiska jebkurai tīmekļa lietojumprogrammai ar lietotāja saskarni. Ir daudz templēšanas dzinēju, kas var tikt izmantoti ar Flight. - -- [flightphp/core View](/learn#views) - Tas ir ļoti pamata templēšanas dzinējs, kas ir daļa no kodola. Nav ieteicams izmantot to, ja jūsu projektā ir vairāk nekā dažas lapas. -- [latte/latte](/awesome-plugins/latte) - Latte ir pilna funkcionāla templēšanas dzinējs, kas ir ļoti viegli lietojams un jūtas tuvāks PHP sintaksei nekā Twig vai Smarty. To ir arī ļoti viegli paplašināt un pievienot savus filtrus un funkcijas. - -## Contributing - -Vai jums ir spraudnis, ko vēlaties koplietot? Iesniedziet pieprasījumu pull, lai to pievienotu sarakstam! \ No newline at end of file diff --git a/content/v3/lv/awesome-plugins/pdo_wrapper.md b/content/v3/lv/awesome-plugins/pdo_wrapper.md deleted file mode 100644 index 3b841f3d..00000000 --- a/content/v3/lv/awesome-plugins/pdo_wrapper.md +++ /dev/null @@ -1,119 +0,0 @@ -# PdoWrapper PDO Palīgklase - -Flight ir palīgklase PDO. Tas ļauj viegli vaicāt savu datu bāzi ar visu sagatavoto/izpildīto/fetchAll() šaubību. Tas ievērojami vienkāršo, kā jūs varat vaicāt savu datu bāzi. Katra rindas rezultāts tiek atgriezts kā "Flight Collection" klase, kas ļauj piekļūt datiem, izmantojot masīva sintaksi vai objekta sintaksi. - -## Reģistrējot PDO Palīgklasi - -```php -// Reģistrējiet PDO palīgklasi -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 - ] -]); -``` - -## Lietošana -Šis objekts paplašina PDO, tāpēc visi normālie PDO metodēs ir pieejami. Tika pievienotas šādas metodes, lai atvieglotu datu bāzes vaicājumu veikšanu: - -### `runQuery(string $sql, array $params = []): PDOStatement` -Izmantojiet šo INSERTS, UPDATE vai ja plānojat izmantot SELECT cilpas iekšā - -```php -$db = Flight::db(); -$statement = $db->runQuery("SELECT * FROM table WHERE something = ?", [ $something ]); -while($row = $statement->fetch()) { - // ... -} - -// Vai ierakstiet datubāzē -$db->runQuery("INSERT INTO table (name) VALUES (?)", [ $name ]); -$db->runQuery("UPDATE table SET name = ? WHERE id = ?", [ $name, $id ]); -``` - -### `fetchField(string $sql, array $params = []): mixed` -Izvelk pirmo lauku no vaicājuma - -```php -$db = Flight::db(); -$count = $db->fetchField("SELECT COUNT(*) FROM table WHERE something = ?", [ $something ]); -``` - -### `fetchRow(string $sql, array $params = []): array` -Izvelk vienu rindu no vaicājuma - -```php -$db = Flight::db(); -$row = $db->fetchRow("SELECT id, name FROM table WHERE id = ?", [ $id ]); -echo $row['name']; -// vai -echo $row->name; -``` - -### `fetchAll(string $sql, array $params = []): array` -Izvelk visus rindas no vaicājuma - -```php -$db = Flight::db(); -$rows = $db->fetchAll("SELECT id, name FROM table WHERE something = ?", [ $something ]); -foreach($rows as $row) { - echo $row['name']; - // vai - echo $row->name; -} -``` - -## Piezīme par `IN()` sintaksi -Tai ir noderīga aploksne `IN()` apgalvojumiem. Vienu jautājuma zīmi vienkārši varat padot kā vietotni `IN()` un pēc tam masīvu ar vērtībām. Šeit ir piemērs, kā tas varētu izskatīties: - -```php -$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 ]); -``` - -## Pilns piemērs - -```php -// Piemēra maršruts un kā jūs izmantotu šo apvalku -Flight::route('/users', function () { - // Iegūt visus lietotājus - $users = Flight::db()->fetchAll('SELECT * FROM users'); - - // Plūsmas visi lietotāji - $statement = Flight::db()->runQuery('SELECT * FROM users'); - while ($user = $statement->fetch()) { - echo $user['name']; - // vai echo $user->name; - } - - // Iegūt vienu lietotāju - $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); - - // Iegūt vienu vērtību - $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); - - // Speciālā IN() sintakse, lai palīdzētu (pārliecinieties, ka IN ir lieli burti) - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); - // jūs varētu arī darīt šo - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [ '1,2,3,4,5']); - - // Ievietot jaunu lietotāju - Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']); - $insert_id = Flight::db()->lastInsertId(); - - // Atjaunināt lietotāju - Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]); - - // Dzēst lietotāju - Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]); - - // Iegūt ietekmēto rindu skaitu - $statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']); - $affected_rows = $statement->rowCount(); - -}); -``` \ No newline at end of file diff --git a/content/v3/lv/install.md b/content/v3/lv/install.md deleted file mode 100644 index bfeed578..00000000 --- a/content/v3/lv/install.md +++ /dev/null @@ -1,65 +0,0 @@ -# Instalācija - -## Lejupielādēt failus. - -Ja izmantojat [Composer](https://getcomposer.org), varat izpildīt sekojošo komandu: - -```bash -composer require flightphp/core -``` - -VAI arī varat [lejupielādēt failus](https://github.com/flightphp/core/archive/master.zip) tieši un izvilkt tos savā tīmekļa direktorijā. - -## Konfigurējiet savu tīmekļa serveri. - -### Apache -Lai Apache, rediģējiet savu `.htaccess` failu ar šādu informāciju: - -```apacheconf -RewriteEngine On -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule ^(.*)$ index.php [QSA,L] -``` - -> **Piezīme**: Ja jums ir nepieciešams izmantot Flight apakškatalogu, pievienojiet rindu -> `RewriteBase /apakskatalogs/` tieši pēc `RewriteEngine On`. - -> **Piezīme**: Ja vēlaties aizsargāt visus servera failus, piemēram, db vai env failu. -> Ievietojiet šo savā `.htaccess` failā: - -```apacheconf -RewriteEngine On -RewriteRule ^(.*)$ index.php -``` - -### Nginx - -Lai Nginx, pievienojiet sekojošo savā servera deklarācijā: - -```nginx -server { - location / { - try_files $uri $uri/ /index.php; - } -} -``` - -## Izveidojiet savu `index.php` failu. - -```php -getTraceAsString(); -}); -``` - -Pēc noklusējuma kļūdas netiek reģistrētas tīmekļa serverī. Jūs varat to iespējot, mainot konfigurāciju: - -```php -Flight::set('flight.log_errors', true); -``` - -## Nav Atrasts - -Kad URL nav atrodams, Flight izsauc `notFound` metodi. Noklusējuma uzvedība ir nosūtīt `HTTP 404 Nav atrasts` atbildi ar vienkāršu ziņojumu. - -Jūs varat pārrakstīt šo uzvedību savām vajadzībām: - -```php -Flight::map('notFound', function () { - // Apstrādāt nav atrasts -}); -``` \ No newline at end of file diff --git a/content/v3/lv/learn/frameworkinstance.md b/content/v3/lv/learn/frameworkinstance.md deleted file mode 100644 index 035bfc55..00000000 --- a/content/v3/lv/learn/frameworkinstance.md +++ /dev/null @@ -1,19 +0,0 @@ -# Framework instances - -Vietā zīmēt `Flight` kā globālu statisku klasi, Jūs varat izpildespienākumu -palaižot kā objekta instanci. - -```php -require 'flight/autoload.php'; - -$app = Flight::app(); - -$app->route('/', function () { - echo 'sveika, pasaule!'; -}); - -$app->start(); -``` - -Tātad vietā, lai izsauktu statisko metodi, Jūs izsauktu instances metodi ar -tādu pašu nosaukumu uz Dzinēja objektu. \ No newline at end of file diff --git a/content/v3/lv/learn/frameworkmethods.md b/content/v3/lv/learn/frameworkmethods.md deleted file mode 100644 index 744bd284..00000000 --- a/content/v3/lv/learn/frameworkmethods.md +++ /dev/null @@ -1,42 +0,0 @@ -# Framework Metodes - -Flight ir izstrādāts, lai būtu viegli lietojams un saprotams. Zemāk ir pilns -metožu kopums ietvariem. Tas sastāv no pamatmetodēm, kas ir parastie -statiskie metodes, un paplašināmās metodes, kas ir kartētas metodes, kurām var piemērot filtrus -vai pārrakstīt. - -## Pamatmetodes - -```php -Flight::map(virkne $nosaukums, callable $atgriezamā_virziena_funkcija, bool $ietekme_uz_marsrutu = false) // Izveido pielāgotu ietvaru metodi. -Flight::register(virkne $nosaukums, string $klase, masīvs $parametri = [], ?callable $atgriezamā_virziena_funkcija = null) // Reģistrē klasi ietvaru metodē. -Flight::before(virkne $nosaukums, callable $atgriezamā_virziena_funkcija) // Pievieno filtru pirms ietvaru metodes. -Flight::after(virkne $nosaukums, callable $atgriezamā_virziena_funkcija) // Pievieno filtru pēc ietvaru metodes. -Flight::path(virkne $ceļš) // Pievieno ceļu automātiskai klasielu ielādei. -Flight::get(virkne $atslēga) // Iegūst mainīgo. -Flight::set(virkne $atslēga, mixed $vertība) // Iestata mainīgo. -Flight::has(virkne $atslēga) // Pārbauda, vai mainīgais ir iestatīts. -Flight::clear(masīvs|virkne $atslēga = []) // Nodzēš mainīgo. -Flight::init() // Inicializē ietvaru tās noklusētajos iestatījumos. -Flight::app() // Iegūst aplikācijas objekta instanci -``` - -## Paplašināmās metodes - -```php -Flight::start() // Sāk ietvaru. -Flight::stop() // Aptur ietvaru un nosūta atbildi. -Flight::halt(int $kods = 200, virkne $ziņojums = '') // Aptur ietvaru ar neobligātu statusa kodu un ziņojumu. -Flight::route(virkne $parauga, callable $atgriezamā_virziena_funkcija, bool $ietekme_uz_marsrutu = false) // Kartē URL paraugu atpakaļsaukumam. -Flight::group(virkne $parauga, callable $atgriezamā_virziena_funkcija) // Izveido grupēšanu URL, paraugs ir jābūt virknei. -Flight::redirect(virkne $url, int $kods) // Novirza uz citu URL. -Flight::render(virkne $fails, masīvs $datus, ?string $atslēga = null) // Atveido veidnes failu. -Flight::error(Throwable $kļūda) // Nosūta HTTP 500 atbildi. -Flight::notFound() // Nosūta HTTP 404 atbildi. -Flight::etag(virkne $id, virkne $tips = 'string') // Veic ETag HTTP kešošanu. -Flight::lastModified(int $laiks) // Veic pēdējo modificēto HTTP kešošanu. -Flight::json(mixed $datus, int $kods = 200, bool $kodēt = true, virkne $kodēšanas_kopa = 'utf8', int $opcija) // Nosūta JSON atbildi. -Flight::jsonp(mixed $datus, virkne $param = 'jsonp', int $kods = 200, bool $kodēt = true, virkne $kodēšanas_kopa = 'utf8', int $opcija) // Nosūta JSONP atbildi. -``` - -Jebkuras pielāgotas metodes, kas pievienotas ar `map` un `register`, var arī tikt filtrētas. \ No newline at end of file diff --git a/content/v3/lv/learn/httpcaching.md b/content/v3/lv/learn/httpcaching.md deleted file mode 100644 index 299ee6a8..00000000 --- a/content/v3/lv/learn/httpcaching.md +++ /dev/null @@ -1,35 +0,0 @@ -# HTTP kešošana - -Flight nodrošina iebūvētu atbalstu HTTP līmeņa kešošanai. Ja kešošanas nosacījums -ir izpildīts, Flight atgriezīs HTTP `304 Nav modificēts` atbildi. Nākamajā reizē, -kad klienta pieprasīs to pašu resursu, viņiem tiks ierosināts izmantot vietējo -kešotu versiju. - -## Pēdējais modificēšanas laiks - -Jūs varat izmantot `lastModified` metodi un padot UNIX laikrādi, lai iestatītu datumu -un laiku, kad lapas tika pēdējo reizi modificētas. Klients turpinās izmantot savu kešu līdz -pēdējais modificēšanas vērtība tiks mainīta. - -```php -Flight::route('/jaunumi', function () { - Flight::lastModified(1234567890); - echo 'Šis saturs tiks kešots.'; -}); -``` - -## ETag - -`ETag` kešošana ir līdzīga `Last-Modified`, izņemot to, ka jūs varat norādīt jebkādu id, -ko vēlaties izmantot resursam: - -```php -Flight::route('/jaunumi', function () { - Flight::etag('mans-unikālais-id'); - echo 'Šis saturs tiks kešots.'; -}); -``` - -Ņemiet vērā, ka saucot gan `lastModified`, gan `etag`, tiks gan iestatīta, gan pārbaudīta -kešu vērtība. Ja kešu vērtība ir vienāda starp pieprasījumiem, Flight nekavējoties -nosūtīs `HTTP 304` atbildi un pārtrauks apstrādi. \ No newline at end of file diff --git a/content/v3/lv/learn/overriding.md b/content/v3/lv/learn/overriding.md deleted file mode 100644 index 59f99ced..00000000 --- a/content/v3/lv/learn/overriding.md +++ /dev/null @@ -1,29 +0,0 @@ -# Pārrakstīšana - -Flight ļauj jums pārrakstīt tās noklusējuma funkcionalitāti, lai pielāgotu to savām vajadzībām, -neiesaistoties tajā nekādā veidā. - -Piemēram, kad Flight nevar sakrist ar URL adresi maršrutam, tas izsauc `notFound` -metodi, kas nosūta vispārēju `HTTP 404` atbildi. Jūs varat pārrakstīt šo darbību -izmantojot `map` metodi: - -```php -Flight::map('notFound', function() { - // Parādīt pielāgoto 404. lapu - include 'errors/404.html'; -}); -``` - -Flight arī ļauj jums aizstāt pamata framework komponentes. -Piemēram, jūs varat aizstāt noklusējuma Router klasi ar savu pielāgoto klasi: - -```php -// Reģistrējiet savu pielāgoto klasi -Flight::register('router', MyRouter::class); - -// Kad Flight ielādē Router instanci, tā ielādēs jūsu klasi -$myrouter = Flight::router(); -``` - -Framework metodēm, piemēram, `map` un `register`, tomēr nevar pārrakstīt. Jums -iegūsiet kļūdu, ja mēģināsiet to izdarīt. \ No newline at end of file diff --git a/content/v3/lv/learn/redirects.md b/content/v3/lv/learn/redirects.md deleted file mode 100644 index 64166c09..00000000 --- a/content/v3/lv/learn/redirects.md +++ /dev/null @@ -1,11 +0,0 @@ -# Pāradresācijas - -Jūs varat pāradresēt pašreizējo pieprasījumu, izmantojot `redirect` metodi un padodot jaunu URL: -```php -Flight::redirect('/jauna/vietas'); -``` - -Pēc noklusējuma Flight nosūta HTTP 303 statusa kodu. Jūs varat izvēlēties iestatīt pielāgotu kodu: -```php -Flight::redirect('/jauna/vietas', 401); -``` \ No newline at end of file diff --git a/content/v3/lv/learn/stopping.md b/content/v3/lv/learn/stopping.md deleted file mode 100644 index c46157cd..00000000 --- a/content/v3/lv/learn/stopping.md +++ /dev/null @@ -1,20 +0,0 @@ -# Aptur - -Jūs varat apturēt pamatstruktūru jebkurā brīdī, izsaucot `halt` metodi: - -```php -Flight::halt(); -``` - -Jūs arī varat norādīt neobligātu `HTTP` statusa kodu un ziņojumu: - -```php -Flight::halt(200, 'Jau drīz atgriezīšos...'); -``` - -Izsaukot `halt`, tiks atcelts jebkāds atbildes saturs līdz tam brīdim. Ja vēlaties apturēt -pamatstruktūru un izvadīt pašreizējo atbildi, izmantojiet `stop` metodi: - -```php -Flight::stop(); -``` \ No newline at end of file diff --git a/content/v3/lv/learn/troubleshooting.md b/content/v3/lv/learn/troubleshooting.md deleted file mode 100644 index eaa13494..00000000 --- a/content/v3/lv/learn/troubleshooting.md +++ /dev/null @@ -1,68 +0,0 @@ -# Problemløgšana - -Šī lapa palīdzēs jums novērst vispārējas problēmas, ar kurām jūs varat saskarties, izmantojot Flight. - -## Parastās problēmas - -### 404 Netika Atrasts vai Negaidīta Maršruta Uzvedība - -Ja jums tiek rādīta 404 Netika Atrasta kļūda (bet jūs zvērās par savu dzīvi, ka tā patiešām tur ir un tas nav tikai kļūda rakstīšanā), tas varētu būt problēma jums atgriežot vērtību savā maršruta gala punktā, nevis vienkārši to echojot. Šī iemesla dēļ tam ir nodoma, bet dažiem izstrādātājiem tas var nejauši notikt. - -```php -  -Flight::route('/hello', function(){ - // Tas var izraisīt 404 Netika Atrasta kļūdu - return 'Sveika, pasaule!'; -}); - -// To, iespējams, jūs vēlaties -Flight::route('/hello', function(){ - echo 'Sveika, pasaule!'; -}); -``` - -Iemesls tam ir īpaša mehānisms, kas iebūvēts maršrutētājā, kas apstrādā atgriezto izvadi kā vienu "pāreju uz nākamo maršrutu". Jūs varat redzēt šādu uzvedību dokumentācijā sadaļā [Maršrutēšana](/learn/routing#passing). - -### Klase Netika Atrasta (automašīnas ielāde nedarbojas) - -Šai problēmai var būt daži iemesli. Zemāk ir daži piemēri, bet pārliecinieties, ka jūs arī apskatāt sadaļu [automašīna](/learn/autoloading). - -#### Nepareizs Faila Nosaukums -Visbiežākais ir tas, ka klases nosaukums nesakrīt ar faila nosaukumu. - -Ja jums ir klase ar nosaukumu `ManāKlase`, tad failam vajadzētu būt nosauktam `ManāKlase.php`. Ja jums ir klase ar nosaukumu `ManāKlase` un fails ir nosaukts `manāklase.php`, -tad automātisks ielādētājs to nespēs atrast. - -#### Nepareizs Vardraba -Ja jūs izmantojat vardrabas, tad vardraba atbilst šaurmaiņa struktūrai. - -```php -// kods - -// ja jūsu ManaisKontrolieris ir app/kontrolieri direktorijā un tas ir vardrabā -// tas nestrādās. -Flight::route('/hello', 'ManaisKontrolieris->sveiki'); - -// jums būs jāizvēlas viens no šiem variantiem -Flight::route('/hello', 'app\kontrolieri\ManaisKontrolieris->sveiki'); -// vai ja jums ir lietošanas paziņojums augšā - -lieto app\kontrolieri\ManaisKontrolieris; - -Flight::route('/hello', [ ManaisKontrolieris::class, 'sveiki' ]); -// var būt arī rakstīts -Flight::route('/hello', ManaisKontrolieris::class.'->sveiki'); -// arī... -Flight::route('/hello', [ 'app\kontrolieri\ManaisKontrolieris', 'sveiki' ]); -``` - -#### `path()` nav definēta - -Skeleta lietotnē, tas ir definēts `config.php` failā, bet, lai jūsu klases tiktu atrastas, jums jāpārliecinās, ka `path()` metode ir definēta -(probablyto saka visu jūsu direktorijas saknes) pirms jūs mēģināt to izmantot. - -```php -  -// Pievienojiet ceļu autoloaderim -Flight::path(__DIR__.'/../'); -``` \ No newline at end of file diff --git a/content/v3/lv/learn/variables.md b/content/v3/lv/learn/variables.md deleted file mode 100644 index 8eebed8b..00000000 --- a/content/v3/lv/learn/variables.md +++ /dev/null @@ -1,35 +0,0 @@ -```lv -# Mainīgie - -Flight ļauj saglabāt mainīgos, lai tos varētu izmantot jebkur aplikācijā. - -```php -// Saglabā savu mainīgo -Flight::set('id', 123); - -// Citur aplikācijā -$id = Flight::get('id'); -``` -Lai pārbaudītu, vai mainīgais ir iestatīts, varat izdarīt: - -```php -if (Flight::has('id')) { - // Izdarīt kaut ko -} -``` - -Mainīgo var notīrīt: - -```php -// Notīra id mainīgo -Flight::clear('id'); - -// Notīra visus mainīgos -Flight::clear(); -``` - -Flight izmanto mainīgos arī konfigurācijas nolūkos. - -```php -Flight::set('flight.log_errors', true); -``` \ No newline at end of file diff --git a/content/v3/lv/learn/views.md b/content/v3/lv/learn/views.md deleted file mode 100644 index 5371e54c..00000000 --- a/content/v3/lv/learn/views.md +++ /dev/null @@ -1,139 +0,0 @@ -# Skati - -Flight nodrošina pamata templēšanas funkcionalitāti pēc noklusējuma. Lai parādītu skata -templātu, izsauciet `render` metodi ar templāta faila nosaukumu un opcijas -templātu datiem: - -```php -Flight::render('hello.php', ['name' => 'Bob']); -``` - -Datubāzi, ko jūs nododat iekšā, automātiski ievada templātā un var -būt atsauce kā lokāls mainīgais. Templāta faili ir vienkārši PHP faili. Ja -`hello.php` templāta faila saturs ir: - -```php -Sveiki, ! -``` - -Izvade būtu: - -``` -Sveiki, Bob! -``` - -Jūs arī varat manuāli iestatīt skata mainīgos, izmantojot set metodi: - -```php -Flight::view()->set('name', 'Bob'); -``` - -Mainīgais `name` tagad ir pieejams visos jūsu skatos. Tātad vienkārši varat darīt: - -```php -Flight::render('hello'); -``` - -Ņemiet vērā, ka norādot templāta nosaukumu render metodē, jūs varat -izlaist `.php` paplašinājumu. - -Pēc noklusējuma Flight meklēs `views` direktoriju templātu failiem. Jūs varat -iestatīt alternatīvu ceļu saviem templātiem, iestatot šādu konfigurāciju: - -```php -Flight::set('flight.views.path', '/ceļš/līdz/views'); -``` - -## Izkārtojumi - -Ir parasts, ka tīmekļa vietnēm ir viens izkārtojuma templāta fails, kurā mainās -saturs. Lai attēlotu saturu, kas jāizmanto izkārtojumā, jūs varat nodot opcijas -parametru `render` metodē. - -```php -Flight::render('header', ['heading' => 'Sveiki'], 'headerContent'); -Flight::render('body', ['body' => 'Pasaulē'], 'bodyContent'); -``` - -Jūsu skatam tad būs saglabāti mainīgie ar nosaukumiem `headerContent` un `bodyContent`. -Tad jūs varat attēlot savu izkārtojumu, darot: - -```php -Flight::render('layout', ['title' => 'Mājas lapā']); -``` - -Ja templātu faili izskatās šādi: - -`header.php`: - -```php -

-``` - -`body.php`: - -```php -
-``` - -`layout.php`: - -```php - - - <?= $title ?> - - - - - - -``` - -Izvade būtu: -```html - - - Mājas lapā - - -

Sveiki

-
Pasaulē
- - -``` - -## Pielāgoti skati - -Flight ļauj nomainīt noklusējuma skata dzinēju, vienkārši reģistrējot savu -skata klasi. Šeit ir, kā jūs izmantotu [Smarty](http://www.smarty.net/) -templāta dzinēju savām skatam: - -```php -// Ielādēt Smarty bibliotēku -require './Smarty/libs/Smarty.class.php'; - -// Reģistrējiet Smarty kā skata klasi -// Iepriekš padodot atsauces funkciju, lai konfigurētu Smarty, ielādējot -Flight::register('view', Smarty::class, [], function (Smarty $smarty) { - $smarty->setTemplateDir('./templates/'); - $smarty->setCompileDir('./templates_c/'); - $smarty->setConfigDir('./config/'); - $smarty->setCacheDir('./cache/'); -}); - -// Piešķiriet templāta datus -Flight::view()->assign('name', 'Bob'); - -// Rādīt templātu -Flight::view()->display('hello.tpl'); -``` - -Lai būtu pilnīgs, jums vajadzētu arī pārrakstīt Flight noklusējuma render metodi: - -```php -Flight::map('render', function(string $template, array $data): void { - Flight::view()->assign($data); - Flight::view()->display($template); -}); -``` \ No newline at end of file diff --git a/content/v3/pt/awesome-plugins/index.md b/content/v3/pt/awesome-plugins/index.md deleted file mode 100644 index 100599c6..00000000 --- a/content/v3/pt/awesome-plugins/index.md +++ /dev/null @@ -1,40 +0,0 @@ -# Plugins Incríveis - -O Flight é incrivelmente extensível. Existem vários plugins que podem ser usados para adicionar funcionalidades à sua aplicação Flight. Alguns são oficialmente suportados pela Equipe do Flight e outros são bibliotecas micro/lite para ajudá-lo a começar. - -## Caching - -O armazenamento em cache é uma ótima maneira de acelerar a sua aplicação. Existem diversas bibliotecas de cache que podem ser usadas com o Flight. - -- [Wruczek/PHP-File-Cache](/awesome-plugins/php-file-cache) - Classe de armazenamento em arquivo PHP leve, simples e independente. - -## Debugging - -Depurar é crucial quando você está desenvolvendo no seu ambiente local. Existem alguns plugins que podem aprimorar a sua experiência de depuração. - -- [tracy/tracy](/awesome-plugins/tracy) - Este é um manipulador de erros completo que pode ser usado com o Flight. Possui várias painéis que podem ajudá-lo a depurar a sua aplicação. Também é muito fácil de estender e adicionar os seus próprios painéis. -- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado com o manipulador de erros [Tracy](/awesome-plugins/tracy), este plugin adiciona alguns painéis extras para ajudar na depuração especificamente em projetos do Flight. - -## Bancos de Dados - -Os bancos de dados são a base da maioria das aplicações. É assim que você armazena e recupera dados. Algumas bibliotecas de banco de dados são simplesmente wrappers para escrever consultas e outras são ORMs completos. - -- [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Wrapper PDO Oficial do Flight que faz parte do core. Este é um wrapper simples para ajudar a simplificar o processo de escrever consultas e executá-las. Não é um ORM. -- [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper Active Record oficial do Flight. Ótima pequena biblioteca para recuperar e armazenar dados facilmente no seu banco de dados. - -## Sessão - -As sessões não são realmente úteis para APIs, mas para desenvolver uma aplicação web, as sessões podem ser cruciais para manter o estado e as informações de login. - -- [Ghostff/Session](/awesome-plugins/session) - Gerenciador de Sessão PHP (não bloqueante, flash, segmento, criptografia de sessão). Usa o open_ssl do PHP para criptografar/criptografar opcionalmente os dados da sessão. - -## Templating - -A criação de modelos é essencial para qualquer aplicação web com uma interface de usuário. Existem várias engines de templates que podem ser usadas com o Flight. - -- [flightphp/core View](/learn#views) - Esta é uma engine de templates muito básica que faz parte do core. Não é recomendado para uso se você tiver mais do que algumas páginas no seu projeto. -- [latte/latte](/awesome-plugins/latte) - Latte é uma engine de templates completa que é muito fácil de usar e se aproxima mais de uma sintaxe PHP do que Twig ou Smarty. Também é muito fácil de estender e adicionar os seus próprios filtros e funções. - -## Contribuindo - -Tem um plugin que gostaria de compartilhar? Envie uma solicitação pull para adicioná-lo à lista! \ No newline at end of file diff --git a/content/v3/pt/awesome-plugins/pdo_wrapper.md b/content/v3/pt/awesome-plugins/pdo_wrapper.md deleted file mode 100644 index e69de29b..00000000 diff --git a/content/v3/pt/install.md b/content/v3/pt/install.md deleted file mode 100644 index 488d208f..00000000 --- a/content/v3/pt/install.md +++ /dev/null @@ -1,65 +0,0 @@ -# Instalação - -## Baixe os arquivos. - -Se estiver a usar [Composer](https://getcomposer.org), pode executar o seguinte comando: - -```bash -composer require flightphp/core -``` - -OU então pode [baixar os arquivos](https://github.com/flightphp/core/archive/master.zip) diretamente e extrair para o seu diretório web. - -## Configure o seu servidor web. - -### Apache -Para o Apache, edite o seu ficheiro `.htaccess` com o seguinte: - -```apacheconf -RewriteEngine On -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule ^(.*)$ index.php [QSA,L] -``` - -> **Nota**: Se necessitar de utilizar o Flight numa subpasta, adicione a linha -> `RewriteBase /subdir/` logo após `RewriteEngine On`. - -> **Nota**: Se quiser proteger todos os ficheiros do servidor, como um ficheiro de bd ou env. -> Coloque isto no seu ficheiro `.htaccess`: - -```apacheconf -RewriteEngine On -RewriteRule ^(.*)$ index.php -``` - -### Nginx - -Para o Nginx, adicione o seguinte à declaração do seu servidor: - -```nginx -server { - location / { - try_files $uri $uri/ /index.php; - } -} -``` - -## Crie o seu ficheiro `index.php`. - -```php -getTraceAsString(); -}); -``` - -Por padrão, os erros não são registrados no servidor web. Você pode habilitar isso -alterando a configuração: - -```php -Flight::set('flight.log_errors', true); -``` - -## Não Encontrado - -Quando um URL não pode ser encontrado, o Flight chama o método `notFound`. O comportamento -padrão é enviar uma resposta de `HTTP 404 Não Encontrado` com uma mensagem simples. - -Você pode substituir esse comportamento para suas próprias necessidades: - -```php -Flight::map('notFound', function () { - // Lidar com não encontrado -}); -``` \ No newline at end of file diff --git a/content/v3/pt/learn/frameworkinstance.md b/content/v3/pt/learn/frameworkinstance.md deleted file mode 100644 index f74209a3..00000000 --- a/content/v3/pt/learn/frameworkinstance.md +++ /dev/null @@ -1,17 +0,0 @@ -# Instância do Framework - -Em vez de executar o Flight como uma classe estática global, você pode executá-lo opcionalmente como uma instância de objeto. - -```php -require 'flight/autoload.php'; - -$app = Flight::app(); - -$app->route('/', function () { - echo 'olá mundo!'; -}); - -$app->start(); -``` - -Portanto, em vez de chamar o método estático, você chamaria o método de instância com o mesmo nome no objeto Engine. \ No newline at end of file diff --git a/content/v3/pt/learn/frameworkmethods.md b/content/v3/pt/learn/frameworkmethods.md deleted file mode 100644 index 6b5d0e28..00000000 --- a/content/v3/pt/learn/frameworkmethods.md +++ /dev/null @@ -1,44 +0,0 @@ -```pt -# Métodos do Framework - -Flight é projetado para ser fácil de usar e entender. O seguinte é o conjunto completo -de métodos para o framework. Consiste em métodos principais, que são métodos estáticos regulares, -e métodos extensíveis, que são métodos mapeados que podem ser filtrados -ou substituídos. - -## Métodos Principais - -```php -Flight::map(string $name, callable $callback, bool $pass_route = false) // Cria um método de framework personalizado. -Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // Registra uma classe a um método de framework. -Flight::before(string $name, callable $callback) // Adiciona um filtro antes de um método de framework. -Flight::after(string $name, callable $callback) // Adiciona um filtro após um método de framework. -Flight::path(string $path) // Adiciona um caminho para carregar classes automaticamente. -Flight::get(string $key) // Obtém uma variável. -Flight::set(string $key, mixed $value) // Define uma variável. -Flight::has(string $key) // Verifica se uma variável está definida. -Flight::clear(array|string $key = []) // Limpa uma variável. -Flight::init() // Inicializa o framework com suas configurações padrão. -Flight::app() // Obtém a instância do objeto de aplicativo -``` - -## Métodos Extensíveis - -```php -Flight::start() // Inicia o framework. -Flight::stop() // Para o framework e envia uma resposta. -Flight::halt(int $code = 200, string $message = '') // Para o framework com um código de status e mensagem opcionais. -Flight::route(string $pattern, callable $callback, bool $pass_route = false) // Mapeia um padrão de URL para um retorno de chamada. -Flight::group(string $pattern, callable $callback) // Cria agrupamento para urls, o padrão deve ser uma string. -Flight::redirect(string $url, int $code) // Redireciona para outra URL. -Flight::render(string $file, array $data, ?string $key = null) // Renderiza um arquivo de modelo. -Flight::error(Throwable $error) // Envia uma resposta HTTP 500. -Flight::notFound() // Envia uma resposta HTTP 404. -Flight::etag(string $id, string $type = 'string') // Realiza o cache do HTTP ETag. -Flight::lastModified(int $time) // Realiza o cache do HTTP de última modificação. -Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Envia uma resposta JSON. -Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Envia uma resposta JSONP. -``` - -Quaisquer métodos personalizados adicionados com `map` e `register` também podem ser filtrados. -``` \ No newline at end of file diff --git a/content/v3/pt/learn/httpcaching.md b/content/v3/pt/learn/httpcaching.md deleted file mode 100644 index 732a5b09..00000000 --- a/content/v3/pt/learn/httpcaching.md +++ /dev/null @@ -1,27 +0,0 @@ -# Caching HTTP - -Voo fornece suporte embutido para o caching de nível HTTP. Se a condição de caching for atendida, Voo retornará uma resposta `304 Not Modified` HTTP. Da próxima vez que o cliente solicitar o mesmo recurso, eles serão convidados a usar sua versão em cache localmente. - -## Última Modificação - -Você pode usar o método `lastModified` e passar um carimbo de data/hora UNIX para definir a data e hora em que a página foi modificada pela última vez. O cliente continuará a usar seu cache até que o valor da última modificação seja alterado. - -```php -Flight::route('/noticias', function () { - Flight::lastModified(1234567890); - echo 'Este conteúdo será armazenado em cache.'; -}); -``` - -## ETag - -O caching `ETag` é semelhante ao `Última Modificação`, exceto que você pode especificar qualquer ID que desejar para o recurso: - -```php -Flight::route('/noticias', function () { - Flight::etag('meu-id-único'); - echo 'Este conteúdo será armazenado em cache.'; -}); -``` - -Tenha em mente que chamar `lastModified` ou `etag` definirá e verificará o valor do cache. Se o valor do cache for o mesmo entre as solicitações, Voo enviará imediatamente uma resposta `HTTP 304` e interromperá o processamento. \ No newline at end of file diff --git a/content/v3/pt/learn/overriding.md b/content/v3/pt/learn/overriding.md deleted file mode 100644 index 5de84b0e..00000000 --- a/content/v3/pt/learn/overriding.md +++ /dev/null @@ -1,29 +0,0 @@ -# Substituição - -O Flight permite que você substitua sua funcionalidade padrão para atender às suas próprias necessidades, -sem ter que modificar nenhum código. - -Por exemplo, quando o Flight não consegue corresponder a uma URL a uma rota, ele invoca o método `notFound`, -que envia uma resposta genérica de `HTTP 404`. Você pode substituir esse comportamento -usando o método `map`: - -```php -Flight::map('notFound', function() { - // Exibir página 404 personalizada - include 'errors/404.html'; -}); -``` - -O Flight também permite que você substitua componentes principais do framework. -Por exemplo, você pode substituir a classe do Roteador padrão pela sua própria classe personalizada: - -```php -// Registre sua classe personalizada -Flight::register('router', MyRouter::class); - -// Quando o Flight carrega a instância do Roteador, ele carregará sua classe -$myrouter = Flight::router(); -``` - -Métodos do framework como `map` e `register`, no entanto, não podem ser substituídos. Você receberá -um erro se tentar fazê-lo. \ No newline at end of file diff --git a/content/v3/pt/learn/redirects.md b/content/v3/pt/learn/redirects.md deleted file mode 100644 index d0958ed7..00000000 --- a/content/v3/pt/learn/redirects.md +++ /dev/null @@ -1,15 +0,0 @@ -# Redirecionamentos - -Você pode redirecionar a solicitação atual usando o método `redirect` e passando -uma nova URL: - -```php -Flight::redirect('/novo/local'); -``` - -Por padrão, o Flight envia um código de status HTTP 303. Você pode opcionalmente definir um -código personalizado: - -```php -Flight::redirect('/novo/local', 401); -``` \ No newline at end of file diff --git a/content/v3/pt/learn/stopping.md b/content/v3/pt/learn/stopping.md deleted file mode 100644 index 10ba04ca..00000000 --- a/content/v3/pt/learn/stopping.md +++ /dev/null @@ -1,20 +0,0 @@ -# Parando - -Você pode parar o framework a qualquer momento chamando o método `halt`: - -```php -Flight::halt(); -``` - -Você também pode especificar um código de status `HTTP` opcional e uma mensagem: - -```php -Flight::halt(200, 'Volto em breve...'); -``` - -Chamar `halt` irá descartar qualquer conteúdo de resposta até esse ponto. Se você quiser parar -o framework e exibir a resposta atual, use o método `stop`: - -```php -Flight::stop(); -``` \ No newline at end of file diff --git a/content/v3/pt/learn/troubleshooting.md b/content/v3/pt/learn/troubleshooting.md deleted file mode 100644 index 475f3eb3..00000000 --- a/content/v3/pt/learn/troubleshooting.md +++ /dev/null @@ -1,74 +0,0 @@ -```pt -# Solução de problemas - -Esta página irá ajudá-lo a resolver problemas comuns que você pode encontrar ao usar o Flight. - -## Problemas Comuns - -### 404 Não Encontrado ou Comportamento de Rota Inesperado - -Se você estiver vendo um erro 404 Não Encontrado (mas jura pela sua vida que está realmente lá e não é um erro de digitação) isso poderia -realmente ser um problema com você retornando um valor no ponto final da sua rota em vez de apenas ecoá-lo. A razão para isso é intencional, -mas pode pegar alguns desenvolvedores de surpresa. - -```php - -Flight::route('/hello', function(){ - // Isso pode causar um erro 404 Não Encontrado - return 'Olá Mundo'; -}); - -// O que você provavelmente quer -Flight::route('/hello', function(){ - echo 'Olá Mundo'; -}); - -``` - -A razão para isso é por causa de um mecanismo especial incorporado no roteador que trata a saída de retorno como um sinal para "ir para a próxima rota". -Você pode ver o comportamento documentado na seção de [Roteamento](/learn/routing#passing). - -### Classe Não Encontrada (autoload não funcionando) - -Podem haver algumas razões para isso não estar funcionando. Abaixo estão alguns exemplos, mas certifique-se também de verificar a seção de [autoload](/learn/autoloading). - -#### Nome do Arquivo Incorreto -O mais comum é que o nome da classe não corresponda ao nome do arquivo. - -Se você tem uma classe chamada `MyClass`, então o arquivo deve ser chamado `MyClass.php`. Se você tem uma classe chamada `MyClass` e o arquivo é chamado `myclass.php` -então o autoload não será capaz de encontrá-lo. - -#### Namespace Incorreto -Se estiver usando namespaces, então o namespace deve corresponder à estrutura de diretórios. - -```php -// código - -// se o seu MyController estiver no diretório app/controllers e estiver em um namespace -// isso não funcionará -Flight::route('/hello', 'MyController->hello'); - -// você precisará escolher uma dessas opções -Flight::route('/hello', 'app\controllers\MyController->hello'); -// ou se você tiver um comando use no topo - -use app\controllers\MyController; - -Flight::route('/hello', [ MyController::class, 'hello' ]); -// também pode ser escrito -Flight::route('/hello', MyController::class.'->hello'); -// também... -Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); -``` - -#### `path()` não definido - -No aplicativo skeleton, isso é definido dentro do arquivo `config.php`, mas para que suas classes sejam encontradas, você precisa garantir que o método `path()` -esteja definido (provavelmente na raiz do seu diretório) antes de tentar usá-lo. - -```php - -// Adicione um caminho ao autoload -Flight::path(__DIR__.'/../'); - -``` \ No newline at end of file diff --git a/content/v3/pt/learn/variables.md b/content/v3/pt/learn/variables.md deleted file mode 100644 index cb3c6201..00000000 --- a/content/v3/pt/learn/variables.md +++ /dev/null @@ -1,35 +0,0 @@ -# Variáveis - -O Flight permite que você salve variáveis para que possam ser usadas em qualquer lugar de sua aplicação. - -```php -// Salve sua variável -Flight::set('id', 123); - -// Em outro lugar de sua aplicação -$id = Flight::get('id'); -``` - -Para verificar se uma variável foi definida, você pode fazer: - -```php -if (Flight::has('id')) { - // Faça algo -} -``` - -Você pode limpar uma variável fazendo: - -```php -// Limpa a variável id -Flight::clear('id'); - -// Limpa todas as variáveis -Flight::clear(); -``` - -O Flight também usa variáveis para fins de configuração. - -```php -Flight::set('flight.log_errors', true); -``` \ No newline at end of file diff --git a/content/v3/pt/learn/views.md b/content/v3/pt/learn/views.md deleted file mode 100644 index ce17834d..00000000 --- a/content/v3/pt/learn/views.md +++ /dev/null @@ -1,136 +0,0 @@ -## Vistas - -Flight fornece alguma funcionalidade básica de modelagem por padrão. Para exibir uma vista -chame o método `render` com o nome do arquivo de modelo e dados de modelo opcionais: - -```php -Flight::render('hello.php', ['name' => 'Bob']); -``` - -Os dados do modelo que você passa são automaticamente injetados no modelo e podem -ser referenciados como uma variável local. Os arquivos de modelo são simplesmente arquivos PHP. Se o -conteúdo do arquivo de modelo `hello.php` for: - -```php -Olá, ! -``` - -A saída seria: - -``` -Olá, Bob! -``` - -Você também pode definir manualmente variáveis de visualização usando o método set: - -```php -Flight::view()->set('name', 'Bob'); -``` - -A variável `name` agora está disponível em todas as suas visualizações. Então você pode simplesmente fazer: - -```php -Flight::render('hello'); -``` - -Observe que ao especificar o nome do modelo no método render, você pode -omitir a extensão `.php`. - -Por padrão, o Flight procurará um diretório `views` para arquivos de modelo. Você pode -definir um caminho alternativo para seus modelos configurando o seguinte: - -```php -Flight::set('flight.views.path', '/caminho/para/views'); -``` - -## Layouts - -É comum que sites tenham um único arquivo de modelo de layout com conteúdo alternante. Para renderizar conteúdo a ser usado em um layout, você pode passar um parâmetro opcional para o método `render`. - -```php -Flight::render('header', ['heading' => 'Olá'], 'headerContent'); -Flight::render('body', ['body' => 'Mundo'], 'bodyContent'); -``` - -Sua visualização então terá variáveis salvas chamadas `headerContent` e `bodyContent`. -Você pode então renderizar seu layout fazendo: - -```php -Flight::render('layout', ['title' => 'Página Inicial']); -``` - -Se os arquivos de modelo forem assim: - -`header.php`: - -```php -

-``` - -`body.php`: - -```php -
-``` - -`layout.php`: - -```php - - - <?= $title ?> - - - - - - -``` - -A saída seria: -```html - - - Página Inicial - - -

Olá

-
Mundo
- - -``` - -## Vistas Personalizadas - -O Flight permite que você substitua a engine de visualização padrão simplesmente registrando sua -própria classe de visualização. Veja como você usaria o [Smarty](http://www.smarty.net/) -template engine para suas visualizações: - -```php -// Carregar biblioteca do Smarty -require './Smarty/libs/Smarty.class.php'; - -// Registrar Smarty como a classe de visualização -// Também passar uma função de retorno de chamada para configurar o Smarty ao carregar -Flight::register('view', Smarty::class, [], function (Smarty $smarty) { - $smarty->setTemplateDir('./templates/'); - $smarty->setCompileDir('./templates_c/'); - $smarty->setConfigDir('./config/'); - $smarty->setCacheDir('./cache/'); -}); - -// Atribuir dados do modelo -Flight::view()->assign('name', 'Bob'); - -// Exibir o modelo -Flight::view()->display('hello.tpl'); -``` - -Para completude, você também deve substituir o método de renderização padrão do Flight: - -```php -Flight::map('render', function(string $template, array $data): void { - Flight::view()->assign($data); - Flight::view()->display($template); -}); -``` \ No newline at end of file diff --git a/content/v3/ru/awesome-plugins/index.md b/content/v3/ru/awesome-plugins/index.md deleted file mode 100644 index dbcb6952..00000000 --- a/content/v3/ru/awesome-plugins/index.md +++ /dev/null @@ -1,40 +0,0 @@ -# Удивительные плагины - -Flight невероятно расширяем. Есть ряд плагинов, которые можно использовать для добавления функциональности в ваше приложение Flight. Некоторые официально поддерживаются командой Flight, а другие являются микро/лайт библиотеками, чтобы помочь вам начать. - -## Кэширование - -Кэширование - отличный способ ускорить ваше приложение. Есть несколько библиотек кэширования, которые можно использовать с Flight. - -- [Wruczek/PHP-File-Cache](/awesome-plugins/php-file-cache) - Легкий, простой и автономный класс кэширования в файле PHP - -## Отладка - -Отладка критически важна при разработке в локальной среде. Есть несколько плагинов, которые могут улучшить ваш опыт отладки. - -- [tracy/tracy](/awesome-plugins/tracy) - Это полнофункциональный обработчик ошибок, который можно использовать с Flight. У него есть несколько панелей, которые могут помочь вам отлаживать ваше приложение. Также очень легко расширяем и добавляете собственные панели. -- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Используется с обработчиком ошибок [Tracy](/awesome-plugins/tracy), этот плагин добавляет несколько дополнительных панелей для улучшения отладки специально для проектов Flight. - -## Базы данных - -Базы данных являются основой для большинства приложений. Это то, как вы сохраняете и извлекаете данные. Некоторые библиотеки баз данных просто обертки для написания запросов, а некоторые - полноценные ORM. - -- [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Официальная обертка Flight PDO, которая является частью ядра. Это простая обертка, которая помогает упростить процесс написания и выполнения запросов. Это не ORM. -- [flightphp/active-record](/awesome-plugins/active-record) - Официальная библиотека Flight ActiveRecord ORM/Mapper. Отличная библиотека для легкого получения и хранения данных в вашей базе данных. - -## Сессии - -Сессии действительно не очень полезны для API, но для создания веб-приложения они могут быть критически важны для поддержания состояния и информации о входе. - -- [Ghostff/Session](/awesome-plugins/session) - Менеджер сессий PHP (неблокирующий, flash, сегмент, шифрование сессий). Использует PHP open_ssl для дополнительного шифрования/дешифрования данных сессии. - -## Шаблонизация - -Шаблонизация является основой любого веб-приложения с интерфейсом пользователя. Есть несколько шаблонизаторов, которые можно использовать с Flight. - -- [flightphp/core View](/learn#views) - Это очень простой шаблонизатор, который является частью ядра. Не рекомендуется использовать его, если у вас больше чем несколько страниц в вашем проекте. -- [latte/latte](/awesome-plugins/latte) - Latte - это полнофункциональный шаблонизатор, который очень легко использовать и ближе к синтаксису PHP, чем Twig или Smarty. Также очень легко расширяем и добавляете свои собственные фильтры и функции. - -## Вклад - -У вас есть плагин, который вы хотели бы поделиться? Отправьте запрос на добавление его в список! \ No newline at end of file diff --git a/content/v3/ru/awesome-plugins/pdo_wrapper.md b/content/v3/ru/awesome-plugins/pdo_wrapper.md deleted file mode 100644 index 57942707..00000000 --- a/content/v3/ru/awesome-plugins/pdo_wrapper.md +++ /dev/null @@ -1,122 +0,0 @@ -# PdoWrapper Класс помощника PDO - -Flight поставляется с классом помощника для PDO. Он позволяет легко выполнять запросы к базе данных -с использованием всех этих заморочек с подготовкой/выполнением/fetchAll(). Это значительно упрощает -ваш способ выполнения запросов к базе данных. Каждая строка результата возвращается как класс Flight Collection, -который позволяет вам получать доступ к данным с использованием синтаксиса массива или объекта. - -## Регистрация класса помощника PDO - -```php -// Регистрация класса помощника PDO -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 - ] -]); -``` - -## Применение -Этот объект расширяет PDO, поэтому все обычные методы PDO доступны. Для упрощения выполнения запросов к базе данных были добавлены следующие методы: - -### `runQuery(string $sql, array $params = []): PDOStatement` -Используйте это для INSERTS, UPDATES или если вы планируете использовать SELECT в цикле while - -```php -$db = Flight::db(); -$statement = $db->runQuery("SELECT * FROM table WHERE something = ?", [ $something ]); -while($row = $statement->fetch()) { - // ... -} - -// Или запись в базу данных -$db->runQuery("INSERT INTO table (name) VALUES (?)", [ $name ]); -$db->runQuery("UPDATE table SET name = ? WHERE id = ?", [ $name, $id ]); -``` - -### `fetchField(string $sql, array $params = []): mixed` -Извлекает первое поле из запроса - -```php -$db = Flight::db(); -$count = $db->fetchField("SELECT COUNT(*) FROM table WHERE something = ?", [ $something ]); -``` - -### `fetchRow(string $sql, array $params = []): array` -Извлекает одну строку из запроса - -```php -$db = Flight::db(); -$row = $db->fetchRow("SELECT id, name FROM table WHERE id = ?", [ $id ]); -echo $row['name']; -// или -echo $row->name; -``` - -### `fetchAll(string $sql, array $params = []): array` -Извлекает все строки из запроса - -```php -$db = Flight::db(); -$rows = $db->fetchAll("SELECT id, name FROM table WHERE something = ?", [ $something ]); -foreach($rows as $row) { - echo $row['name']; - // или - echo $row->name; -} -``` - -## Примечание к синтаксису `IN()` -Здесь также есть удобная оболочка для оператора `IN()`. Просто передайте один вопросительный знак в качестве заполнителя для `IN()`, а затем массив значений. Вот пример того, как это может выглядеть: - -```php -$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 ]); -``` - -## Полный пример - -```php -// Пример маршрута и как использовать эту оболочку -Flight::route('/users', function () { - // Получить всех пользователей - $users = Flight::db()->fetchAll('SELECT * FROM users'); - - // Отправить всех пользователей - $statement = Flight::db()->runQuery('SELECT * FROM users'); - while ($user = $statement->fetch()) { - echo $user['name']; - // или echo $user->name; - } - - // Получить одного пользователя - $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); - - // Получить одно значение - $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); - - // Особый синтаксис IN() для помощи (убедитесь, что IN написано заглавными буквами) - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); - // вы также можете сделать так - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [ '1,2,3,4,5']); - - // Вставить нового пользователя - Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']); - $insert_id = Flight::db()->lastInsertId(); - - // Обновить пользователя - Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]); - - // Удалить пользователя - Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]); - - // Получить количество затронутых строк - $statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']); - $affected_rows = $statement->rowCount(); - -}); -``` \ No newline at end of file diff --git a/content/v3/ru/install.md b/content/v3/ru/install.md deleted file mode 100644 index 88d43378..00000000 --- a/content/v3/ru/install.md +++ /dev/null @@ -1,67 +0,0 @@ -# Установка - -## Загрузите файлы. - -Если вы используете [Composer](https://getcomposer.org), вы можете запустить следующую -команду: - -```bash -composer require flightphp/core -``` - -ИЛИ вы можете [скачать файлы](https://github.com/flightphp/core/archive/master.zip) - напрямую и извлечь их в ваш веб-каталог. - -## Настройка вашего веб-сервера. - -### Apache -Для Apache отредактируйте ваш файл `.htaccess` следующим образом: - -```apacheconf -RewriteEngine On -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule ^(.*)$ index.php [QSA,L] -``` - -> **Примечание**: Если вам нужно использовать flight в подкаталоге, добавьте строку -> `RewriteBase /subdir/` сразу после `RewriteEngine On`. - -> **Примечание**: Если вы хотите защитить все файлы сервера, такие как файл db или env. -> Поместите это в свой файл `.htaccess`: - -```apacheconf -RewriteEngine On -RewriteRule ^(.*)$ index.php -``` - -### Nginx - -Для Nginx добавьте следующее в ваше объявление сервера: - -```nginx -server { - location / { - try_files $uri $uri/ /index.php; - } -} -``` - -## Создайте файл `index.php`. - -```php -getTraceAsString(); -}); -``` - -По умолчанию ошибки не записываются в журнал веб-сервера. Вы можете включить это, -изменив конфигурацию: - -```php -Flight::set('flight.log_errors', true); -``` - -## Не Найдено - -Когда URL не может быть найден, Flight вызывает метод `notFound`. Поведение по -умолчанию - отправить ответ `HTTP 404 Не Найдено` с простым сообщением. - -Вы можете переопределить это поведение для ваших собственных потребностей: - -```php -Flight::map('notFound', function () { - // Обработать не найдено -}); -``` \ No newline at end of file diff --git a/content/v3/ru/learn/frameworkinstance.md b/content/v3/ru/learn/frameworkinstance.md deleted file mode 100644 index ea6853ac..00000000 --- a/content/v3/ru/learn/frameworkinstance.md +++ /dev/null @@ -1,19 +0,0 @@ -# Экземпляр фреймворка - -Вместо того чтобы запускать Flight как глобальный статический класс, вы можете -опционально запустить его как экземпляр объекта. - -```php -require 'flight/autoload.php'; - -$app = Flight::app(); - -$app->route('/', function () { - echo 'hello world!'; -}); - -$app->start(); -``` - -Таким образом, вместо вызова статического метода, вы вызывали бы метод экземпляра -с тем же именем на объекте Engine. \ No newline at end of file diff --git a/content/v3/ru/learn/frameworkmethods.md b/content/v3/ru/learn/frameworkmethods.md deleted file mode 100644 index 017b377c..00000000 --- a/content/v3/ru/learn/frameworkmethods.md +++ /dev/null @@ -1,42 +0,0 @@ -## Методы фреймворка - -Flight разработан для удобства использования и понимания. Ниже приведен полный -набор методов для фреймворка. Он состоит из основных методов, которые являются -обычными статическими методами, и расширяемых методов, которые являются отображенными методами, -которые могут быть отфильтрованы или переопределены. - -## Основные Методы - -```php -Flight::map(строка $name, callable $callback, bool $pass_route = false) // Создает пользовательский метод фреймворка. -Flight::register(строка $name, строка $class, массив $params = [], ?callable $callback = null) // Регистрирует класс для метода фреймворка. -Flight::before(строка $name, callable $callback) // Добавляет фильтр перед методом фреймворка. -Flight::after(строка $name, callable $callback) // Добавляет фильтр после метода фреймворка. -Flight::path(строка $path) // Добавляет путь для автозагрузки классов. -Flight::get(строка $key) // Получает переменную. -Flight::set(строка $key, смешанный $value) // Устанавливает переменную. -Flight::has(строка $key) // Проверяет, установлена ли переменная. -Flight::clear(массив|строка $key = []) // Очищает переменную. -Flight::init() // Инициализирует фреймворк к его настройкам по умолчанию. -Flight::app() // Получает экземпляр объекта приложения. -``` - -## Расширяемые Методы - -```php -Flight::start() // Запускает фреймворк. -Flight::stop() // Останавливает фреймворк и отправляет ответ. -Flight::halt(int $code = 200, строка $message = '') // Останавливает фреймворк с необязательным кодом состояния и сообщением. -Flight::route(строка $pattern, callable $callback, bool $pass_route = false) // Сопоставляет шаблон URL с обратным вызовом. -Flight::group(строка $pattern, callable $callback) // Создает группировку для URL, шаблон должен быть строкой. -Flight::redirect(строка $url, int $code) // Перенаправляет на другой URL. -Flight::render(строка $file, массив $data, ?строка $key = null) // Рендерит файл шаблона. -Flight::error(Throwable $error) // Отправляет ответ HTTP 500. -Flight::notFound() // Отправляет ответ HTTP 404. -Flight::etag(строка $id, строка $type = 'string') // Выполняет кэширование HTTP ETag. -Flight::lastModified(int $time) // Выполняет кэширование HTTP Last-Modified. -Flight::json(смешанный $data, int $code = 200, bool $encode = true, строка $charset = 'utf8', int $option) // Отправляет ответ JSON. -Flight::jsonp(смешанный $data, строка $param = 'jsonp', int $code = 200, bool $encode = true, строка $charset = 'utf8', int $option) // Отправляет ответ JSONP. -``` - -Любые пользовательские методы, добавленные с помощью `map` и `register`, также могут быть отфильтрованы. \ No newline at end of file diff --git a/content/v3/ru/learn/httpcaching.md b/content/v3/ru/learn/httpcaching.md deleted file mode 100644 index 714f406b..00000000 --- a/content/v3/ru/learn/httpcaching.md +++ /dev/null @@ -1,35 +0,0 @@ -# Кэширование HTTP - -Flight обеспечивает встроенную поддержку кэширования на уровне HTTP. Если условие кэширования -выполнено, Flight вернет ответ HTTP `304 Not Modified`. В следующий раз -когда клиент запросит тот же ресурс, их попросят использовать локально -кэшированную версию. - -## Последнее изменение - -Вы можете использовать метод `lastModified` и передать временную метку UNIX для установки даты -и времени последнего изменения страницы. Клиент будет продолжать использовать свой кэш до тех пор, -пока значение последнего изменения не изменится. - -```php -Flight::route('/news', function () { - Flight::lastModified(1234567890); - echo 'Этот контент будет кэширован.'; -}); -``` - -## ETag - -Кэширование `ETag` аналогично `Last-Modified`, за исключением того, что вы можете указать любой идентификатор -для ресурса: - -```php -Flight::route('/news', function () { - Flight::etag('my-unique-id'); - echo 'Этот контент будет кэширован.'; -}); -``` - -Имейте в виду, что вызов методов `lastModified` или `etag` устанавливает и проверяет -значение кэша. Если значение кэша совпадает между запросами, Flight немедленно -отправит ответ `HTTP 304` и прекратит обработку. \ No newline at end of file diff --git a/content/v3/ru/learn/overriding.md b/content/v3/ru/learn/overriding.md deleted file mode 100644 index e2182220..00000000 --- a/content/v3/ru/learn/overriding.md +++ /dev/null @@ -1,29 +0,0 @@ -# Переопределение - -Flight позволяет вам переопределять его стандартную функциональность под свои собственные потребности, -не изменяя какой-либо код. - -Например, когда Flight не может сопоставить URL с маршрутом, он вызывает метод `notFound`, -который отправляет общий ответ `HTTP 404`. Вы можете переопределить это поведение -используя метод `map`: - -```php -Flight::map('notFound', function() { - // Показать пользовательскую страницу 404 - include 'errors/404.html'; -}); -``` - -Flight также позволяет заменять основные компоненты фреймворка. -Например, вы можете заменить стандартный класс Router на свой собственный класс: - -```php -// Зарегистрируйте свой собственный класс -Flight::register('router', MyRouter::class); - -// Когда Flight загружает экземпляр Router, он загрузит ваш класс -$myrouter = Flight::router(); -``` - -Однако методы фреймворка, такие как `map` и `register`, не могут быть переопределены. Если -вы попытаетесь это сделать, вы получите ошибку. \ No newline at end of file diff --git a/content/v3/ru/learn/redirects.md b/content/v3/ru/learn/redirects.md deleted file mode 100644 index 830d3c26..00000000 --- a/content/v3/ru/learn/redirects.md +++ /dev/null @@ -1,14 +0,0 @@ -# Редиректы - -Можно перенаправить текущий запрос, используя метод `redirect` и передав новый URL: - -```php -Flight::redirect('/новое/местоположение'); -``` - -По умолчанию Flight отправляет статусный код HTTP 303. Можно дополнительно установить -пользовательский код: - -```php -Flight::redirect('/новое/местоположение', 401); -``` \ No newline at end of file diff --git a/content/v3/ru/learn/stopping.md b/content/v3/ru/learn/stopping.md deleted file mode 100644 index 95672b36..00000000 --- a/content/v3/ru/learn/stopping.md +++ /dev/null @@ -1,20 +0,0 @@ -# Остановка - -Вы можете остановить фреймворк в любой момент, вызвав метод `halt`: - -```php -Flight::halt(); -``` - -Вы также можете указать необязательный `HTTP` код состояния и сообщение: - -```php -Flight::halt(200, 'Сейчас вернусь...'); -``` - -Вызов `halt` приведет к отмене любого содержимого ответа до этого момента. Если вы хотите остановить -фреймворк и вывести текущий ответ, используйте метод `stop`: - -```php -Flight::stop(); -``` \ No newline at end of file diff --git a/content/v3/ru/learn/troubleshooting.md b/content/v3/ru/learn/troubleshooting.md deleted file mode 100644 index 0bf30143..00000000 --- a/content/v3/ru/learn/troubleshooting.md +++ /dev/null @@ -1,70 +0,0 @@ -# Решение проблем - -Эта страница поможет вам устранить общие проблемы, с которыми вы можете столкнуться при использовании Flight. - -## Общие проблемы - -### 404 Страница не найдена или непредвиденное поведение маршрута - -Если вы видите ошибку 404 Страница не найдена (но вы клянетесь своей жизнью, что она действительно там и это не опечатка), на самом деле это может быть проблема с возвращением значения в конечной точке маршрута вместо простого его вывода. Причина этого намеренная, но некоторым разработчикам это может ускользнуть. - -```php - -Flight::route('/hello', function(){ - // Это может вызвать ошибку 404 Страница не найдена - return 'Hello World'; -}); - -// Что вам, вероятно, нужно -Flight::route('/hello', function(){ - echo 'Hello World'; -}); - -``` - -Причина заключается в том, что в маршрутизаторе встроен специальный механизм, который обрабатывает возвращаемый вывод как инструкцию "перейти к следующему маршруту". Вы можете ознакомиться с этим поведением в разделе [Маршрутизация](/learn/routing#passing). - -### Класс не найден (автозагрузка не работает) - -Могут быть несколько причин, почему это происходит. Ниже приведены некоторые примеры, но убедитесь также, что вы изучили раздел [автозагрузка](/learn/autoloading). - -#### Некорректное имя файла -Самая распространенная причина в том, что имя класса не совпадает с именем файла. - -Если у вас есть класс с именем `MyClass`, то файл должен иметь имя `MyClass.php`. Если у вас есть класс с именем `MyClass` и файл назван `myclass.php`, -то автозагрузчик не сможет его найти. - -#### Некорректное пространство имен -Если вы используете пространства имен, то пространство имен должно соответствовать структуре каталогов. - -```php -// код - -// если ваш MyController находится в каталоге app/controllers и у него есть пространство имен -// это не сработает. -Flight::route('/hello', 'MyController->hello'); - -// вам нужно выбрать один из этих вариантов -Flight::route('/hello', 'app\controllers\MyController->hello'); -// или если у вас есть оператор use вверху - -use app\controllers\MyController; - -Flight::route('/hello', [ MyController::class, 'hello' ]); -// также можно написать -Flight::route('/hello', MyController::class.'->hello'); -// или так... -Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); -``` - -#### `path()` не определен - -В контрольном приложении это определяется внутри файла `config.php`, но для того чтобы ваши классы были найдены, убедитесь, что метод `path()` -определен (вероятно, к корневому каталогу вашего каталога) прежде чем пытаться его использовать. - -```php - -// Добавьте путь к автозагрузчику -Flight::path(__DIR__.'/../'); - -``` \ No newline at end of file diff --git a/content/v3/ru/learn/variables.md b/content/v3/ru/learn/variables.md deleted file mode 100644 index 806c8712..00000000 --- a/content/v3/ru/learn/variables.md +++ /dev/null @@ -1,35 +0,0 @@ -# Переменные - -Flight позволяет вам сохранять переменные, чтобы они могли быть использованы в любом месте вашего приложения. - -```php -// Сохраняет вашу переменную -Flight::set('id', 123); - -// В другом месте вашего приложения -$id = Flight::get('id'); -``` - -Для проверки установленной переменной вы можете сделать следующее: - -```php -if (Flight::has('id')) { - // Сделать что-то -} -``` - -Вы можете очистить переменную, выполнив: - -```php -// Очищает переменную id -Flight::clear('id'); - -// Очищает все переменные -Flight::clear(); -``` - -Flight также использует переменные для целей конфигурации. - -```php -Flight::set('flight.log_errors', true); -``` \ No newline at end of file diff --git a/content/v3/ru/learn/views.md b/content/v3/ru/learn/views.md deleted file mode 100644 index d10d583e..00000000 --- a/content/v3/ru/learn/views.md +++ /dev/null @@ -1,139 +0,0 @@ -# Виды - -Flight по умолчанию предоставляет некоторые базовые функции шаблонизации. Чтобы отобразить вид -шаблона, вызовите метод `render` с именем файла шаблона и необязательными -данными шаблона: - -```php -Flight::render('hello.php', ['name' => 'Bob']); -``` - -Данные шаблона, которые вы передаете, автоматически встраиваются в шаблон и могут -быть обращены как локальная переменная. Файлы шаблонов - это просто файлы PHP. Если -содержимое файла шаблона `hello.php` выглядит так: - -```php -Привет, ! -``` - -То вывод будет: - -``` -Привет, Bob! -``` - -Вы также можете вручную устанавливать переменные представления с помощью метода set: - -```php -Flight::view()->set('name', 'Bob'); -``` - -Переменная `name` теперь доступна во всех ваших представлениях. Поэтому вы просто можете сделать: - -```php -Flight::render('hello'); -``` - -Обратите внимание, что при указании имени шаблона в методе render вы можете -пропустить расширение `.php`. - -По умолчанию Flight будет искать каталог `views` для файлов шаблонов. Вы можете -задать альтернативный путь для ваших шаблонов, установив следующую конфигурацию: - -```php -Flight::set('flight.views.path', '/путь/к/views'); -``` - -## Макеты - -Часто веб-сайты имеют один файл шаблона макета с переменным -содержимым. Чтобы отобразить содержимое для использования в макете, вы можете передать -необязательный параметр в метод `render`. - -```php -Flight::render('header', ['heading' => 'Привет'], 'headerContent'); -Flight::render('body', ['body' => 'Мир'], 'bodyContent'); -``` - -Ваше представление затем будет иметь сохраненные переменные с именами `headerContent` и `bodyContent`. -Затем вы можете отобразить ваш макет так: - -```php -Flight::render('layout', ['title' => 'Домашняя страница']); -``` - -Если файлы шаблонов выглядят так: - -`header.php`: - -```php -

-``` - -`body.php`: - -```php -
-``` - -`layout.php`: - -```php - - - <?= $title ?> - - - - - - -``` - -Вывод будет: -```html - - - Домашняя страница - - -

Привет

-
Мир
- - -``` - -## Пользовательские представления - -Flight позволяет заменить стандартный движок представлений просто зарегистрировав свой -собственный класс представлений. Вот как вы можете использовать [Smarty](http://www.smarty.net/) -шаблонный движок для ваших представлений: - -```php -// Загрузка библиотеки Smarty -require './Smarty/libs/Smarty.class.php'; - -// Регистрация Smarty как класса представления -// Также передайте функцию обратного вызова для настройки Smarty при загрузке -Flight::register('view', Smarty::class, [], function (Smarty $smarty) { - $smarty->setTemplateDir('./templates/'); - $smarty->setCompileDir('./templates_c/'); - $smarty->setConfigDir('./config/'); - $smarty->setCacheDir('./cache/'); -}); - -// Назначение данных шаблона -Flight::view()->assign('name', 'Bob'); - -// Отображение шаблона -Flight::view()->display('hello.tpl'); -``` - -Для полноты вы также должны переопределить стандартный метод render Flight: - -```php -Flight::map('render', function(string $template, array $data): void { - Flight::view()->assign($data); - Flight::view()->display($template); -}); -``` \ No newline at end of file diff --git a/content/v3/uk/awesome-plugins/pdo_wrapper.md b/content/v3/uk/awesome-plugins/pdo_wrapper.md deleted file mode 100644 index ccbe5fb6..00000000 --- a/content/v3/uk/awesome-plugins/pdo_wrapper.md +++ /dev/null @@ -1,122 +0,0 @@ -# PdoWrapper PDO Helper Class - -Flight постачається з допоміжним класом для PDO. Це дозволяє вам легко запитувати вашу базу даних -з усією підготовкою/виконанням/fetchAll() заморочкою. Це значно спрощує, як ви можете -запитувати вашу базу даних. Кожен рядок результату повертається як клас Colletion Flight, який -дозволяє вам отримувати доступ до ваших даних через синтаксис масиву або синтаксис об'єкта. - -## Реєстрація класу допомоги PDO - -```php -// Зареєструйте клас допомоги PDO -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 - ] -]); -``` - -## Використання -Цей об'єкт розширює PDO, тому всі звичайні методи PDO доступні. Наступні методи додані, щоб спростити запити до бази даних: - -### `runQuery(string $sql, array $params = []): PDOStatement` -Використовуйте це для ВСТАВКИ, ОНОВЛЕННЯ або якщо ви плануєте використовувати SELECT в циклі while - -```php -$db = Flight::db(); -$statement = $db->runQuery("SELECT * FROM table WHERE something = ?", [ $something ]); -while($row = $statement->fetch()) { - // ... -} - -// Або запис до бази даних -$db->runQuery("INSERT INTO table (name) VALUES (?)", [ $name ]); -$db->runQuery("UPDATE table SET name = ? WHERE id = ?", [ $name, $id ]); -``` - -### `fetchField(string $sql, array $params = []): mixed` -Отримує перше поле з запиту - -```php -$db = Flight::db(); -$count = $db->fetchField("SELECT COUNT(*) FROM table WHERE something = ?", [ $something ]); -``` - -### `fetchRow(string $sql, array $params = []): array` -Отримує один рядок з запиту - -```php -$db = Flight::db(); -$row = $db->fetchRow("SELECT id, name FROM table WHERE id = ?", [ $id ]); -echo $row['name']; -// або -echo $row->name; -``` - -### `fetchAll(string $sql, array $params = []): array` -Отримує всі рядки з запиту - -```php -$db = Flight::db(); -$rows = $db->fetchAll("SELECT id, name FROM table WHERE something = ?", [ $something ]); -foreach($rows as $row) { - echo $row['name']; - // або - echo $row->name; -} -``` - -## Примітка зі синтаксисом `IN()` -Це також має корисну обгортку для операторів `IN()`. Ви можете просто передати один знак питання як заповнювач для `IN()` а потім масив значень. Ось приклад того, як це може виглядати: - -```php -$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 ]); -``` - -## Повний приклад - -```php -// Приклад маршруту і як ви б використовували цю обгортку -Flight::route('/users', function () { - // Отримати всіх користувачів - $users = Flight::db()->fetchAll('SELECT * FROM users'); - - // Потік всіх користувачів - $statement = Flight::db()->runQuery('SELECT * FROM users'); - while ($user = $statement->fetch()) { - echo $user['name']; - // або echo $user->name; - } - - // Отримати одного користувача - $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); - - // Отримати одне значення - $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); - - // Спеціальний синтаксис IN() для допомоги (обов'язково, щоб IN було великими літерами) - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); - // ви також можете зробити так - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [ '1,2,3,4,5']); - - // Вставити нового користувача - Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']); - $insert_id = Flight::db()->lastInsertId(); - - // Оновити користувача - Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]); - - // Видалити користувача - Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]); - - // Отримати кількість змінених рядків - $statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']); - $affected_rows = $statement->rowCount(); - -}); -``` \ No newline at end of file diff --git a/content/v3/uk/learn.md b/content/v3/uk/learn.md deleted file mode 100644 index d8c5990f..00000000 --- a/content/v3/uk/learn.md +++ /dev/null @@ -1,90 +0,0 @@ -# Дізнайтеся про Flight - -Flight є швидким, простим, розширюваним фреймворком для PHP. Він досить гнучкий і може використовуватися для створення будь-якого виду веб-застосунків. -Він створений з урахуванням простоти і написаний так, що легко зрозуміти і використовувати. - -## 🚀 AI & Developer Experience з Flight - -Flight не тільки швидкий і простий — він також розроблений для того, щоб допомогти вам кодувати розумніше і робити більше, особливо з допомогою сучасних інструментів AI. Незалежно від того, чи використовуєте ви AI-підтримку для кодування, автоматизуєте повторювані завдання, або просто хочете підвищити продуктивність, низький слід Flight і проста структура роблять його приємним для використання разом з останніми робочими процесами devex і AI. - -- **AI-Enhanced Coding:** Flight добре працює з AI-асистентами для кодування, дозволяючи вам створювати каркас, рефакторити і будувати функції швидше, ніж будь-коли. -- **Faster Prototyping:** Швидко запускайте нові ідеї і ітеруйте з допомогою інструментів AI — Flight не буде вам заважати. -- **Integrate AI APIs:** Якщо ви хочете підключитися до послуг AI або додати розумні функції, Flight робить це легко, але вам не потрібно бути експертом AI, щоб скористатися. - -Цікаво, як розпочати? [Дослідіть наш посібник AI & DevEx](/learn/ai) для порад, інструментів і реальних прикладів щодо роботи швидше і розумніше з Flight! - -## Важливі концепції фреймворку - -##### [Чому фреймворк?](/learn/why-frameworks) - -Ось коротка стаття про те, чому ви повинні використовувати фреймворк. Це гарна ідея зрозуміти переваги використання фреймворку, перш ніж почати використовувати його. - -Крім того, відмінний навчальний посібник був створений [@lubiana](https://git.php.fail/lubiana). Хоча він не йде в глибокі деталі про Flight specifically, -цей посібник допоможе вам зрозуміти деякі основні концепції навколо фреймворку і чому вони корисні. -Ви можете знайти навчальний посібник [тут](https://git.php.fail/lubiana/no-framework-tutorial/src/branch/master/README.md). - -##### [Flight у порівнянні з іншими фреймворками](/learn/flight-vs-another-framework) -Якщо ви мігруєте з іншого фреймворку, такого як Laravel, Slim, Fat-Free або Symfony до Flight, ця сторінка допоможе вам зрозуміти відмінності між ними. - -## Основні теми - -##### [AI & Developer Experience](/learn/ai) -Дізнайтеся, як Flight працює з інструментами AI та сучасними робочими процесами розробників, щоб допомогти вам кодувати швидше і розумніше. - -##### [Автозавантаження](/learn/autoloading) - -Дізнайтеся, як автозавантажувати ваші власні класи у вашому застосунку. - -##### [Маршрутизація](/learn/routing) - -Дізнайтеся, як керувати маршрутами для вашого веб-застосунку. Це також включає групування маршрутів, параметри маршрутів і middleware. - -##### [Middleware](/learn/middleware) - -Дізнайтеся, як використовувати middleware для фільтрації запитів і відповідей у вашому застосунку. - -##### [Запити](/learn/requests) - -Дізнайтеся, як обробляти запити і відповіді у вашому застосунку. - -##### [Відповіді](/learn/responses) - -Дізнайтеся, як надсилати відповіді вашим користувачам. - -##### [Події](/learn/events) - -Дізнайтеся, як використовувати систему подій для додавання власних подій до вашого застосунку. - -##### [HTML-шаблони](/learn/templates) - -Дізнайтеся, як використовувати вбудований рушій перегляду для рендерингу ваших HTML-шаблонів. - -##### [Безпека](/learn/security) - -Дізнайтеся, як захистити ваш застосунок від загроз безпеки. - -##### [Конфігурація](/learn/configuration) - -Дізнайтеся, як налаштувати фреймворк для вашого застосунку. - -##### [Розширення Flight](/learn/extending) - -Дізнайтеся, як розширити фреймворк, додаючи власні методи і класи. - -##### [Події та фільтрування](/learn/filtering) - -Дізнайтеся, як використовувати систему подій для додавання хуків до ваших методів і внутрішніх методів фреймворку. - -##### [Контейнер залежностей](/learn/dependency-injection-container) - -Дізнайтеся, як використовувати контейнери залежностей (DIC) для управління залежностями вашого застосунку. - -##### [API фреймворку](/learn/api) - -Дізнайтеся про основні методи фреймворку. - -##### [Міграція до v3](/learn/migrating-to-v3) -Зворотна сумісність в основному збереглася, але є деякі зміни, про які ви повинні знати при міграції з v2 до v3. - -##### [Усунення проблем](/learn/troubleshooting) -Є деякі поширені проблеми, з якими ви можете зіткнутися при використанні Flight. Ця сторінка допоможе вам усунути ці проблеми. \ No newline at end of file diff --git a/content/v3/uk/learn/api.md b/content/v3/uk/learn/api.md deleted file mode 100644 index 22842109..00000000 --- a/content/v3/uk/learn/api.md +++ /dev/null @@ -1,55 +0,0 @@ -# Методи API фреймворку - -Flight розроблений для того, щоб бути простим у використанні та розумінні. Нижче наведено повний набір методів для фреймворку. Він складається з основних методів, які є регулярними статичними методами, а також розширювальних методів, які є відображеними методами, що можуть бути відфільтровані або перевизначені. - -## Основні методи - -Ці методи є основними для фреймворку і не можуть бути перевизначені. - -```php -Flight::map(string $name, callable $callback, bool $pass_route = false) // Створює кастомний метод фреймворку. -Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // Реєструє клас для методу фреймворку. -Flight::unregister(string $name) // Скасовує реєстрацію класу для методу фреймворку. -Flight::before(string $name, callable $callback) // Додає фільтр перед методом фреймворку. -Flight::after(string $name, callable $callback) // Додає фільтр після методу фреймворку. -Flight::path(string $path) // Додає шлях для автоматичного завантаження класів. -Flight::get(string $key) // Отримує змінну, встановлену Flight::set(). -Flight::set(string $key, mixed $value) // Встановлює змінну в рамках движка Flight. -Flight::has(string $key) // Перевіряє, чи встановлено змінну. -Flight::clear(array|string $key = []) // Очищає змінну. -Flight::init() // Ініціалізує фреймворк з його стандартними налаштуваннями. -Flight::app() // Отримує екземпляр об'єкта програми. -Flight::request() // Отримує екземпляр об'єкта запиту. -Flight::response() // Отримує екземпляр об'єкта відповіді. -Flight::router() // Отримує екземпляр об'єкта маршрутизатора. -Flight::view() // Отримує екземпляр об'єкта перегляду. -``` - -## Розширювальні методи - -```php -Flight::start() // Запускає фреймворк. -Flight::stop() // Зупиняє фреймворк і відправляє відповідь. -Flight::halt(int $code = 200, string $message = '') // Зупиняє фреймворк з необов'язковим кодом статусу та повідомленням. -Flight::route(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Відображає шаблон URL на колбек. -Flight::post(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Відображає шаблон URL запиту POST на колбек. -Flight::put(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Відображає шаблон URL запиту PUT на колбек. -Flight::patch(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Відображає шаблон URL запиту PATCH на колбек. -Flight::delete(string $pattern, callable $callback, bool $pass_route = false, string $alias = '') // Відображає шаблон URL запиту DELETE на колбек. -Flight::group(string $pattern, callable $callback) // Створює групування для URL, шаблон має бути рядком. -Flight::getUrl(string $name, array $params = []) // Генерує URL на основі псевдоніму маршруту. -Flight::redirect(string $url, int $code) // Перенаправляє на інший URL. -Flight::download(string $filePath) // Завантажує файл. -Flight::render(string $file, array $data, ?string $key = null) // Відображає шаблонний файл. -Flight::error(Throwable $error) // Відправляє відповідь HTTP 500. -Flight::notFound() // Відправляє відповідь HTTP 404. -Flight::etag(string $id, string $type = 'string') // Виконує ETag HTTP кешування. -Flight::lastModified(int $time) // Виконує кешування HTTP останнього модифікованого. -Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Відправляє відповідь JSON. -Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Відправляє відповідь JSONP. -Flight::jsonHalt(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // Відправляє відповідь JSON і зупиняє фреймворк. -Flight::onEvent(string $event, callable $callback) // Реєструє слухача подій. -Flight::triggerEvent(string $event, ...$args) // Запускає подію. -``` - -Будь-які кастомні методи, додані за допомогою `map` та `register`, також можуть бути відфільтровані. Для прикладів того, як відобразити ці методи, дивіться посібник [Розширення Flight](/learn/extending). \ No newline at end of file diff --git a/content/v3/uk/learn/troubleshooting.md b/content/v3/uk/learn/troubleshooting.md deleted file mode 100644 index da6cf47c..00000000 --- a/content/v3/uk/learn/troubleshooting.md +++ /dev/null @@ -1,72 +0,0 @@ -# Виправлення несправностей - -Ця сторінка допоможе вам вирішити поширені проблеми, з якими ви можете зіткнутися при використанні Flight. - -## Поширені проблеми - -### 404 Не знайдено або несподівана поведінка маршруту - -Якщо ви бачите помилку 404 Не знайдено (але клянетесь, що це дійсно там і це не помилка), це може бути проблемою -з тим, що ви повертаєте значення у вашому маршруті замість того, щоб просто виводити його. Причина цього є навмисною, але може підкочуватися до деяких розробників. - -```php - -Flight::route('/hello', function(){ - // Це може викликати помилку 404 Не знайдено - return 'Hello World'; -}); - -// Що ви, напевно, хочете -Flight::route('/hello', function(){ - echo 'Hello World'; -}); - -``` - -Причина цього полягає в особливому механізмі, вбудованому в маршрутизатор, який обробляє повернення виводу як одиночний для "перейти до наступного маршруту". -Ви можете ознайомитися з поведінкою, задокументованою в розділі [Маршрутизація](/learn/routing#passing). - -### Клас не знайдено (автозавантаження не працює) - -Можливо, є кілька причин, чому це не відбувається. Нижче наведено кілька прикладів, але переконайтеся, що ви також переглянули розділ [автозавантаження](/learn/autoloading). - -#### Неправильне ім'я файлу -Найпоширенішою є те, що ім'я класу не відповідає імені файлу. - -Якщо у вас є клас під назвою `MyClass`, то файл повинен називатися `MyClass.php`. Якщо у вас є клас під назвою `MyClass`, а файл називається `myclass.php`, -тоді автозавантажувач не зможе його знайти. - -#### Неправильний простір імен -Якщо ви використовуєте простори імен, то простір імен має відповідати структурі каталогу. - -```php -// код - -// якщо ваш MyController знаходиться в каталозі app/controllers і має простір імен -// це не спрацює. -Flight::route('/hello', 'MyController->hello'); - -// вам потрібно вибрати один з цих варіантів -Flight::route('/hello', 'app\controllers\MyController->hello'); -// або якщо у вас є оператор use на початку - -use app\controllers\MyController; - -Flight::route('/hello', [ MyController::class, 'hello' ]); -// також можна записати -Flight::route('/hello', MyController::class.'->hello'); -// також... -Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); -``` - -#### `path()` не визначено - -У скелетній програмі це визначено в файлі `config.php`, але для того, щоб ваші класи були знайдені, вам потрібно переконатися, що метод `path()` -визначено (ймовірно, до кореня вашого каталогу) перед тим, як ви спробуєте його використовувати. - -```php - -// Додайте шлях до автозавантажувача -Flight::path(__DIR__.'/../'); - -``` \ No newline at end of file diff --git a/content/v3/zh/awesome-plugins/index.md b/content/v3/zh/awesome-plugins/index.md deleted file mode 100644 index 9b218a5f..00000000 --- a/content/v3/zh/awesome-plugins/index.md +++ /dev/null @@ -1,40 +0,0 @@ -# 令人惊叹的插件 - -Flight非常可扩展。有许多插件可以用于向您的Flight应用程序添加功能。其中一些得到了Flight团队的官方支持,而其他一些是微型/轻量级库,可帮助您入门。 - -## 缓存 - -缓存是加速应用程序的绝佳方法。有许多缓存库可与Flight一起使用。 - -- [Wruczek/PHP-File-Cache](/awesome-plugins/php-file-cache) - 轻巧、简单且独立的PHP文件缓存类 - -## 调试 - -在本地环境中进行开发时,调试至关重要。有一些插件可以提升您的调试体验。 - -- [tracy/tracy](/awesome-plugins/tracy) - 这是一个功能齐全的错误处理程序,可以与Flight一起使用。它具有多个面板,可以帮助您调试应用程序。扩展和添加自定义面板也非常简单。 -- [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - 与[Tracy](/awesome-plugins/tracy)错误处理程序一起使用,此插件添加了一些额外的面板,专门用于Flight项目的调试。 - -## 数据库 - -数据库是大多数应用程序的核心。这是您存储和检索数据的方式。有些数据库库只是用来编写查询的包装器,而有些是完整的ORM。 - -- [flightphp/core PdoWrapper](/awesome-plugins/pdo-wrapper) - Flight官方PDO包装器,是核心的一部分。这是一个简单的包装器,帮助简化编写查询和执行查询的过程。它不是ORM。 -- [flightphp/active-record](/awesome-plugins/active-record) - Flight官方ActiveRecord ORM/Mapper。非常适合轻松检索和存储数据库中的数据的小型库。 - -## 会话 - -对于API来说,会话实际上并不那么有用,但对于构建Web应用程序来说,会话可以对保持状态和登录信息至关重要。 - -- [Ghostff/Session](/awesome-plugins/session) - PHP会话管理器(非阻塞,闪存,分段,会话加密)。使用PHP open_ssl进行可选的会话数据加密/解密。 - -## 模板 - -模板是任何具有UI的Web应用程序的核心。有许多模板引擎可与Flight一起使用。 - -- [flightphp/core View](/learn#views) - 这是Flight核心的一个非常基本的模板引擎。如果项目中有多个页面,则不建议使用它。 -- [latte/latte](/awesome-plugins/latte) - Latte是一个功能齐全的模板引擎,非常易于使用,更接近于PHP语法而不是Twig或Smarty。扩展和添加自定义过滤器和功能也非常简单。 - -## 贡献 - -有插件想要分享吗?提交拉取请求将其添加到列表中! \ No newline at end of file diff --git a/content/v3/zh/awesome-plugins/pdo_wrapper.md b/content/v3/zh/awesome-plugins/pdo_wrapper.md deleted file mode 100644 index 83deab1c..00000000 --- a/content/v3/zh/awesome-plugins/pdo_wrapper.md +++ /dev/null @@ -1,119 +0,0 @@ -# PdoWrapper PDO 辅助类 - -Flight 自带一个用于 PDO 的辅助类。它允许您轻松地查询您的数据库,使用所有准备/执行/获取所有结果的功能。它极大简化了您查询数据库的方式。每一行结果都作为 Flight 集合类返回,允许您通过数组语法或对象语法访问您的数据。 - -## 注册 PDO 辅助类 - -```php -// 注册 PDO 辅助类 -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 - ] -]); -``` - -## 用法 -此对象扩展了 PDO,因此所有正常的 PDO 方法都可用。以下方法已添加以使查询数据库更容易: - -### `runQuery(string $sql, array $params = []): PDOStatement` -用于INSERTS、UPDATES,或者如果您打算在 while 循环中使用 SELECT - -```php -$db = Flight::db(); -$statement = $db->runQuery("SELECT * FROM table WHERE something = ?", [ $something ]); -while($row = $statement->fetch()) { - // ... -} - -// 或写入数据库 -$db->runQuery("INSERT INTO table (name) VALUES (?)", [ $name ]); -$db->runQuery("UPDATE table SET name = ? WHERE id = ?", [ $name, $id ]); -``` - -### `fetchField(string $sql, array $params = []): mixed` -从查询中获取第一个字段 - -```php -$db = Flight::db(); -$count = $db->fetchField("SELECT COUNT(*) FROM table WHERE something = ?", [ $something ]); -``` - -### `fetchRow(string $sql, array $params = []): array` -从查询中获取一行 - -```php -$db = Flight::db(); -$row = $db->fetchRow("SELECT id, name FROM table WHERE id = ?", [ $id ]); -echo $row['name']; -// 或 -echo $row->name; -``` - -### `fetchAll(string $sql, array $params = []): array` -从查询中获取所有行 - -```php -$db = Flight::db(); -$rows = $db->fetchAll("SELECT id, name FROM table WHERE something = ?", [ $something ]); -foreach($rows as $row) { - echo $row['name']; - // 或 - echo $row->name; -} -``` - -## 注意 `IN()` 语法 -这还有一个有用的 `IN()` 语句包装器。您可以简单地传递一个问号作为 `IN()` 的占位符,然后是一个值数组。以下是这种用法的示例: - -```php -$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 ]); -``` - -## 完整示例 - -```php -// 示例路由及如何使用该包装器 -Flight::route('/users', function () { - // 获取所有用户 - $users = Flight::db()->fetchAll('SELECT * FROM users'); - - // 流式传输所有用户 - $statement = Flight::db()->runQuery('SELECT * FROM users'); - while ($user = $statement->fetch()) { - echo $user['name']; - // or echo $user->name; - } - - // 获取单个用户 - $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); - - // 获取单个值 - $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); - - // 特殊 IN() 语法以帮助你(确保 IN 大写) - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); - // 您也可以这样做 - $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [ '1,2,3,4,5']); - - // 插入新用户 - Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']); - $insert_id = Flight::db()->lastInsertId(); - - // 更新用户 - Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]); - - // 删除用户 - Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]); - - // 获取受影响行数 - $statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']); - $affected_rows = $statement->rowCount(); - -}); -``` \ No newline at end of file diff --git a/content/v3/zh/install.md b/content/v3/zh/install.md deleted file mode 100644 index 31a126e0..00000000 --- a/content/v3/zh/install.md +++ /dev/null @@ -1,65 +0,0 @@ -# 安装 - -## 下载文件 - -如果您正在使用[Composer](https://getcomposer.org),可以运行以下命令: - -```bash -composer require flightphp/core -``` - -或者您可以直接[下载文件](https://github.com/flightphp/core/archive/master.zip) 并将其提取到您的 web 目录中。 - -## 配置您的 Web 服务器 - -### Apache - -对于 Apache,请编辑您的 `.htaccess` 文件如下: - -```apacheconf -RewriteEngine On -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule ^(.*)$ index.php [QSA,L] -``` - -> **注意**: 如果您需要在子目录中使用 Flight,请在 `RewriteEngine On` 之后添加 `RewriteBase /subdir/`。 - -> **注意**: 如果您希望保护所有服务器文件,例如 db 或 env 文件, -> 请将以下内容放入您的 `.htaccess` 文件中: - -```apacheconf -RewriteEngine On -RewriteRule ^(.*)$ index.php -``` - -### Nginx - -对于 Nginx,请将以下内容添加到您的服务器声明中: - -```nginx -server { - location / { - try_files $uri $uri/ /index.php; - } -} -``` - -## 创建您的 `index.php` 文件 - -```php -getTraceAsString(); -}); -``` - -默认情况下,错误不会记录到 web 服务器。您可以通过更改配置来启用此功能: - -```php -Flight::set('flight.log_errors', true); -``` - -## 未找到 - -当 URL 找不到时,Flight 调用`notFound`方法。默认行为是发送一个`HTTP 404 未找到`响应,带有一个简单消息。 - -您可以根据自己的需求覆盖此行为: - -```php -Flight::map('notFound', function () { - // 处理未找到 -}); -``` \ No newline at end of file diff --git a/content/v3/zh/learn/frameworkinstance.md b/content/v3/zh/learn/frameworkinstance.md deleted file mode 100644 index a57cce22..00000000 --- a/content/v3/zh/learn/frameworkinstance.md +++ /dev/null @@ -1,17 +0,0 @@ -# 框架实例 - -# 将 Flight 作为全局静态类运行,您可以选择将其作为对象实例运行。 - -```php -require 'flight/autoload.php'; - -$app = Flight::app(); - -$app->route('/', function () { - echo 'hello world!'; -}); - -$app->start(); -``` - -# 因此,您可以通过引擎对象上具有相同名称的实例方法来调用实例方法,而不是调用静态方法。 \ No newline at end of file diff --git a/content/v3/zh/learn/frameworkmethods.md b/content/v3/zh/learn/frameworkmethods.md deleted file mode 100644 index 248022fe..00000000 --- a/content/v3/zh/learn/frameworkmethods.md +++ /dev/null @@ -1,42 +0,0 @@ -```zh -# 框架方法 - -Flight 旨在易于使用和理解。以下是框架的完整方法集。 -它包括核心方法,这些是常规静态方法,以及可被筛选或覆盖的可扩展方法,这些是映射方法。 - -## 核心方法 - -```php -Flight::map(string $name, callable $callback, bool $pass_route = false) // 创建自定义框架方法。 -Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // 将类注册到框架方法。 -Flight::before(string $name, callable $callback) // 在调用框架方法前添加筛选器。 -Flight::after(string $name, callable $callback) // 在调用框架方法后添加筛选器。 -Flight::path(string $path) // 添加自动加载类的路径。 -Flight::get(string $key) // 获取变量。 -Flight::set(string $key, mixed $value) // 设置变量。 -Flight::has(string $key) // 检查变量是否设置。 -Flight::clear(array|string $key = []) // 清除变量。 -Flight::init() // 将框架初始化为默认设置。 -Flight::app() // 获取应用程序对象实例 -``` - -## 可扩展方法 - -```php -Flight::start() // 启动框架。 -Flight::stop() // 停止框架并发送响应。 -Flight::halt(int $code = 200, string $message = '') // 停止框架,可选择性地附带状态代码和消息。 -Flight::route(string $pattern, callable $callback, bool $pass_route = false) // 将 URL 模式映射到回调。 -Flight::group(string $pattern, callable $callback) // 为 URL 创建分组,模式必须为字符串。 -Flight::redirect(string $url, int $code) // 重定向到另一个 URL。 -Flight::render(string $file, array $data, ?string $key = null) // 渲染模板文件。 -Flight::error(Throwable $error) // 发送 HTTP 500 响应。 -Flight::notFound() // 发送 HTTP 404 响应。 -Flight::etag(string $id, string $type = 'string') // 执行 ETag HTTP 缓存。 -Flight::lastModified(int $time) // 执行上次修改的 HTTP 缓存。 -Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // 发送 JSON 响应。 -Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // 发送 JSONP 响应。 -``` - -`map` 和 `register` 添加的任何自定义方法也可进行筛选。 -``` \ No newline at end of file diff --git a/content/v3/zh/learn/httpcaching.md b/content/v3/zh/learn/httpcaching.md deleted file mode 100644 index b64388bf..00000000 --- a/content/v3/zh/learn/httpcaching.md +++ /dev/null @@ -1,27 +0,0 @@ -# HTTP 缓存 - -Flight 提供了内置支持,用于 HTTP 级别的缓存。如果满足缓存条件,Flight 将返回一个 HTTP `304 Not Modified` 响应。下一次客户端请求相同资源时,它们将被提示使用本地缓存版本。 - -## 上次修改时间 - -您可以使用 `lastModified` 方法并传入一个 UNIX 时间戳来设置页面上次修改的日期和时间。客户端将继续使用它们的缓存,直到上次修改的值被更改。 - -```php -Flight::route('/news', function () { - Flight::lastModified(1234567890); - echo '此内容将被缓存。'; -}); -``` - -## ETag - -`ETag` 缓存类似于 `Last-Modified`,不同之处在于您可以为资源指定任何想要的 id: - -```php -Flight::route('/news', function () { - Flight::etag('my-unique-id'); - echo '此内容将被缓存。'; -}); -``` - -请记住,调用 `lastModified` 或 `etag` 都将设置并检查缓存值。如果在请求之间的缓存值相同,则 Flight 将立即发送一个 `HTTP 304` 响应并停止处理。 \ No newline at end of file diff --git a/content/v3/zh/learn/overriding.md b/content/v3/zh/learn/overriding.md deleted file mode 100644 index 704f9ca1..00000000 --- a/content/v3/zh/learn/overriding.md +++ /dev/null @@ -1,24 +0,0 @@ -# 覆盖 - -Flight 允许您覆盖其默认功能以满足您自己的需求,而无需修改任何代码。 - -例如,当 Flight 无法将 URL 与路由匹配时,它会调用 `notFound` 方法,该方法发送一个通用的 `HTTP 404` 响应。您可以使用 `map` 方法覆盖此行为: - -```php -Flight::map('notFound', function() { - // 显示自定义 404 页面 - include 'errors/404.html'; -}); -``` - -Flight 还允许您替换框架的核心组件。例如,您可以使用自定义类替换默认的 Router 类: - -```php -// 注册您的自定义类 -Flight::register('router', MyRouter::class); - -// 当 Flight 加载 Router 实例时,它将加载您的类 -$myrouter = Flight::router(); -``` - -但是,像 `map` 和 `register` 这样的框架方法不能被覆盖。如果您尝试这样做,将会收到错误提示。 \ No newline at end of file diff --git a/content/v3/zh/learn/redirects.md b/content/v3/zh/learn/redirects.md deleted file mode 100644 index a1864d20..00000000 --- a/content/v3/zh/learn/redirects.md +++ /dev/null @@ -1,13 +0,0 @@ -# 重定向 - -您可以使用`redirect`方法并传入新的URL来重定向当前请求: - -```php -Flight::redirect('/new/location'); -``` - -默认情况下,Flight发送HTTP 303状态码。您还可以选择设置自定义代码: - -```php -Flight::redirect('/new/location', 401); -``` \ No newline at end of file diff --git a/content/v3/zh/learn/stopping.md b/content/v3/zh/learn/stopping.md deleted file mode 100644 index 19240bce..00000000 --- a/content/v3/zh/learn/stopping.md +++ /dev/null @@ -1,19 +0,0 @@ -# 停止 - -您可以通过调用 `halt` 方法在任何时候停止框架: - -```php -Flight::halt(); -``` - -您还可以指定一个可选的 `HTTP` 状态码和消息: - -```php -Flight::halt(200, '马上回来...'); -``` - -调用 `halt` 将丢弃直到该点的任何响应内容。如果您想要停止框架并输出当前响应,请使用 `stop` 方法: - -```php -Flight::stop(); -``` \ No newline at end of file diff --git a/content/v3/zh/learn/troubleshooting.md b/content/v3/zh/learn/troubleshooting.md deleted file mode 100644 index 7ce6758c..00000000 --- a/content/v3/zh/learn/troubleshooting.md +++ /dev/null @@ -1,68 +0,0 @@ -# 故障排除 - -这个页面将帮助您解决在使用Flight时可能遇到的常见问题。 - -## 常见问题 - -### 404未找到或意外路由行为 - -如果您看到404未找到错误(但您发誓它确实存在,而且没有拼写错误),实际上可能是因为您在路由终点返回一个值而不是仅仅输出它。这样做的原因是故意的,但可能会让一些开发人员感到意外。 - -```php - -Flight::route('/hello', function(){ - // 这可能导致404未找到错误 - return 'Hello World'; -}); - -// 您可能想要的是 -Flight::route('/hello', function(){ - echo 'Hello World'; -}); - -``` - -造成这种情况的原因是路由器中内置的特殊机制,它将返回输出视为“继续下一个路由”。您可以在[路由](/learn/routing#passing)部分中查看这种行为的文档。 - -### 类未找到(自动加载不起作用) - -可能有几个原因导致这种情况发生。以下是一些示例,但请确保您还查看了[自动加载](/learn/autoloading)部分。 - -#### 文件名不正确 -最常见的情况是类名与文件名不匹配。 - -如果您有一个名为 `MyClass` 的类,那么文件应该命名为 `MyClass.php`。如果您有一个名为 `MyClass` 的类,而文件命名为 `myclass.php`,那么自动加载程序将找不到它。 - -#### 命名空间不正确 -如果您正在使用命名空间,那么命名空间应该与目录结构匹配。 - -```php -// 代码 - -// 如果您的MyController位于app/controllers目录中并且具有命名空间 -// 这样将无法工作。 -Flight::route('/hello', 'MyController->hello'); - -// 您需要选择以下其中一种选项 -Flight::route('/hello', 'app\controllers\MyController->hello'); -// 或者如果您在顶部有一个use语句 - -use app\controllers\MyController; - -Flight::route('/hello', [ MyController::class, 'hello' ]); -// 也可以写成 -Flight::route('/hello', MyController::class.'->hello'); -// 还有... -Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); -``` - -#### `path()` 未定义 - -在骨架应用程序中,这在 `config.php` 文件中定义,但为了使您的类能够被找到,您需要确保在尝试使用它之前定义了 `path()` 方法(可能是指向您的目录根)。 - -```php - -// 向自动加载器添加路径 -Flight::path(__DIR__.'/../'); - -``` \ No newline at end of file diff --git a/content/v3/zh/learn/variables.md b/content/v3/zh/learn/variables.md deleted file mode 100644 index 079fa564..00000000 --- a/content/v3/zh/learn/variables.md +++ /dev/null @@ -1,34 +0,0 @@ -# 变量 - -Flight允许您保存变量,以便它们可以在应用程序的任何地方使用。 - -```php -// 保存变量 -Flight::set('id', 123); - -// 在应用程序的其他地方 -$id = Flight::get('id'); -``` -要查看变量是否已设置,可以执行以下操作: - -```php -if (Flight::has('id')) { - // 做些什么 -} -``` - -您可以通过以下方式清除变量: - -```php -// 清除id变量 -Flight::clear('id'); - -// 清除所有变量 -Flight::clear(); -``` - -Flight还使用变量进行配置目的。 - -```php -Flight::set('flight.log_errors', true); -``` \ No newline at end of file diff --git a/content/v3/zh/learn/views.md b/content/v3/zh/learn/views.md deleted file mode 100644 index e2805fec..00000000 --- a/content/v3/zh/learn/views.md +++ /dev/null @@ -1,128 +0,0 @@ -# 视图 - -Flight默认提供一些基本的模板功能。要显示视图模板,请调用`render`方法并提供模板文件名称以及可选的模板数据: - -```php -Flight::render('hello.php', ['name' => 'Bob']); -``` - -您传递的模板数据将自动注入到模板中,并且可以像本地变量一样引用。模板文件只是简单的PHP文件。如果`hello.php`模板文件的内容是: - -```php -Hello, ! -``` - -输出将是: - -``` -Hello, Bob! -``` - -您还可以通过使用`set`方法手动设置视图变量: - -```php -Flight::view()->set('name', 'Bob'); -``` - -现在名为`name`的变量可以在所有视图中使用。因此,您只需简单地执行: - -```php -Flight::render('hello'); -``` - -请注意,在`render`方法中指定模板名称时,可以省略`.php`扩展名。 - -默认情况下,Flight将在`views`目录中查找模板文件。您可以通过设置以下配置来为您的模板设置替代路径: - -```php -Flight::set('flight.views.path', '/path/to/views'); -``` - -## 布局 - -网站通常具有一个带有可互换内容的单个布局模板文件。要呈现要在布局中使用的内容,您可以向`render`方法传递一个可选参数。 - -```php -Flight::render('header', ['heading' => 'Hello'], 'headerContent'); -Flight::render('body', ['body' => 'World'], 'bodyContent'); -``` - -然后,您的视图将保存名为`headerContent`和`bodyContent`的变量。然后,您可以通过执行以下操作来呈现您的布局: - -```php -Flight::render('layout', ['title' => 'Home Page']); -``` - -如果模板文件如下所示: - -`header.php`: - -```php -

-``` - -`body.php`: - -```php -
-``` - -`layout.php`: - -```php - - - <?= $title ?> - - - - - - -``` - -输出将是: -```html - - - Home Page - - -

Hello

-
World
- - -``` - -## 自定义视图 - -Flight允许您通过注册自己的视图类简单地更换默认视图引擎。以下是如何为视图使用[Smarty](http://www.smarty.net/)模板引擎的示例: - -```php -// 加载Smarty库 -require './Smarty/libs/Smarty.class.php'; - -// 将Smarty注册为视图类 -// 还要传递回调函数以在加载时配置Smarty -Flight::register('view', Smarty::class, [], function (Smarty $smarty) { - $smarty->setTemplateDir('./templates/'); - $smarty->setCompileDir('./templates_c/'); - $smarty->setConfigDir('./config/'); - $smarty->setCacheDir('./cache/'); -}); - -// 设置模板数据 -Flight::view()->assign('name', 'Bob'); - -// 显示模板 -Flight::view()->display('hello.tpl'); -``` - -为了完整起见,您还应该覆盖Flight的默认`render`方法: - -```php -Flight::map('render', function(string $template, array $data): void { - Flight::view()->assign($data); - Flight::view()->display($template); -}); -``` \ No newline at end of file diff --git a/translate_content.php b/translate_content.php index ab18353c..245d8339 100644 --- a/translate_content.php +++ b/translate_content.php @@ -127,3 +127,45 @@ echo " Updated: " . $translatedFilePath . PHP_EOL; } } + +// --- Begin: Remove orphaned translated files --- + +// Build a set of all relative file paths in /en/ +$enFiles = []; +foreach ($files as $file) { + // Get path relative to /content/v3/en/ + $enFiles[] = ltrim(str_replace(realpath(__DIR__ . '/content/v3/en/'), '', realpath($file)), '/\\'); +} + +// For each language, scan its directory and remove files not present in $enFiles +foreach ($languages as $languageAbbreviation) { + $langDir = __DIR__ . "/content/v3/{$languageAbbreviation}/"; + if (!is_dir($langDir)) continue; + + // Recursive iterator to find all .md files + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($langDir, RecursiveDirectoryIterator::SKIP_DOTS) + ); + + foreach ($iterator as $translatedFile) { + if ($translatedFile->getExtension() !== 'md') continue; + + // Get path relative to /content/v3/{lang}/ + $relativePath = ltrim(str_replace(realpath($langDir), '', $translatedFile->getRealPath()), '/\\'); + + // If this file doesn't exist in /en/, delete it + if (!in_array($relativePath, $enFiles)) { + echo "Deleting orphaned file: {$translatedFile->getRealPath()}" . PHP_EOL; + unlink($translatedFile->getRealPath()); + + // Remove empty directories up the tree + $dir = dirname($translatedFile->getRealPath()); + while ($dir !== $langDir && is_dir($dir) && count(glob("$dir/*")) === 0) { + rmdir($dir); + $dir = dirname($dir); + } + } + } +} + +// --- End: Remove orphaned translated files --- From a1520aa05fe7353131d5f9bdc124c0055d4f7611 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Tue, 30 Sep 2025 18:42:07 +0100 Subject: [PATCH 02/36] Fix a couple little hiccups --- app/middleware/HeaderSecurityMiddleware.php | 2 +- app/utils/Text.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/middleware/HeaderSecurityMiddleware.php b/app/middleware/HeaderSecurityMiddleware.php index 9730d1ce..3a3dcb42 100644 --- a/app/middleware/HeaderSecurityMiddleware.php +++ b/app/middleware/HeaderSecurityMiddleware.php @@ -18,7 +18,7 @@ public function before() { } Flight::response()->header('X-Frame-Options', 'SAMEORIGIN'); - Flight::response()->header("Content-Security-Policy", "default-src 'self'; script-src 'self' https://api.github.com https://cdn.jsdelivr.net https://buttons.github.io https://unpkg.com https://opengraph.b-cdn.net https://www.googletagmanager.com 'nonce-" . $nonce . "'; font-src 'self' https://fonts.gstatic.com https://fonts.googleapis.com https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.jsdelivr.net https://unpkg.com https://cdnjs.cloudflare.com; img-src 'self' https://dcbadge.limes.pink https://img.shields.io https://cdn.jsdelivr.net data: https://api.github.com https://raw.githubusercontent.com; connect-src 'self' https://api.github.com; frame-src https://www.youtube.com"); + Flight::response()->header("Content-Security-Policy", "default-src 'self'; script-src 'self' https://api.github.com https://cdn.jsdelivr.net https://buttons.github.io https://unpkg.com https://opengraph.b-cdn.net https://www.googletagmanager.com 'nonce-" . $nonce . "'; font-src 'self' https://fonts.gstatic.com https://fonts.googleapis.com https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.jsdelivr.net https://unpkg.com https://cdnjs.cloudflare.com; img-src 'self' https://dcbadge.limes.pink https://img.shields.io https://cdn.jsdelivr.net data: https://api.github.com https://raw.githubusercontent.com; connect-src 'self' https://api.github.com https://cdn.jsdelivr.net; frame-src https://www.youtube.com"); Flight::response()->header('X-XSS-Protection', '1; mode=block'); Flight::response()->header('X-Content-Type-Options', 'nosniff'); Flight::response()->header('Referrer-Policy', 'no-referrer-when-downgrade'); diff --git a/app/utils/Text.php b/app/utils/Text.php index 8edce162..74e663c2 100644 --- a/app/utils/Text.php +++ b/app/utils/Text.php @@ -54,7 +54,7 @@ public static function generateAndConvertHeaderListFromHtml(string $markdown_htm } $title = strip_tags($matches[3]); $rawTitle = $matches[3]; - $slugged_title = Text::slugify($title); + $slugged_title = 'heading-' . Text::slugify($title); $id_attr = 'id="' . $slugged_title . '"'; $permalink = ' '; From 1eea96b84542bcc8ae8a97753d93cf3ba877a7c4 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Tue, 30 Sep 2025 18:44:38 +0100 Subject: [PATCH 03/36] fixed numbered slugs --- app/utils/Text.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/utils/Text.php b/app/utils/Text.php index 74e663c2..b4b41691 100644 --- a/app/utils/Text.php +++ b/app/utils/Text.php @@ -54,7 +54,11 @@ public static function generateAndConvertHeaderListFromHtml(string $markdown_htm } $title = strip_tags($matches[3]); $rawTitle = $matches[3]; - $slugged_title = 'heading-' . Text::slugify($title); + $slugged_title = Text::slugify($title); + // if $slugged_title starts with a number, prepend it with 'section-' + if (preg_match('/^\d/', $slugged_title)) { + $slugged_title = 'section-' . $slugged_title; + } $id_attr = 'id="' . $slugged_title . '"'; $permalink = ' '; From a26c63af16a656f93bf163a4f161c33299b6420e Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Tue, 30 Sep 2025 18:47:53 +0100 Subject: [PATCH 04/36] fixed AI numbered instructions --- content/v3/en/learn/ai.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/v3/en/learn/ai.md b/content/v3/en/learn/ai.md index 31d4742b..70357a54 100644 --- a/content/v3/en/learn/ai.md +++ b/content/v3/en/learn/ai.md @@ -15,7 +15,7 @@ These features are built into the Flight core CLI and the official [flightphp/sk ## Basic Usage -### 1. Setting Up LLM Credentials +### Setting Up LLM Credentials The `ai:init` command walks you through connecting your project to an LLM provider. @@ -40,7 +40,7 @@ Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: Credentials saved to .runway-creds.json ``` -### 2. Generating Project-Specific AI Instructions +### Generating Project-Specific AI Instructions The `ai:generate-instructions` command helps you create or update instructions for AI coding assistants, tailored to your project. From cb9e64c0e33d981c8ce511a2459557f080a80816 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Tue, 30 Sep 2025 22:55:54 +0100 Subject: [PATCH 05/36] Changed accept logic to only serve markdown for LLMs --- app/utils/DocsLogic.php | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/app/utils/DocsLogic.php b/app/utils/DocsLogic.php index 271e2aef..af3a4f43 100644 --- a/app/utils/DocsLogic.php +++ b/app/utils/DocsLogic.php @@ -91,14 +91,20 @@ public function renderPage(string $latte_file, array $params = []) { $uri = substr($uri, 0, strpos($uri, '?')); } - - // Here we can set variables that will be available on any page - $params['url'] = $request->getScheme() . '://' . $request->getHeader('Host') . $uri; - $params['nonce'] = HeaderSecurityMiddleware::$nonce; - $params['q'] = $request->query['q'] ?? ''; - $startTime = microtime(true); - $this->app->latte()->render($latte_file, $params); + if(!empty($params['raw_markdown']) && (str_contains($request->header('Accept'), 'text/plain') || str_contains($request->header('Accept'), 'text/markdown'))) { + $this->app->response()->header('Content-Type', 'text/markdown; charset=utf-8'); + $this->app->response()->write($params['raw_markdown']); + } else { + + // Here we can set variables that will be available on any page + $params['url'] = $request->getScheme() . '://' . $request->getHeader('Host') . $uri; + $params['nonce'] = HeaderSecurityMiddleware::$nonce; + $params['q'] = $request->query['q'] ?? ''; + + $this->app->latte()->render($latte_file, $params); + } + $executionTime = microtime(true) - $startTime; $this->app->eventDispatcher()->trigger('flight.view.rendered', $latte_file.':'.$uri, $executionTime); } @@ -145,9 +151,10 @@ public function compileSinglePage(string $language, string $version, string $sec $cacheHit = true; $cacheKey = $section . '_html_' . $language . '_' . $version; $markdown_html = $app->cache()->retrieve($cacheKey); + $rawMarkdown = $Translator->getMarkdownLanguageFile($section . '.md'); if ($markdown_html === null) { $cacheHit = false; - $markdown_html = $app->parsedown()->text($Translator->getMarkdownLanguageFile($section . '.md')); + $markdown_html = $app->parsedown()->text($rawMarkdown); $markdown_html = Text::addClassesToElements($markdown_html); $app->cache()->store($cacheKey, $markdown_html, 86400); // 1 day } @@ -161,6 +168,7 @@ public function compileSinglePage(string $language, string $version, string $sec 'markdown' => $markdown_html, 'version' => $version, 'language' => $language, + 'raw_markdown' => $rawMarkdown, ]); } @@ -195,9 +203,10 @@ public function compileScrollspyPage(string $language, string $version, string $ $cacheHit = true; $cacheKey = $sub_section_underscored . '_html_' . $language . '_' . $version; $markdown_html = $app->cache()->retrieve($cacheKey); + $rawMarkdown = $Translator->getMarkdownLanguageFile('/' . $section_file_path . '/' . $sub_section_underscored . '.md'); if ($markdown_html === null) { $cacheHit = false; - $markdown_html = $app->parsedown()->text($Translator->getMarkdownLanguageFile('/' . $section_file_path . '/' . $sub_section_underscored . '.md')); + $markdown_html = $app->parsedown()->text($rawMarkdown); $heading_data = []; $markdown_html = Text::generateAndConvertHeaderListFromHtml($markdown_html, $heading_data, $section_file_path.'/'.$sub_section); @@ -223,6 +232,7 @@ public function compileScrollspyPage(string $language, string $version, string $ $params = [ 'custom_page_title' => ($page_title ? $page_title . ' - ' : '') . $Translator->translate($section), + 'raw_markdown' => $rawMarkdown, 'markdown' => $markdown_html, 'heading_data' => $heading_data, 'relative_uri' => '/'.$section_file_path, From 864c00104a6fcce66b0a53cf840f65ff65db0e4f Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Tue, 30 Sep 2025 23:00:59 +0100 Subject: [PATCH 06/36] added demo for flight docs --- content/v3/en/awesome-plugins/apm.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content/v3/en/awesome-plugins/apm.md b/content/v3/en/awesome-plugins/apm.md index fcb7efb0..9d81fa4a 100644 --- a/content/v3/en/awesome-plugins/apm.md +++ b/content/v3/en/awesome-plugins/apm.md @@ -2,6 +2,8 @@ Welcome to FlightPHP APM—your app’s personal performance coach! This guide is your roadmap to setting up, using, and mastering Application Performance Monitoring (APM) with FlightPHP. Whether you’re hunting down slow requests or just want to geek out over latency charts, we’ve got you covered. Let’s make your app faster, your users happier, and your debugging sessions a breeze! +View a [demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) of the dashboard for the Flight Docs site. + ![FlightPHP APM](/images/apm.png) ## Why APM Matters From 870832adc4b910dd587da8878360946d97c3b319 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Sat, 4 Oct 2025 12:43:18 +0100 Subject: [PATCH 07/36] added documentation for options/head and negotiateContentType --- composer.lock | 61 +- content/v3/de/awesome-plugins/apm.md | 234 +- content/v3/de/learn/ai.md | 34 +- content/v3/de/learn/requests.md | 153 +- content/v3/de/learn/responses.md | 117 +- content/v3/de/learn/routing.md | 185 +- content/v3/en/learn/requests.md | 28 +- content/v3/en/learn/responses.md | 3 + content/v3/en/learn/routing.md | 64 +- content/v3/es/awesome-plugins/apm.md | 232 +- content/v3/es/learn/ai.md | 16 +- content/v3/es/learn/requests.md | 70 +- content/v3/es/learn/responses.md | 131 +- content/v3/es/learn/routing.md | 126 +- content/v3/fr/awesome-plugins/apm.md | 184 +- content/v3/fr/learn/ai.md | 10 +- content/v3/fr/learn/requests.md | 69 +- content/v3/fr/learn/responses.md | 99 +- content/v3/fr/learn/routing.md | 178 +- content/v3/id/awesome-plugins/apm.md | 6732 +------------------------- content/v3/id/learn/ai.md | 8 +- content/v3/id/learn/requests.md | 104 +- content/v3/id/learn/responses.md | 101 +- content/v3/id/learn/routing.md | 374 +- content/v3/ja/awesome-plugins/apm.md | 282 +- content/v3/ja/learn/ai.md | 58 +- content/v3/ja/learn/requests.md | 93 +- content/v3/ja/learn/responses.md | 144 +- content/v3/ja/learn/routing.md | 211 +- content/v3/ko/awesome-plugins/apm.md | 234 +- content/v3/ko/learn/ai.md | 52 +- content/v3/ko/learn/requests.md | 126 +- content/v3/ko/learn/responses.md | 91 +- content/v3/ko/learn/routing.md | 239 +- content/v3/lv/awesome-plugins/apm.md | 246 +- content/v3/lv/learn/ai.md | 38 +- content/v3/lv/learn/requests.md | 95 +- content/v3/lv/learn/responses.md | 113 +- content/v3/lv/learn/routing.md | 207 +- content/v3/pt/awesome-plugins/apm.md | 188 +- content/v3/pt/learn/ai.md | 24 +- content/v3/pt/learn/requests.md | 68 +- content/v3/pt/learn/responses.md | 62 +- content/v3/pt/learn/routing.md | 288 +- content/v3/ru/awesome-plugins/apm.md | 218 +- content/v3/ru/learn/ai.md | 12 +- content/v3/ru/learn/requests.md | 57 +- content/v3/ru/learn/responses.md | 109 +- content/v3/ru/learn/routing.md | 195 +- content/v3/uk/awesome-plugins/apm.md | 216 +- content/v3/uk/learn/ai.md | 44 +- content/v3/uk/learn/requests.md | 56 +- content/v3/uk/learn/responses.md | 69 +- content/v3/uk/learn/routing.md | 170 +- content/v3/zh/awesome-plugins/apm.md | 188 +- content/v3/zh/learn/ai.md | 24 +- content/v3/zh/learn/requests.md | 50 +- content/v3/zh/learn/responses.md | 66 +- content/v3/zh/learn/routing.md | 166 +- 59 files changed, 4164 insertions(+), 9648 deletions(-) diff --git a/composer.lock b/composer.lock index 651c3fed..1fe8908f 100644 --- a/composer.lock +++ b/composer.lock @@ -247,16 +247,16 @@ }, { "name": "flightphp/cache", - "version": "1.0.0", + "version": "v1.1.0", "source": { "type": "git", "url": "https://github.com/flightphp/cache.git", - "reference": "75fe4fc60186e2663f8371095b0977c319939902" + "reference": "0e28ca9eac632a539afaf94e91d27453182977cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/flightphp/cache/zipball/75fe4fc60186e2663f8371095b0977c319939902", - "reference": "75fe4fc60186e2663f8371095b0977c319939902", + "url": "https://api.github.com/repos/flightphp/cache/zipball/0e28ca9eac632a539afaf94e91d27453182977cd", + "reference": "0e28ca9eac632a539afaf94e91d27453182977cd", "shasum": "" }, "require": { @@ -295,22 +295,22 @@ "description": "Light, simple and standalone PHP in-file caching class", "support": { "issues": "https://github.com/flightphp/cache/issues", - "source": "https://github.com/flightphp/cache/tree/1.0.0" + "source": "https://github.com/flightphp/cache/tree/v1.1.0" }, - "time": "2025-02-21T14:03:10+00:00" + "time": "2025-09-29T03:38:37+00:00" }, { "name": "flightphp/core", - "version": "v3.17.0", + "version": "v3.17.2", "source": { "type": "git", "url": "https://github.com/flightphp/core.git", - "reference": "b331797ae3bb2f721e55c5f4d56c56614504b7c1" + "reference": "095a46663f7090c549f5c3459f0dada893b3b5d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/flightphp/core/zipball/b331797ae3bb2f721e55c5f4d56c56614504b7c1", - "reference": "b331797ae3bb2f721e55c5f4d56c56614504b7c1", + "url": "https://api.github.com/repos/flightphp/core/zipball/095a46663f7090c549f5c3459f0dada893b3b5d9", + "reference": "095a46663f7090c549f5c3459f0dada893b3b5d9", "shasum": "" }, "require": { @@ -371,9 +371,9 @@ "homepage": "http://flightphp.com", "support": { "issues": "https://github.com/flightphp/core/issues", - "source": "https://github.com/flightphp/core/tree/v3.17.0" + "source": "https://github.com/flightphp/core/tree/v3.17.2" }, - "time": "2025-07-20T15:54:04+00:00" + "time": "2025-10-03T21:05:48+00:00" }, { "name": "flightphp/runway", @@ -756,16 +756,16 @@ "packages-dev": [ { "name": "flightphp/tracy-extensions", - "version": "v0.2.6", + "version": "v0.2.7", "source": { "type": "git", "url": "https://github.com/flightphp/tracy-extensions.git", - "reference": "0488323812c8a11a57c1f60fd9416ec2a46d3cb6" + "reference": "4150ea7dc9bbb56fa089e7a4662f68011a771256" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/flightphp/tracy-extensions/zipball/0488323812c8a11a57c1f60fd9416ec2a46d3cb6", - "reference": "0488323812c8a11a57c1f60fd9416ec2a46d3cb6", + "url": "https://api.github.com/repos/flightphp/tracy-extensions/zipball/4150ea7dc9bbb56fa089e7a4662f68011a771256", + "reference": "4150ea7dc9bbb56fa089e7a4662f68011a771256", "shasum": "" }, "require": { @@ -795,9 +795,9 @@ "description": "A few Flight specific extensions for Tracy Debugger to help debug your code quickly.", "support": { "issues": "https://github.com/flightphp/tracy-extensions/issues", - "source": "https://github.com/flightphp/tracy-extensions/tree/v0.2.6" + "source": "https://github.com/flightphp/tracy-extensions/tree/v0.2.7" }, - "time": "2025-05-26T16:33:00+00:00" + "time": "2025-09-03T13:47:57+00:00" }, { "name": "phpstan/extension-installer", @@ -849,16 +849,11 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.22", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "41600c8379eb5aee63e9413fe9e97273e25d57e4" - }, + "version": "2.1.30", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/41600c8379eb5aee63e9413fe9e97273e25d57e4", - "reference": "41600c8379eb5aee63e9413fe9e97273e25d57e4", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/a4a7f159927983dd4f7c8020ed227d80b7f39d7d", + "reference": "a4a7f159927983dd4f7c8020ed227d80b7f39d7d", "shasum": "" }, "require": { @@ -903,20 +898,20 @@ "type": "github" } ], - "time": "2025-08-04T19:17:37+00:00" + "time": "2025-10-02T16:07:52+00:00" }, { "name": "rector/rector", - "version": "2.1.2", + "version": "2.1.7", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "40a71441dd73fa150a66102f5ca1364c44fc8fff" + "reference": "c34cc07c4698f007a20dc5c99ff820089ae413ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/40a71441dd73fa150a66102f5ca1364c44fc8fff", - "reference": "40a71441dd73fa150a66102f5ca1364c44fc8fff", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/c34cc07c4698f007a20dc5c99ff820089ae413ce", + "reference": "c34cc07c4698f007a20dc5c99ff820089ae413ce", "shasum": "" }, "require": { @@ -955,7 +950,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.1.2" + "source": "https://github.com/rectorphp/rector/tree/2.1.7" }, "funding": [ { @@ -963,7 +958,7 @@ "type": "github" } ], - "time": "2025-07-17T19:30:06+00:00" + "time": "2025-09-10T11:13:58+00:00" } ], "aliases": [], diff --git a/content/v3/de/awesome-plugins/apm.md b/content/v3/de/awesome-plugins/apm.md index 75d52b2d..27c51e73 100644 --- a/content/v3/de/awesome-plugins/apm.md +++ b/content/v3/de/awesome-plugins/apm.md @@ -1,82 +1,84 @@ -# FlightPHP APM-Dokumentation +# FlightPHP APM Dokumentation -Willkommen bei FlightPHP APM – dein persönlicher Leistungstrainer für deine App! Diese Anleitung ist deine Straßenkarte, um Application Performance Monitoring (APM) mit FlightPHP einzurichten, zu verwenden und zu meistern. Ob du langsame Anfragen aufspürst oder dich einfach über Latenzdiagramme freust, wir haben dich abgedeckt. Lass uns deine App schneller machen, deine Nutzer glücklicher und deine Debugging-Sitzungen unkompliziert! +Willkommen bei FlightPHP APM – dem persönlichen Performance-Coach für Ihre App! Dieser Leitfaden ist Ihre Roadmap zur Einrichtung, Nutzung und Beherrschung der Application Performance Monitoring (APM) mit FlightPHP. Ob Sie langsame Anfragen aufspüren oder einfach nur Latency-Diagramme analysieren möchten, wir haben Sie abgedeckt. Lassen Sie uns Ihre App schneller machen, Ihre Nutzer glücklicher und Ihre Debugging-Sitzungen zu einem Kinderspiel! + +Sehen Sie sich eine [Demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) des Dashboards für die Flight Docs Site an. ![FlightPHP APM](/images/apm.png) ## Warum APM wichtig ist -Stell dir vor: Deine App ist ein volles Restaurant. Ohne eine Möglichkeit, zu verfolgen, wie lange Bestellungen dauern oder wo die Küche hängen bleibt, rätst du nur, warum die Kunden verärgert abreisen. APM ist dein Sous-Chef – es beobachtet jeden Schritt, von eingehenden Anfragen bis zu Datenbankabfragen, und markiert alles, was dich bremst. Langsame Seiten verlieren Nutzer (Studien sagen, 53 % verlassen eine Seite, wenn sie mehr als 3 Sekunden zum Laden braucht!), und APM hilft dir, diese Probleme *bevor* sie schmerzen, zu erkennen. Es ist proaktiver Seelenfrieden – weniger „Warum ist das kaputt?“-Momente, mehr „Schau, wie glatt das läuft!“-Erfolge. +Stellen Sie sich vor: Ihre App ist ein volles Restaurant. Ohne eine Möglichkeit, zu verfolgen, wie lange Bestellungen dauern oder wo die Küche stockt, raten Sie, warum Kunden unzufrieden gehen. APM ist Ihr Sous-Chef – es beobachtet jeden Schritt, von eingehenden Anfragen bis zu Datenbankabfragen, und markiert alles, was Sie verlangsamt. Langsame Seiten verlieren Nutzer (Studien sagen, 53 % verlassen die Seite, wenn sie mehr als 3 Sekunden zum Laden braucht!), und APM hilft Ihnen, diese Probleme *bevor* sie schmerzen zu erkennen. Es ist proaktive Seelenruhe – weniger „Warum ist das kaputt?“-Momente, mehr „Schau, wie reibungslos das läuft!“-Erfolge. ## Installation -Komm mit Composer los: +Beginnen Sie mit Composer: ```bash composer require flightphp/apm ``` -Du brauchst: -- **PHP 7.4+**: Halten wir kompatibel mit LTS-Linux-Distros und unterstützen moderne PHP. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Das leichtgewichtige Framework, das wir verbessern. +Sie benötigen: +- **PHP 7.4+**: Hält uns kompatibel mit LTS Linux-Distributionen, während es modernes PHP unterstützt. +- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Das leichte Framework, das wir boosten. ## Unterstützte Datenbanken FlightPHP APM unterstützt derzeit die folgenden Datenbanken zur Speicherung von Metriken: -- **SQLite3**: Einfach, dateibasierend und großartig für lokale Entwicklung oder kleine Apps. Standardoption in den meisten Einrichtungen. -- **MySQL/MariaDB**: Ideal für größere Projekte oder Produktionsumgebungen, in denen du robusten, skalierbaren Speicherplatz brauchst. +- **SQLite3**: Einfach, dateibasiert und ideal für lokale Entwicklung oder kleine Apps. Standardoption in den meisten Setups. +- **MySQL/MariaDB**: Ideal für größere Projekte oder Produktionsumgebungen, in denen Sie robuste, skalierbare Speicherung benötigen. -Du kannst deinen Datenbanktyp während des Konfigurationsschritts wählen (siehe unten). Stelle sicher, dass deine PHP-Umgebung die notwendigen Erweiterungen installiert hat (z. B. `pdo_sqlite` oder `pdo_mysql`). +Sie können Ihren Datenbanktyp während des Konfigurationsschritts wählen (siehe unten). Stellen Sie sicher, dass Ihre PHP-Umgebung die notwendigen Erweiterungen installiert hat (z. B. `pdo_sqlite` oder `pdo_mysql`). ## Erste Schritte -Hier ist dein schrittweiser Leitfaden zu APM-Großartigkeit: +Hier ist Ihr Schritt-für-Schritt zu APM-Großartigkeit: -### 1. APM registrieren +### 1. Registrieren Sie die APM -Füge das in deine `index.php` oder eine `services.php`-Datei ein, um mit der Verfolgung zu beginnen: +Fügen Sie das in Ihre `index.php` oder eine `services.php`-Datei ein, um mit dem Tracking zu beginnen: ```php use flight\apm\logger\LoggerFactory; use flight\Apm; -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Erstellt deinen Konfig und richtet einen Logger ein – SQLite per Standard +$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); $Apm = new Apm($ApmLogger); $Apm->bindEventsToFlightInstance($app); -// Wenn du eine Datenbankverbindung hinzufügst -// Muss PdoWrapper oder PdoQueryCapture von Tracy-Erweiterungen sein -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True erforderlich, um die Verfolgung in APM zu aktivieren. +// Wenn Sie eine Datenbankverbindung hinzufügen +// Muss PdoWrapper oder PdoQueryCapture aus Tracy Extensions sein +$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True erforderlich, um Tracking in der APM zu aktivieren. $Apm->addPdoConnection($pdo); ``` **Was passiert hier?** -- `LoggerFactory::create()` greift auf deinen Konfig zu (mehr dazu bald) und richtet einen Logger ein – SQLite per Standard. -- `Apm` ist der Star – es hört auf Flight-Ereignisse (Anfragen, Routen, Fehler usw.) und sammelt Metriken. -- `bindEventsToFlightInstance($app)` verbindet alles mit deiner Flight-App. +- `LoggerFactory::create()` greift auf Ihre Konfiguration zu (mehr dazu bald) und richtet einen Logger ein – standardmäßig SQLite. +- `Apm` ist der Star – es hört auf Flights Events (Anfragen, Routen, Fehler usw.) und sammelt Metriken. +- `bindEventsToFlightInstance($app)` verbindet alles mit Ihrer Flight-App. **Pro-Tipp: Sampling** -Wenn deine App beschäftigt ist, könnte das Protokollieren *jeder* Anfrage zu viel werden. Verwende eine Sample-Rate (0,0 bis 1,0): +Wenn Ihre App beschäftigt ist, könnte das Loggen *jeder* Anfrage die Dinge überlasten. Verwenden Sie eine Sample-Rate (0.0 bis 1.0): ```php $Apm = new Apm($ApmLogger, 0.1); // Protokolliert 10 % der Anfragen ``` -Das hält die Leistung flott, während du solide Daten erhältst. +Das hält die Performance knackig, während es Ihnen dennoch solide Daten liefert. -### 2. Konfiguriere es +### 2. Konfigurieren Sie es -Führe das aus, um deine `.runway-config.json` zu erstellen: +Führen Sie das aus, um Ihre `.runway-config.json` zu erstellen: ```bash php vendor/bin/runway apm:init ``` **Was macht das?** -- Startet einen Assistenten, der fragt, woher die unbearbeiteten Metriken kommen (Quelle) und wohin die verarbeiteten Daten gehen (Ziel). -- Standard ist SQLite – z. B. `sqlite:/tmp/apm_metrics.sqlite` für die Quelle, ein weiteres für das Ziel. -- Du erhältst eine Konfig wie: +- Startet einen Wizard, der fragt, wo rohe Metriken herkommen (Quelle) und wo verarbeitete Daten hingehen (Ziel). +- Standard ist SQLite – z. B. `sqlite:/tmp/apm_metrics.sqlite` für die Quelle, eine andere für das Ziel. +- Sie erhalten eine Konfiguration wie: ```json { "apm": { @@ -88,48 +90,48 @@ php vendor/bin/runway apm:init } ``` -> Dieser Prozess fragt auch, ob du die Migrationen für diese Einrichtung ausführen möchtest. Wenn du das zum ersten Mal einrichtest, ist die Antwort ja. +> Dieser Prozess fragt auch, ob Sie die Migrationen für dieses Setup ausführen möchten. Wenn Sie das zum ersten Mal einrichten, lautet die Antwort ja. **Warum zwei Orte?** -Unbearbeitete Metriken sammeln sich schnell (denke an unfiltrierte Protokolle). Der Worker verarbeitet sie in ein strukturiertes Ziel für das Dashboard. Das hält alles ordentlich! +Rohe Metriken häufen sich schnell an (denken Sie an ungefilterte Logs). Der Worker verarbeitet sie in ein strukturiertes Ziel für das Dashboard. Hält alles ordentlich! ### 3. Metriken mit dem Worker verarbeiten -Der Worker verwandelt unbearbeitete Metriken in Dashboard-fähige Daten. Führe ihn einmal aus: +Der Worker verwandelt rohe Metriken in dashboard-bereite Daten. Führen Sie ihn einmal aus: ```bash php vendor/bin/runway apm:worker ``` **Was macht er?** -- Liest von deiner Quelle (z. B. `apm_metrics.sqlite`). -- Verarbeitet bis zu 100 Metriken (Standard-Pakgroße) in dein Ziel. -- Stoppt, wenn fertig oder keine Metriken mehr übrig sind. +- Liest aus Ihrer Quelle (z. B. `apm_metrics.sqlite`). +- Verarbeitet bis zu 100 Metriken (Standard-Batch-Größe) in Ihr Ziel. +- Stoppt, wenn fertig oder keine Metriken mehr da sind. -**Lass es laufen** -Für Live-Apps möchtest du kontinuierliche Verarbeitung. Hier sind deine Optionen: +**Am Laufen halten** +Für Live-Apps möchten Sie kontinuierliche Verarbeitung. Hier sind Ihre Optionen: - **Daemon-Modus**: ```bash php vendor/bin/runway apm:worker --daemon ``` - Läuft ewig und verarbeitet Metriken, sobald sie eintreffen. Toll für Entwicklung oder kleine Einrichtungen. + Läuft ewig und verarbeitet Metriken, sobald sie kommen. Gut für Dev oder kleine Setups. - **Crontab**: - Füge das zu deiner Crontab hinzu (`crontab -e`): + Fügen Sie das zu Ihrer Crontab hinzu (`crontab -e`): ```bash * * * * * php /path/to/project/vendor/bin/runway apm:worker ``` - Führt jede Minute aus – perfekt für Produktion. + Feuert jede Minute – perfekt für Produktion. - **Tmux/Screen**: - Starte eine ablösbare Sitzung: + Starten Sie eine abtrennbare Sitzung: ```bash tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon - # Strg+B, dann D, um zu lösen; `tmux attach -t apm-worker`, um wieder anzuschließen + # Ctrl+B, dann D zum Abtrennen; `tmux attach -t apm-worker` zum Wiederverbinden ``` - Hält es am Laufen, auch wenn du dich abmeldest. + Hält es am Laufen, auch wenn Sie ausloggen. - **Benutzerdefinierte Anpassungen**: ```bash @@ -140,11 +142,11 @@ Für Live-Apps möchtest du kontinuierliche Verarbeitung. Hier sind deine Option - `--timeout 300`: Beendet nach 5 Minuten. **Warum die Mühe?** -Ohne den Worker ist dein Dashboard leer. Es ist die Brücke zwischen unbearbeiteten Protokollen und handlungsrelevanten Erkenntnissen. +Ohne den Worker ist Ihr Dashboard leer. Es ist die Brücke zwischen rohen Logs und handlungsrelevanten Erkenntnissen. -### 4. Das Dashboard starten +### 4. Dashboard starten -Sieh die Vitalwerte deiner App: +Sehen Sie die Vitalwerte Ihrer App: ```bash php vendor/bin/runway apm:dashboard @@ -152,59 +154,59 @@ php vendor/bin/runway apm:dashboard **Was ist das?** - Startet einen PHP-Server unter `http://localhost:8001/apm/dashboard`. -- Zeigt Anfrageprotokolle, langsame Routen, Fehlerquoten und mehr. +- Zeigt Anfragen-Logs, langsame Routen, Fehlerquoten und mehr. -**Passe es an**: +**Anpassen**: ```bash php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php ``` -- `--host 0.0.0.0`: Von jeder IP zugänglich (praktisch für Fernansicht). -- `--port 8080`: Verwende einen anderen Port, wenn 8001 belegt ist. -- `--php-path`: Zeige auf PHP, wenn es nicht in deinem Pfad ist. +- `--host 0.0.0.0`: Erreichbar von jeder IP (praktisch für Fernzugriff). +- `--port 8080`: Verwenden Sie einen anderen Port, wenn 8001 belegt ist. +- `--php-path`: Zeigen Sie auf PHP, wenn es nicht in Ihrem PATH ist. -Öffne die URL in deinem Browser und erkunde! +Öffnen Sie die URL in Ihrem Browser und erkunden Sie! #### Produktionsmodus -In der Produktion musst du möglicherweise einige Techniken ausprobieren, um das Dashboard zu starten, da es wahrscheinlich Firewalls und andere Sicherheitsmaßnahmen gibt. Hier sind ein paar Optionen: +Für die Produktion müssen Sie möglicherweise einige Techniken ausprobieren, um das Dashboard zum Laufen zu bringen, da wahrscheinlich Firewalls und andere Sicherheitsmaßnahmen im Spiel sind. Hier sind ein paar Optionen: -- **Umgekehrtes Proxy**: Richte Nginx oder Apache ein, um Anfragen an das Dashboard weiterzuleiten. -- **SSH-Tunnel**: Wenn du per SSH auf den Server zugreifen kannst, verwende `ssh -L 8080:localhost:8001 youruser@yourserver`, um das Dashboard auf deinen lokalen Rechner zu tunneln. -- **VPN**: Wenn dein Server hinter einem VPN liegt, verbinde dich damit und greife direkt auf das Dashboard zu. -- **Firewall konfigurieren**: Öffne Port 8001 für deine IP oder das Netzwerk des Servers. (oder welchen Port du eingestellt hast). -- **Apache/Nginx konfigurieren**: Wenn du einen Webserver vor deiner Anwendung hast, kannst du ihn für eine Domain oder Subdomain konfigurieren. Wenn du das tust, setze das Dokumentenroot auf `/path/to/your/project/vendor/flightphp/apm/dashboard`. +- **Reverse Proxy verwenden**: Richten Sie Nginx oder Apache ein, um Anfragen an das Dashboard weiterzuleiten. +- **SSH-Tunnel**: Wenn Sie per SSH auf den Server zugreifen können, verwenden Sie `ssh -L 8080:localhost:8001 youruser@yourserver`, um das Dashboard zu Ihrem lokalen Rechner zu tunneln. +- **VPN**: Wenn Ihr Server hinter einem VPN ist, verbinden Sie sich damit und greifen Sie direkt auf das Dashboard zu. +- **Firewall konfigurieren**: Öffnen Sie Port 8001 für Ihre IP oder das Netzwerk des Servers. (Oder welchen Port Sie auch eingestellt haben). +- **Apache/Nginx konfigurieren**: Wenn Sie einen Webserver vor Ihrer Anwendung haben, können Sie ihn für eine Domain oder Subdomain konfigurieren. Wenn Sie das tun, setzen Sie das Document Root auf `/path/to/your/project/vendor/flightphp/apm/dashboard`. -#### Willst du ein anderes Dashboard? +#### Wollen Sie ein anderes Dashboard? -Du kannst dein eigenes Dashboard erstellen, wenn du möchtest! Schau in das Verzeichnis `vendor/flightphp/apm/src/apm/presenter` für Ideen, wie du die Daten für dein eigenes Dashboard darstellen kannst! +Sie können Ihr eigenes Dashboard bauen, wenn Sie möchten! Schauen Sie in das Verzeichnis `vendor/flightphp/apm/src/apm/presenter` für Ideen, wie Sie die Daten für Ihr eigenes Dashboard präsentieren können! ## Dashboard-Funktionen -Das Dashboard ist dein APM-Hauptquartier – hier ist, was du siehst: +Das Dashboard ist Ihr APM-Hauptquartier – hier ist, was Sie sehen werden: -- **Anfrageprotokoll**: Jede Anfrage mit Zeitstempel, URL, Antwortcode und Gesamtzeit. Klicke auf „Details“, um Middleware, Abfragen und Fehler zu sehen. -- **Langsamste Anfragen**: Die Top 5 Anfragen, die Zeit verbrauchen (z. B. „/api/heavy“ bei 2,5 s). -- **Langsamste Routen**: Die Top 5 Routen nach durchschnittlicher Zeit – großartig zum Erkennen von Mustern. -- **Fehlerquote**: Prozentsatz der fehlgeschlagenen Anfragen (z. B. 2,3 % 500er). -- **Latenz-Percentile**: 95. (p95) und 99. (p99) Antwortzeiten – kenne deine schlimmsten Szenarien. -- **Antwortcode-Diagramm**: Visualisiere 200er, 404er, 500er im Laufe der Zeit. -- **Lange Abfragen/Middleware**: Die Top 5 langsamen Datenbankaufrufe und Middleware-Schichten. -- **Cache-Treffer/Fehlgeschlagene**: Wie oft dein Cache hilft. +- **Anfragen-Log**: Jede Anfrage mit Zeitstempel, URL, Response-Code und Gesamtzeit. Klicken Sie auf „Details“ für Middleware, Abfragen und Fehler. +- **Langsamste Anfragen**: Top 5 Anfragen, die Zeit fressen (z. B. „/api/heavy“ bei 2,5 s). +- **Langsamste Routen**: Top 5 Routen nach durchschnittlicher Zeit – super zum Erkennen von Mustern. +- **Fehlerquote**: Prozentsatz fehlgeschlagener Anfragen (z. B. 2,3 % 500er). +- **Latenz-Percentile**: 95. (p95) und 99. (p99) Response-Zeiten – kennen Sie Ihre Worst-Case-Szenarien. +- **Response-Code-Diagramm**: Visualisieren Sie 200er, 404er, 500er über die Zeit. +- **Lange Abfragen/Middleware**: Top 5 langsame Datenbankaufrufe und Middleware-Schichten. +- **Cache-Treffer/Verfehlung**: Wie oft Ihr Cache den Tag rettet. -**Zusätze**: -- Filtere nach „Letzte Stunde“, „Letzter Tag“ oder „Letzte Woche“. -- Schalte den Dunkelmodus für nächtliche Sitzungen ein. +**Extras**: +- Filtern nach „Letzte Stunde“, „Letzter Tag“ oder „Letzte Woche“. +- Umschalten auf Dark Mode für nächtliche Sessions. **Beispiel**: -Eine Anfrage zu `/users` könnte zeigen: +Eine Anfrage an `/users` könnte zeigen: - Gesamtzeit: 150 ms - Middleware: `AuthMiddleware->handle` (50 ms) - Abfrage: `SELECT * FROM users` (80 ms) -- Cache: Treffer auf `user_list` (5 ms) +- Cache: Treffer bei `user_list` (5 ms) -## Hinzufügen benutzerdefinierter Ereignisse +## Hinzufügen benutzerdefinierter Events -Verfolge alles – wie einen API-Aufruf oder einen Zahlungsprozess: +Verfolgen Sie alles – wie einen API-Aufruf oder Zahlungsprozess: ```php use flight\apm\CustomEvent; @@ -216,10 +218,10 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ])); ``` -**Wo zeigt es auf?** -In den Anfragedetails des Dashboards unter „Benutzerdefinierte Ereignisse“ – erweiterbar mit hübscher JSON-Formatierung. +**Wo erscheint es?** +In den Anfragen-Details des Dashboards unter „Custom Events“ – erweiterbar mit hübscher JSON-Formatierung. -**Anwendungsfalld**: +**Anwendungsfall**: ```php $start = microtime(true); $apiResponse = file_get_contents('https://api.example.com/data'); @@ -229,28 +231,28 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -Jetzt siehst du, ob diese API deine App bremst! +Jetzt sehen Sie, ob diese API Ihre App herunterzieht! -## Datenbanküberwachung +## Datenbank-Monitoring -Verfolge PDO-Abfragen so: +Verfolgen Sie PDO-Abfragen so: ```php use flight\database\PdoWrapper; -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True erforderlich, um die Verfolgung in APM zu aktivieren. +$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True erforderlich, um Tracking in der APM zu aktivieren. $Apm->addPdoConnection($pdo); ``` -**Was du bekommst**: +**Was Sie bekommen**: - Abfragetext (z. B. `SELECT * FROM users WHERE id = ?`) - Ausführungszeit (z. B. 0,015 s) - Zeilenanzahl (z. B. 42) **Achtung**: -- **Optional**: Überspringe das, wenn du keine DB-Verfolgung brauchst. -- **Nur PdoWrapper**: Kern-PDO ist noch nicht angebunden – bleib dran! -- **Leistungs-Warnung**: Das Protokollieren jeder Abfrage auf einer DB-intensiven Site kann Dinge verlangsamen. Verwende Sampling (`$Apm = new Apm($ApmLogger, 0.1)`), um die Last zu reduzieren. +- **Optional**: Überspringen Sie das, wenn Sie kein DB-Tracking brauchen. +- **Nur PdoWrapper**: Core PDO ist noch nicht integriert – bleiben Sie dran! +- **Performance-Warnung**: Das Loggen jeder Abfrage auf einer DB-lastigen Site kann Dinge verlangsamen. Verwenden Sie Sampling (`$Apm = new Apm($ApmLogger, 0.1)`), um die Last zu reduzieren. **Beispiel-Ausgabe**: - Abfrage: `SELECT name FROM products WHERE price > 100` @@ -259,56 +261,56 @@ $Apm->addPdoConnection($pdo); ## Worker-Optionen -Passe den Worker an deine Vorlieben an: +Passen Sie den Worker nach Ihrem Geschmack an: - `--timeout 300`: Stoppt nach 5 Minuten – gut für Tests. -- `--max_messages 500`: Begrenzt auf 500 Metriken – hält es begrenzt. +- `--max_messages 500`: Begrenzt auf 500 Metriken – hält es endlich. - `--batch_size 200`: Verarbeitet 200 auf einmal – balanciert Geschwindigkeit und Speicher. -- `--daemon`: Läuft ununterbrochen – ideal für Live-Überwachung. +- `--daemon`: Läuft non-stop – ideal für Live-Monitoring. **Beispiel**: ```bash php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ``` -Läuft eine Stunde lang und verarbeitet 100 Metriken auf einmal. +Läuft eine Stunde, verarbeitet 100 Metriken auf einmal. -## Request-ID in der App +## Request ID in der App -Jede Anfrage hat eine eindeutige Request-ID zur Verfolgung. Du kannst diese ID in deiner App verwenden, um Protokolle und Metriken zu korrelieren. Zum Beispiel kannst du die Request-ID auf einer Fehlerseite hinzufügen: +Jede Anfrage hat eine eindeutige Request ID für das Tracking. Sie können diese ID in Ihrer App verwenden, um Logs und Metriken zu korrelieren. Zum Beispiel können Sie die Request ID auf einer Fehlerseite hinzufügen: ```php Flight::map('error', function($message) { - // Hole die Request-ID aus dem Response-Header X-Flight-Request-Id + // Holen Sie die Request ID aus dem Response-Header X-Flight-Request-Id $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - // Zusätzlich könntest du sie aus der Flight-Variablen holen + // Zusätzlich könnten Sie sie aus der Flight-Variable holen // Diese Methode funktioniert nicht gut in Swoole oder anderen asynchronen Plattformen. // $requestId = Flight::get('apm.request_id'); - echo "Error: $message (Request ID: $requestId)"; + echo "Fehler: $message (Request ID: $requestId)"; }); ``` ## Upgrade -Wenn du auf eine neuere Version von APM aktualisierst, könnte es sein, dass Datenbank-Migrationen ausgeführt werden müssen. Du kannst das tun, indem du den folgenden Befehl ausführst: +Wenn Sie auf eine neuere Version der APM upgraden, besteht die Möglichkeit, dass Datenbank-Migrationen ausgeführt werden müssen. Sie können das tun, indem Sie den folgenden Befehl ausführen: ```bash php vendor/bin/runway apm:migrate ``` Das führt alle benötigten Migrationen aus, um das Datenbankschema auf die neueste Version zu aktualisieren. -**Hinweis:** Wenn deine APM-Datenbank groß ist, könnte diese Ausführung Zeit in Anspruch nehmen. Du möchtest den Befehl vielleicht in den Nebenzeiten ausführen. +**Hinweis:** Wenn Ihre APM-Datenbank groß ist, können diese Migrationen einige Zeit in Anspruch nehmen. Sie möchten diesen Befehl vielleicht während der Nebenzeiten ausführen. -## Bereinigen alter Daten +## Alte Daten bereinigen -Um deine Datenbank aufgeräumt zu halten, kannst du alte Daten löschen. Das ist besonders nützlich, wenn du eine beschäftigte App betreibst und die Datenbankgröße handhabbar halten möchtest. -Du kannst das tun, indem du den folgenden Befehl ausführst: +Um Ihre Datenbank ordentlich zu halten, können Sie alte Daten bereinigen. Das ist besonders nützlich, wenn Sie eine beschäftigte App betreiben und die Datenbankgröße handhabbar halten möchten. +Sie können das tun, indem Sie den folgenden Befehl ausführen: ```bash php vendor/bin/runway apm:purge ``` -Das entfernt alle Daten, die älter als 30 Tage sind, aus der Datenbank. Du kannst die Anzahl der Tage anpassen, indem du einen anderen Wert an die Option `--days` übergeben: +Das entfernt alle Daten, die älter als 30 Tage sind, aus der Datenbank. Sie können die Anzahl der Tage anpassen, indem Sie einen anderen Wert an die `--days`-Option übergeben: ```bash php vendor/bin/runway apm:purge --days 7 @@ -317,29 +319,29 @@ Das entfernt alle Daten, die älter als 7 Tage sind, aus der Datenbank. ## Fehlerbehebung -Festhängen? Probiere das: +Feststecken? Probieren Sie diese aus: - **Kein Dashboard-Daten?** - - Läuft der Worker? Überprüfe `ps aux | grep apm:worker`. - - Stimmen die Konfig-Pfade? Überprüfe, ob die DSNs in `.runway-config.json` auf echte Dateien zeigen. - - Führe `php vendor/bin/runway apm:worker` manuell aus, um ausstehende Metriken zu verarbeiten. + - Läuft der Worker? Überprüfen Sie `ps aux | grep apm:worker`. + - Stimmen die Konfigurationspfade? Überprüfen Sie, ob die DSNs in `.runway-config.json` auf echte Dateien zeigen. + - Führen Sie `php vendor/bin/runway apm:worker` manuell aus, um ausstehende Metriken zu verarbeiten. - **Worker-Fehler?** - - Schau in deine SQLite-Dateien (z. B. `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Überprüfe PHP-Protokolle auf Stack-Traces. + - Schauen Sie in Ihre SQLite-Dateien (z. B. `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). + - Überprüfen Sie PHP-Logs auf Stack-Traces. - **Dashboard startet nicht?** - - Ist Port 8001 belegt? Verwende `--port 8080`. - - PHP nicht gefunden? Verwende `--php-path /usr/bin/php`. - - Firewall blockiert? Öffne den Port oder verwende `--host localhost`. + - Port 8001 belegt? Verwenden Sie `--port 8080`. + - PHP nicht gefunden? Verwenden Sie `--php-path /usr/bin/php`. + - Firewall blockiert? Öffnen Sie den Port oder verwenden Sie `--host localhost`. - **Zu langsam?** - - Reduziere die Sample-Rate: `$Apm = new Apm($ApmLogger, 0.05)` (5 %). - - Reduziere die Pakgroße: `--batch_size 20`. + - Senken Sie die Sample-Rate: `$Apm = new Apm($ApmLogger, 0.05)` (5 %). + - Reduzieren Sie die Batch-Größe: `--batch_size 20`. -- **Verfolgt keine Ausnahmen/Fehler?** - - Wenn du [Tracy](https://tracy.nette.org/) für dein Projekt aktiviert hast, überschreibt es Flights Fehlerbehandlung. Du musst Tracy deaktivieren und sicherstellen, dass `Flight::set('flight.handle_errors', true);` gesetzt ist. +- **Keine Ausnahmen/Fehler getrackt?** + - Wenn Sie [Tracy](https://tracy.nette.org/) für Ihr Projekt aktiviert haben, überschreibt es die Fehlerbehandlung von Flight. Sie müssen Tracy deaktivieren und sicherstellen, dass `Flight::set('flight.handle_errors', true);` gesetzt ist. -- **Verfolgt keine Datenbankabfragen?** - - Stelle sicher, dass du `PdoWrapper` für deine Datenbankverbindungen verwendest. - - Stelle sicher, dass du das letzte Argument im Konstruktor auf `true` setzt. \ No newline at end of file +- **Datenbankabfragen nicht getrackt?** + - Stellen Sie sicher, dass Sie `PdoWrapper` für Ihre Datenbankverbindungen verwenden. + - Vergewissern Sie sich, dass Sie das letzte Argument im Konstruktor auf `true` setzen. \ No newline at end of file diff --git a/content/v3/de/learn/ai.md b/content/v3/de/learn/ai.md index 17152b4b..6b101681 100644 --- a/content/v3/de/learn/ai.md +++ b/content/v3/de/learn/ai.md @@ -2,22 +2,22 @@ ## Überblick -Flight erleichtert es, Ihre PHP-Projekte mit KI-gestützten Tools und modernen Entwickler-Workflows zu superchargen. Mit integrierten Befehlen zum Verbinden mit LLM-Anbietern (Large Language Model) und zur Generierung projektspezifischer KI-Coding-Anweisungen hilft Flight Ihnen und Ihrem Team, das Maximum aus KI-Assistenten wie GitHub Copilot, Cursor und Windsurf herauszuholen. +Flight erleichtert es, Ihre PHP-Projekte mit KI-gestützten Tools und modernen Entwickler-Workflows zu superchargen. Mit integrierten Befehlen zum Verbinden mit LLM-Anbietern (Large Language Model) und zum Generieren projektspezifischer KI-Codierungsanweisungen hilft Flight Ihnen und Ihrem Team, das Maximum aus KI-Assistenten wie GitHub Copilot, Cursor und Windsurf herauszuholen. ## Verständnis -KI-Coding-Assistenten sind am hilfreichsten, wenn sie den Kontext, die Konventionen und die Ziele Ihres Projekts verstehen. Die KI-Hilfsprogramme von Flight ermöglichen es Ihnen: +KI-Codierungsassistenten sind am hilfreichsten, wenn sie den Kontext, die Konventionen und die Ziele Ihres Projekts verstehen. Die KI-Hilfsprogramme von Flight ermöglichen es Ihnen: - Ihr Projekt mit beliebten LLM-Anbietern zu verbinden (OpenAI, Grok, Claude usw.) -- Projektspezifische Anweisungen für KI-Tools zu generieren und zu aktualisieren, damit jeder konsistente, relevante Hilfe erhält +- Projektspezifische Anweisungen für KI-Tools zu generieren und zu aktualisieren, damit alle konsistente, relevante Hilfe erhalten - Ihr Team ausgerichtet und produktiv zu halten, mit weniger Zeit für die Erklärung des Kontexts -Diese Funktionen sind in die Flight-Core-CLI und das offizielle [flightphp/skeleton](https://github.com/flightphp/skeleton)-Starter-Projekt integriert. +Diese Funktionen sind in die Kern-CLI von Flight und das offizielle [flightphp/skeleton](https://github.com/flightphp/skeleton) Starter-Projekt integriert. -## Grundlegende Nutzung +## Grundlegende Verwendung -### 1. Einrichten von LLM-Anmeldeinformationen +### Einrichten von LLM-Zugangsdaten -Der Befehl `ai:init` führt Sie durch die Verbindung Ihres Projekts mit einem LLM-Anbieter. +Der Befehl `ai:init` führt Sie durch den Prozess, Ihr Projekt mit einem LLM-Anbieter zu verbinden. ```bash php runway ai:init @@ -37,27 +37,27 @@ Welchen LLM-API möchten Sie verwenden? [1] openai, [2] grok, [3] claude: 1 Geben Sie die Basis-URL für die LLM-API ein [https://api.openai.com]: Geben Sie Ihren API-Schlüssel für openai ein: sk-... Geben Sie den Modellnamen ein, den Sie verwenden möchten (z. B. gpt-4, claude-3-opus usw.) [gpt-4o]: -Anmeldeinformationen in .runway-creds.json gespeichert +Zugangsdaten in .runway-creds.json gespeichert ``` -### 2. Generieren projektspezifischer KI-Anweisungen +### Generieren projektspezifischer KI-Anweisungen -Der Befehl `ai:generate-instructions` hilft Ihnen, Anweisungen für KI-Coding-Assistenten zu erstellen oder zu aktualisieren, die auf Ihr Projekt zugeschnitten sind. +Der Befehl `ai:generate-instructions` hilft Ihnen, Anweisungen für KI-Codierungsassistenten zu erstellen oder zu aktualisieren, die auf Ihr Projekt zugeschnitten sind. ```bash php runway ai:generate-instructions ``` -Sie beantworten ein paar Fragen zu Ihrem Projekt (Beschreibung, Datenbank, Vorlagen, Sicherheit, Teamgröße usw.). Flight verwendet Ihren LLM-Anbieter, um Anweisungen zu generieren, und schreibt sie dann in: +Sie beantworten ein paar Fragen zu Ihrem Projekt (Beschreibung, Datenbank, Templating, Sicherheit, Teamgröße usw.). Flight verwendet Ihren LLM-Anbieter, um Anweisungen zu generieren, und schreibt sie dann in: - `.github/copilot-instructions.md` (für GitHub Copilot) - `.cursor/rules/project-overview.mdc` (für Cursor) - `.windsurfrules` (für Windsurf) **Beispiel:** ``` -Beschreiben Sie bitte, wofür Ihr Projekt gedacht ist? My awesome API +Beschreiben Sie bitte, wofür Ihr Projekt gedacht ist? Meine tolle API Welche Datenbank planen Sie zu verwenden? MySQL -Welchen HTML-Vorlagen-Engine planen Sie zu verwenden (falls zutreffend)? latte +Welchen HTML-Templating-Engine planen Sie zu verwenden (falls zutreffend)? latte Ist Sicherheit ein wichtiger Aspekt dieses Projekts? (y/n) y ... KI-Anweisungen erfolgreich aktualisiert. @@ -65,11 +65,11 @@ KI-Anweisungen erfolgreich aktualisiert. Nun geben Ihre KI-Tools intelligentere, relevantere Vorschläge basierend auf den tatsächlichen Bedürfnissen Ihres Projekts. -## Erweiterte Nutzung +## Erweiterte Verwendung -- Sie können den Speicherort Ihrer Anmeldeinformations- oder Anweisungsdateien mit Befehlsoptionen anpassen (siehe `--help` für jeden Befehl). +- Sie können den Speicherort Ihrer Zugangsdaten- oder Anweisungsdateien mit Befehlsoptionen anpassen (siehe `--help` für jeden Befehl). - Die KI-Hilfsprogramme sind so konzipiert, dass sie mit jedem LLM-Anbieter funktionieren, der OpenAI-kompatible APIs unterstützt. -- Wenn Sie Ihre Anweisungen aktualisieren möchten, während sich Ihr Projekt weiterentwickelt, führen Sie einfach `ai:generate-instructions` erneut aus und beantworten Sie die Aufforderungen erneut. +- Wenn Sie Ihre Anweisungen aktualisieren möchten, während sich Ihr Projekt weiterentwickelt, führen Sie einfach `ai:generate-instructions` erneut aus und beantworten Sie die Prompts erneut. ## Siehe auch @@ -84,4 +84,4 @@ Nun geben Ihre KI-Tools intelligentere, relevantere Vorschläge basierend auf de ## Änderungsprotokoll -- v3.16.0 – Hinzugefügt: `ai:init` und `ai:generate-instructions` CLI-Befehle für KI-Integration. \ No newline at end of file +- v3.16.0 – Hinzugefügt: CLI-Befehle `ai:init` und `ai:generate-instructions` für KI-Integration. \ No newline at end of file diff --git a/content/v3/de/learn/requests.md b/content/v3/de/learn/requests.md index 47cde208..7feca9b5 100644 --- a/content/v3/de/learn/requests.md +++ b/content/v3/de/learn/requests.md @@ -1,24 +1,24 @@ -# Anfragen +# Requests -## Überblick +## Overview -Flight kapselt die HTTP-Anfrage in ein einzelnes Objekt, das auf folgende Weise zugänglich ist: +Flight kapselt die HTTP-Anfrage in ein einzelnes Objekt, das wie folgt zugänglich ist: ```php $request = Flight::request(); ``` -## Verständnis +## Understanding -HTTP-Anfragen sind einer der Kernaspekte, die man über den HTTP-Lebenszyklus verstehen sollte. Ein Benutzer führt eine Aktion in einem Webbrowser oder einem HTTP-Client aus, und sie senden eine Reihe von Headern, Body, URL usw. an Ihr Projekt. Sie können diese Header (die Sprache des Browsers, welche Art von Kompression sie handhaben können, den User Agent usw.) erfassen und den Body und die URL, die an Ihre Flight-Anwendung gesendet werden, erfassen. Diese Anfragen sind essenziell, damit Ihre App versteht, was als Nächstes zu tun ist. +HTTP-Anfragen sind einer der Kernaspekte, die es zu verstehen gilt, um den HTTP-Lebenszyklus zu verstehen. Ein Benutzer führt eine Aktion in einem Webbrowser oder einem HTTP-Client aus, und sie senden eine Reihe von Headern, Body, URL usw. an Ihr Projekt. Sie können diese Header (die Sprache des Browsers, welche Art von Komprimierung sie handhaben können, den User Agent usw.) erfassen und den Body und die URL, die an Ihre Flight-Anwendung gesendet werden, erfassen. Diese Anfragen sind essenziell, damit Ihre App versteht, was als Nächstes zu tun ist. -## Grundlegende Verwendung +## Basic Usage -PHP hat mehrere Super-Global-Variablen, einschließlich `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` und `$_COOKIE`. Flight abstrahiert diese in praktische [Collections](/learn/collections). Sie können die Eigenschaften `query`, `data`, `cookies` und `files` als Arrays oder Objekte zugreifen. +PHP hat mehrere Super-Globalen, einschließlich `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` und `$_COOKIE`. Flight abstrahiert diese in praktische [Collections](/learn/collections). Sie können die Eigenschaften `query`, `data`, `cookies` und `files` als Arrays oder Objekte zugreifen. -> **Hinweis:** Es wird **STRONGLICH** davon abgeraten, diese Super-Global-Variablen in Ihrem Projekt zu verwenden, und sie sollten über das `request()`-Objekt referenziert werden. +> **Hinweis:** Es wird **STRONGLICH** davon abgeraten, diese Super-Globalen in Ihrem Projekt zu verwenden, und sie sollten über das `request()`-Objekt referenziert werden. -> **Hinweis:** Es gibt keine Abstraktion für `$_ENV` verfügbar. +> **Hinweis:** Es gibt keine Abstraktion für `$_ENV`. ### `$_GET` @@ -28,10 +28,10 @@ Sie können das `$_GET`-Array über die `query`-Eigenschaft zugreifen: // GET /search?keyword=something Flight::route('/search', function(){ $keyword = Flight::request()->query['keyword']; - // oder + // or $keyword = Flight::request()->query->keyword; - echo "Sie suchen nach: $keyword"; - // fragen Sie eine Datenbank oder etwas Ähnliches mit dem $keyword ab + echo "You are searching for: $keyword"; + // query a database or something else with the $keyword }); ``` @@ -43,11 +43,11 @@ Sie können das `$_POST`-Array über die `data`-Eigenschaft zugreifen: Flight::route('POST /submit', function(){ $name = Flight::request()->data['name']; $email = Flight::request()->data['email']; - // oder + // or $name = Flight::request()->data->name; $email = Flight::request()->data->email; - echo "Sie haben eingereicht: $name, $email"; - // speichern Sie in einer Datenbank oder etwas Ähnliches mit dem $name und $email + echo "You submitted: $name, $email"; + // save to a database or something else with the $name and $email }); ``` @@ -58,9 +58,9 @@ Sie können das `$_COOKIE`-Array über die `cookies`-Eigenschaft zugreifen: ```php Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; - // oder + // or $savedLogin = Flight::request()->cookies->myLoginCookie; - // prüfen Sie, ob es wirklich gespeichert ist oder nicht, und wenn ja, loggen Sie sie automatisch ein + // check if it's really saved or not and if it is auto log them in if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -84,23 +84,23 @@ $host = Flight::request()->getVar('HTTP_HOST'); Sie können hochgeladene Dateien über die `files`-Eigenschaft zugreifen: ```php -// roher Zugriff auf die $_FILES-Eigenschaft. Siehe unten für den empfohlenen Ansatz +// raw access to $_FILES property. See below for recommended approach $uploadedFile = Flight::request()->files['myFile']; -// oder +// or $uploadedFile = Flight::request()->files->myFile; ``` -Siehe [Uploaded File Handler](/learn/uploaded-file) für weitere Infos. +Siehe [Uploaded File Handler](/learn/uploaded-file) für mehr Infos. -#### Verarbeiten von Datei-Uploads +#### Processing File Uploads _v3.12.0_ -Sie können Datei-Uploads mit dem Framework und einigen Hilfsmethoden verarbeiten. Es kommt im Wesentlichen darauf an, die Dateidaten aus der Anfrage zu ziehen und sie an einen neuen Ort zu verschieben. +Sie können Datei-Uploads mit dem Framework und einigen Hilfsmethoden verarbeiten. Es läuft im Wesentlichen darauf hinaus, die Dateidaten aus der Anfrage zu ziehen und sie an einen neuen Speicherort zu verschieben. ```php Flight::route('POST /upload', function(){ - // Wenn Sie ein Eingabefeld wie haben + // If you had an input field like $uploadedFileData = Flight::request()->getUploadedFiles(); $uploadedFile = $uploadedFileData['myFile']; $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); @@ -111,7 +111,7 @@ Wenn Sie mehrere Dateien hochgeladen haben, können Sie durch sie iterieren: ```php Flight::route('POST /upload', function(){ - // Wenn Sie ein Eingabefeld wie haben + // If you had an input field like $uploadedFiles = Flight::request()->getUploadedFiles()['myFiles']; foreach ($uploadedFiles as $uploadedFile) { $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); @@ -119,94 +119,93 @@ Flight::route('POST /upload', function(){ }); ``` -> **Sicherheitshinweis:** Validieren und sanitieren Sie immer Benutzereingaben, insbesondere bei Datei-Uploads. Validieren Sie immer den Typ der Erweiterungen, die Sie zum Hochladen erlauben, aber Sie sollten auch die "Magic Bytes" der Datei validieren, um sicherzustellen, dass es tatsächlich der Dateityp ist, den der Benutzer angibt. Es gibt [Artikel](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [und](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [Bibliotheken](https://github.com/RikudouSage/MimeTypeDetector), die dabei helfen. +> **Sicherheitshinweis:** Validieren und sanitieren Sie immer Benutzereingaben, insbesondere bei Datei-Uploads. Validieren Sie immer den Typ der Erweiterungen, die Sie hochladen lassen, aber Sie sollten auch die "Magic Bytes" der Datei validieren, um sicherzustellen, dass es tatsächlich der Dateityp ist, den der Benutzer angibt. Es gibt [Artikel](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [und](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [Bibliotheken](https://github.com/RikudouSage/MimeTypeDetector), die dabei helfen. -### Anfragen-Body +### Request Body -Um den rohen HTTP-Anfragen-Body zu erhalten, z. B. bei POST/PUT-Anfragen, können Sie Folgendes tun: +Um den rohen HTTP-Anfragetext zu erhalten, z. B. bei POST/PUT-Anfragen, können Sie Folgendes tun: ```php Flight::route('POST /users/xml', function(){ $xmlBody = Flight::request()->getBody(); - // tun Sie etwas mit dem gesendeten XML. + // do something with the XML that was sent. }); ``` -### JSON-Body +### JSON Body -Wenn Sie eine Anfrage mit dem Content-Type `application/json` und den Beispieldaten `{"id": 123}` erhalten, ist sie über die `data`-Eigenschaft verfügbar: +Wenn Sie eine Anfrage mit dem Inhaltstyp `application/json` und den Beispieldaten `{"id": 123}` erhalten, ist sie über die `data`-Eigenschaft verfügbar: ```php $id = Flight::request()->data->id; ``` -### Anfragen-Header +### Request Headers -Sie können Anfragen-Header mit der `getHeader()`- oder `getHeaders()`-Methode zugreifen: +Sie können Anfrage-Header mit der `getHeader()`- oder `getHeaders()`-Methode zugreifen: ```php -// Vielleicht brauchen Sie den Authorization-Header +// Maybe you need Authorization header $host = Flight::request()->getHeader('Authorization'); -// oder +// or $host = Flight::request()->header('Authorization'); -// Wenn Sie alle Header holen müssen +// If you need to grab all headers $headers = Flight::request()->getHeaders(); -// oder +// or $headers = Flight::request()->headers(); ``` -### Anfragen-Methode +### Request Method -Sie können die Anfragen-Methode mit der `method`-Eigenschaft oder der `getMethod()`-Methode zugreifen: +Sie können die Anfragemethode mit der `method`-Eigenschaft oder der `getMethod()`-Methode zugreifen: ```php -$method = Flight::request()->method; // tatsächlich von getMethod() befüllt +$method = Flight::request()->method; // actually populated by getMethod() $method = Flight::request()->getMethod(); ``` -**Hinweis:** Die `getMethod()`-Methode holt zuerst die Methode aus `$_SERVER['REQUEST_METHOD']`, dann kann sie von `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` überschrieben werden, wenn sie existiert, oder `$_REQUEST['_method']`, wenn sie existiert. +**Hinweis:** Die `getMethod()`-Methode zieht zunächst die Methode aus `$_SERVER['REQUEST_METHOD']`, dann kann sie von `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` überschrieben werden, falls vorhanden, oder `$_REQUEST['_method']`, falls vorhanden. -## Eigenschaften des Anfragen-Objekts +## Request Object Properties -Das Anfragen-Objekt stellt die folgenden Eigenschaften zur Verfügung: +Das Anfrage-Objekt stellt die folgenden Eigenschaften bereit: -- **body** - Der rohe HTTP-Anfragen-Body +- **body** - Der rohe HTTP-Anfragetext - **url** - Die angeforderte URL - **base** - Das übergeordnete Unterverzeichnis der URL -- **method** - Die Anfragen-Methode (GET, POST, PUT, DELETE) +- **method** - Die Anfragemethode (GET, POST, PUT, DELETE) - **referrer** - Die Referrer-URL - **ip** - IP-Adresse des Clients - **ajax** - Ob es sich um eine AJAX-Anfrage handelt - **scheme** - Das Server-Protokoll (http, https) - **user_agent** - Browser-Informationen -- **type** - Der Content-Type -- **length** - Die Content-Länge +- **type** - Der Inhaltstyp +- **length** - Die Inhaltslänge - **query** - Query-String-Parameter - **data** - Post-Daten oder JSON-Daten - **cookies** - Cookie-Daten - **files** - Hochgeladene Dateien - **secure** - Ob die Verbindung sicher ist - **accept** - HTTP-Accept-Parameter -- **proxy_ip** - Proxy-IP-Adresse des Clients. Scant das `$_SERVER`-Array nach `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` in dieser Reihenfolge. +- **proxy_ip** - Proxy-IP-Adresse des Clients. Scannt das `$_SERVER`-Array nach `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` in dieser Reihenfolge. - **host** - Der Anfragen-Hostname - **servername** - Der SERVER_NAME aus `$_SERVER` -## Hilfsmethoden für URLs +## Helper Methods -Es gibt ein paar Hilfsmethoden, um Teile einer URL für Ihre Bequemlichkeit zusammenzusetzen. +Es gibt ein paar Hilfsmethoden, um Teile einer URL zusammenzusetzen oder mit bestimmten Headern umzugehen. -### Volle URL +### Full URL -Sie können die volle Anfragen-URL mit der `getFullUrl()`-Methode zugreifen: +Sie können die vollständige Anfrage-URL mit der `getFullUrl()`-Methode zugreifen: ```php $url = Flight::request()->getFullUrl(); // https://example.com/some/path?foo=bar ``` - -### Basis-URL +### Base URL Sie können die Basis-URL mit der `getBaseUrl()`-Methode zugreifen: @@ -214,10 +213,10 @@ Sie können die Basis-URL mit der `getBaseUrl()`-Methode zugreifen: // http://example.com/path/to/something/cool?query=yes+thanks $url = Flight::request()->getBaseUrl(); // https://example.com -// Beachten Sie, kein abschließender Schrägstrich. +// Notice, no trailing slash. ``` -## Query-Parsing +## Query Parsing Sie können eine URL an die `parseQuery()`-Methode übergeben, um den Query-String in ein assoziatives Array zu parsen: @@ -226,16 +225,40 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` -## Siehe auch -- [Routing](/learn/routing) - Sehen Sie, wie Routen zu Controllern zugeordnet und Views gerendert werden. -- [Responses](/learn/responses) - Wie man HTTP-Antworten anpasst. -- [Warum ein Framework?](/learn/why-frameworks) - Wie Anfragen in das große Ganze passen. -- [Collections](/learn/collections) - Arbeiten mit Sammlungen von Daten. -- [Uploaded File Handler](/learn/uploaded-file) - Handhaben von Datei-Uploads. +## Negotiate Content Accept Types + +_v3.17.2_ + +Sie können die `negotiateContentType()`-Methode verwenden, um den besten Inhaltstyp zu bestimmen, mit dem geantwortet werden soll, basierend auf dem `Accept`-Header, der vom Client gesendet wird. + +```php + +// Example Accept header: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// The below defines what you support. +$availableTypes = ['application/json', 'application/xml']; +$typeToServe = Flight::request()->negotiateContentType($availableTypes); +if ($typeToServe === 'application/json') { + // Serve JSON response +} elseif ($typeToServe === 'application/xml') { + // Serve XML response +} else { + // Default to something else or throw an error +} +``` + +> **Hinweis:** Wenn keiner der verfügbaren Typen im `Accept`-Header gefunden wird, gibt die Methode `null` zurück. Wenn kein `Accept`-Header definiert ist, gibt die Methode den ersten Typ im `$availableTypes`-Array zurück. + +## See Also +- [Routing](/learn/routing) - See how to map routes to controllers and render views. +- [Responses](/learn/responses) - How to customize HTTP responses. +- [Why a Framework?](/learn/why-frameworks) - How requests fit into the big picture. +- [Collections](/learn/collections) - Working with collections of data. +- [Uploaded File Handler](/learn/uploaded-file) - Handling file uploads. -## Fehlerbehebung -- `request()->ip` und `request()->proxy_ip` können unterschiedlich sein, wenn Ihr Webserver hinter einem Proxy, Load Balancer usw. ist. +## Troubleshooting +- `request()->ip` and `request()->proxy_ip` can be different if your webserver is behind a proxy, load balancer, etc. ## Changelog -- v3.12.0 - Fähigkeit hinzugefügt, Datei-Uploads über das Anfragen-Objekt zu handhaben. -- v1.0 - Erste Veröffentlichung. \ No newline at end of file +- v3.17.2 - Added negotiateContentType() +- v3.12.0 - Added ability to handle file uploads through the request object. +- v1.0 - Initial release. \ No newline at end of file diff --git a/content/v3/de/learn/responses.md b/content/v3/de/learn/responses.md index b4d09e4f..6a57689d 100644 --- a/content/v3/de/learn/responses.md +++ b/content/v3/de/learn/responses.md @@ -1,21 +1,21 @@ # Responses -## Overview +## Überblick Flight hilft dabei, Teile der Response-Header für Sie zu generieren, aber Sie haben die meiste Kontrolle darüber, was Sie an den Benutzer zurücksenden. Meistens greifen Sie direkt auf das `response()`-Objekt zu, aber Flight bietet einige Hilfsmethoden, um einige der Response-Header für Sie zu setzen. -## Understanding +## Verständnis -Nachdem der Benutzer seine [request](/learn/requests)-Anfrage an Ihre Anwendung gesendet hat, müssen Sie eine angemessene Response für sie generieren. Sie haben Ihnen Informationen wie die bevorzugte Sprache, ob sie bestimmte Kompressionstypen handhaben können, ihren User Agent usw. gesendet, und nach der Verarbeitung von allem ist es Zeit, eine angemessene Response zurückzusenden. Dies kann das Setzen von Headern sein, das Ausgeben eines HTML- oder JSON-Bodys für sie oder das Weiterleiten zu einer Seite. +Nachdem der Benutzer seine [request](/learn/requests)-Anfrage an Ihre Anwendung gesendet hat, müssen Sie eine angemessene Response für sie generieren. Sie haben Ihnen Informationen wie die bevorzugte Sprache, ob sie bestimmte Kompressionstypen handhaben können, ihren User Agent usw. gesendet, und nach der Verarbeitung von allem ist es Zeit, ihnen eine angemessene Response zurückzusenden. Dies kann das Setzen von Headern, das Ausgeben eines HTML- oder JSON-Bodys für sie oder das Weiterleiten zu einer Seite sein. -## Basic Usage +## Grundlegende Verwendung -### Sending a Response Body +### Senden eines Response-Bodys Flight verwendet `ob_start()`, um die Ausgabe zu puffern. Das bedeutet, Sie können `echo` oder `print` verwenden, um eine Response an den Benutzer zu senden, und Flight wird sie erfassen und mit den entsprechenden Headern an den Benutzer zurücksenden. ```php -// Dies wird "Hello, World!" an den Browser des Benutzers senden +// Dies sendet "Hello, World!" an den Browser des Benutzers Flight::route('/', function() { echo "Hello, World!"; }); @@ -26,10 +26,10 @@ Flight::route('/', function() { // Hello, World! ``` -Als Alternative können Sie auch die `write()`-Methode aufrufen, um zum Body hinzuzufügen. +Als Alternative können Sie die `write()`-Methode aufrufen, um zum Body hinzuzufügen. ```php -// Dies wird "Hello, World!" an den Browser des Benutzers senden +// Dies sendet "Hello, World!" an den Browser des Benutzers Flight::route('/', function() { // ausführlich, aber erledigt den Job manchmal, wenn Sie es brauchen Flight::response()->write("Hello, World!"); @@ -42,21 +42,21 @@ Flight::route('/', function() { ### JSON -Flight bietet Unterstützung für das Senden von JSON- und JSONP-Responses. Um eine JSON-Response zu senden, übergeben Sie einige Daten, die JSON-kodiert werden sollen: +Flight bietet Unterstützung für das Senden von JSON- und JSONP-Responses. Um eine JSON-Response zu senden, geben Sie einige Daten weiter, die JSON-kodiert werden sollen: ```php Flight::route('/@companyId/users', function(int $companyId) { - // irgendwie Ihre Benutzer aus einer Datenbank ziehen, z. B. + // holen Sie irgendwie Ihre Benutzer aus einer Datenbank, z.B. $users = Flight::db()->fetchAll("SELECT id, first_name, last_name FROM users WHERE company_id = ?", [ $companyId ]); Flight::json($users); }); -// [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* more users */ ] +// [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* mehr Benutzer */ ] ``` -> **Note:** Standardmäßig sendet Flight einen `Content-Type: application/json`-Header mit der Response. Es verwendet auch die Flags `JSON_THROW_ON_ERROR` und `JSON_UNESCAPED_SLASHES`, wenn das JSON kodiert wird. +> **Hinweis:** Standardmäßig sendet Flight einen `Content-Type: application/json`-Header mit der Response. Es verwendet auch die Flags `JSON_THROW_ON_ERROR` und `JSON_UNESCAPED_SLASHES` beim Kodieren des JSON. -#### JSON with Status Code +#### JSON mit Statuscode Sie können auch einen Statuscode als zweiten Argument übergeben: @@ -64,17 +64,17 @@ Sie können auch einen Statuscode als zweiten Argument übergeben: Flight::json(['id' => 123], 201); ``` -#### JSON with Pretty Print +#### JSON mit Pretty Print -Sie können auch ein Argument an der letzten Position übergeben, um Pretty Printing zu aktivieren: +Sie können auch ein Argument an die letzte Position übergeben, um Pretty Printing zu aktivieren: ```php Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT); ``` -#### Changing JSON Argument Order +#### Ändern der JSON-Argument-Reihenfolge -`Flight::json()` ist eine sehr alte Methode, aber das Ziel von Flight ist es, die Abwärtskompatibilität für Projekte aufrechtzuerhalten. Es ist eigentlich sehr einfach, wenn Sie die Reihenfolge der Argumente neu definieren möchten, um eine einfachere Syntax zu verwenden, können Sie die JSON-Methode einfach wie jede andere Flight-Methode [neu zuordnen](/learn/extending): +`Flight::json()` ist eine sehr veraltete Methode, aber das Ziel von Flight ist es, die Abwärtskompatibilität für Projekte aufrechtzuerhalten. Es ist eigentlich sehr einfach, wenn Sie die Reihenfolge der Argumente neu gestalten möchten, um eine einfachere Syntax zu verwenden, können Sie die JSON-Methode einfach neu zuordnen [wie jede andere Flight-Methode](/learn/extending): ```php Flight::map('json', function($data, $code = 200, $options = 0) { @@ -87,7 +87,7 @@ Flight::map('json', function($data, $code = 200, $options = 0) { Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT); ``` -#### JSON and Stopping Execution +#### JSON und Stoppen der Ausführung _v3.10.0_ @@ -120,7 +120,7 @@ Flight::route('/users', function() { }); ``` -### Clearing a Response Body +### Löschen eines Response-Bodys Wenn Sie den Response-Body löschen möchten, können Sie die `clearBody`-Methode verwenden: @@ -134,9 +134,9 @@ Flight::route('/', function() { }); ``` -Der obige Anwendungsfall ist wahrscheinlich nicht üblich, könnte jedoch häufiger vorkommen, wenn dies in einem [Middleware](/learn/middleware) verwendet wird. +Der obige Anwendungsfall ist wahrscheinlich nicht üblich, könnte aber häufiger vorkommen, wenn dies in einem [Middleware](/learn/middleware) verwendet wird. -### Running a Callback on the Response Body +### Ausführen eines Callbacks auf dem Response-Body Sie können einen Callback auf dem Response-Body ausführen, indem Sie die `addResponseBodyCallback`-Methode verwenden: @@ -153,11 +153,11 @@ Flight::response()->addResponseBodyCallback(function($body) { }); ``` -Sie können mehrere Callbacks hinzufügen, und sie werden in der Reihenfolge ausgeführt, in der sie hinzugefügt wurden. Da dies jede [callable](https://www.php.net/manual/en/language.types.callable.php) akzeptieren kann, kann es ein Klass-Array `[ $class, 'method' ]`, eine Closure `$strReplace = function($body) { str_replace('hi', 'there', $body); };` oder einen Funktionsnamen `'minify'` akzeptieren, wenn Sie z. B. eine Funktion haben, um Ihren HTML-Code zu minimieren. +Sie können mehrere Callbacks hinzufügen, und sie werden in der Reihenfolge ausgeführt, in der sie hinzugefügt wurden. Da dies jede [callable](https://www.php.net/manual/en/language.types.callable.php) akzeptieren kann, kann es ein Klassen-Array `[ $class, 'method' ]`, eine Closure `$strReplace = function($body) { str_replace('hi', 'there', $body); };` oder einen Funktionsnamen `'minify'` akzeptieren, wenn Sie z.B. eine Funktion haben, um Ihren HTML-Code zu minimieren. -**Note:** Route-Callbacks funktionieren nicht, wenn Sie die Konfigurationsoption `flight.v2.output_buffering` verwenden. +**Hinweis:** Route-Callbacks funktionieren nicht, wenn Sie die Konfigurationsoption `flight.v2.output_buffering` verwenden. -#### Specific Route Callback +#### Spezifischer Route-Callback Wenn Sie möchten, dass dies nur auf eine spezifische Route angewendet wird, können Sie den Callback direkt in der Route hinzufügen: @@ -174,7 +174,7 @@ Flight::route('/users', function() { }); ``` -#### Middleware Option +#### Middleware-Option Sie können auch [Middleware](/learn/middleware) verwenden, um den Callback auf alle Routes über Middleware anzuwenden: @@ -182,14 +182,14 @@ Sie können auch [Middleware](/learn/middleware) verwenden, um den Callback auf // MinifyMiddleware.php class MinifyMiddleware { public function before() { - // Den Callback hier auf dem response()-Objekt anwenden. + // Wenden Sie den Callback hier auf das response()-Objekt an. Flight::response()->addResponseBodyCallback(function($body) { return $this->minify($body); }); } protected function minify(string $body): string { - // den Body irgendwie minimieren + // minimieren Sie den Body irgendwie return $body; } } @@ -201,7 +201,7 @@ Flight::group('/users', function() { }, [ new MinifyMiddleware() ]); ``` -### Status Codes +### Statuscodes Sie können den Statuscode der Response mit der `status`-Methode setzen: @@ -223,12 +223,12 @@ Wenn Sie den aktuellen Statuscode abrufen möchten, können Sie die `status`-Met Flight::response()->status(); // 200 ``` -### Setting a Response Header +### Setzen eines Response-Headers Sie können einen Header wie den Content-Type der Response mit der `header`-Methode setzen: ```php -// Dies wird "Hello, World!" als Plain Text an den Browser des Benutzers senden +// Dies sendet "Hello, World!" an den Browser des Benutzers als reinen Text Flight::route('/', function() { Flight::response()->header('Content-Type', 'text/plain'); // oder @@ -237,9 +237,9 @@ Flight::route('/', function() { }); ``` -### Redirect +### Weiterleitung -Sie können die aktuelle Anfrage mit der `redirect()`-Methode weiterleiten und eine neue URL übergeben: +Sie können die aktuelle Anfrage weiterleiten, indem Sie die `redirect()`-Methode verwenden und eine neue URL übergeben: ```php Flight::route('/login', function() { @@ -252,19 +252,19 @@ Flight::route('/login', function() { return; // dies ist notwendig, damit die Funktionalität unten nicht ausgeführt wird } - // den neuen Benutzer hinzufügen... + // fügen Sie den neuen Benutzer hinzu... Flight::db()->runQuery("INSERT INTO users ...."); Flight::redirect('/admin/dashboard'); }); ``` -> **Note:** Standardmäßig sendet Flight einen HTTP 303 ("See Other")-Statuscode. Sie können optional einen benutzerdefinierten Code setzen: +> **Hinweis:** Standardmäßig sendet Flight einen HTTP 303 ("See Other")-Statuscode. Sie können optional einen benutzerdefinierten Code setzen: ```php Flight::redirect('/new/location', 301); // permanent ``` -### Stopping Route Execution +### Stoppen der Route-Ausführung Sie können das Framework stoppen und sofort beenden, indem Sie die `halt`-Methode aufrufen: @@ -278,19 +278,19 @@ Sie können auch einen optionalen `HTTP`-Statuscode und eine Nachricht angeben: Flight::halt(200, 'Be right back...'); ``` -Das Aufrufen von `halt` verwirft jeglichen Response-Inhalt bis zu diesem Punkt und stoppt die gesamte Ausführung. Wenn Sie das Framework stoppen und die aktuelle Response ausgeben möchten, verwenden Sie die `stop`-Methode: +Das Aufrufen von `halt` verwirft alle Response-Inhalte bis zu diesem Punkt und stoppt die gesamte Ausführung. Wenn Sie das Framework stoppen und die aktuelle Response ausgeben möchten, verwenden Sie die `stop`-Methode: ```php Flight::stop($httpStatusCode = null); ``` -> **Note:** `Flight::stop()` hat einiges seltsames Verhalten, wie z. B. dass es die Response ausgibt, aber die Ausführung Ihres Skripts fortsetzt, was möglicherweise nicht das ist, was Sie wollen. Sie können `exit` oder `return` nach dem Aufruf von `Flight::stop()` verwenden, um weitere Ausführung zu verhindern, aber es wird allgemein empfohlen, `Flight::halt()` zu verwenden. +> **Hinweis:** `Flight::stop()` hat einiges seltsames Verhalten, wie z.B. dass es die Response ausgibt, aber die Ausführung Ihres Skripts fortsetzt, was möglicherweise nicht das ist, was Sie wollen. Sie können `exit` oder `return` nach dem Aufruf von `Flight::stop()` verwenden, um weitere Ausführung zu verhindern, aber es wird im Allgemeinen empfohlen, `Flight::halt()` zu verwenden. Dies speichert den Header-Schlüssel und -Wert im Response-Objekt. Am Ende des Request-Lebenszyklus wird es die Header aufbauen und eine Response senden. -## Advanced Usage +## Erweiterte Verwendung -### Sending a Header Immediately +### Sofortiges Senden eines Headers Es kann Fälle geben, in denen Sie etwas Benutzerdefiniertes mit dem Header tun müssen und den Header in genau dieser Code-Zeile senden müssen, an der Sie arbeiten. Wenn Sie eine [streamed route](/learn/routing) setzen, ist das, was Sie brauchen. Das ist durch `response()->setRealHeader()` erreichbar. @@ -319,17 +319,17 @@ my_func({"id":123}); Wenn Sie keinen Query-Parameter-Namen übergeben, wird standardmäßig `jsonp` verwendet. -> **Note:** Wenn Sie 2025 und später immer noch JSONP-Anfragen verwenden, springen Sie in den Chat und erzählen Sie uns warum! Wir lieben es, gute Kampf-/Horror-Geschichten zu hören! +> **Hinweis:** Wenn Sie 2025 und später immer noch JSONP-Anfragen verwenden, springen Sie in den Chat und erzählen Sie uns warum! Wir lieben es, gute Kampf-/Horror-Geschichten zu hören! -### Clearing Response Data +### Löschen von Response-Daten -Sie können den Response-Body und die Header mit der `clear()`-Methode löschen. Dies löscht alle dem Response zugewiesenen Header, löscht den Response-Body und setzt den Statuscode auf `200`. +Sie können den Response-Body und Header löschen, indem Sie die `clear()`-Methode verwenden. Dies löscht alle der Response zugewiesenen Header, löscht den Response-Body und setzt den Statuscode auf `200`. ```php Flight::response()->clear(); ``` -#### Clearing Response Body Only +#### Nur Response-Body löschen Wenn Sie nur den Response-Body löschen möchten, können Sie die `clearBody()`-Methode verwenden: @@ -338,11 +338,11 @@ Wenn Sie nur den Response-Body löschen möchten, können Sie die `clearBody()`- Flight::response()->clearBody(); ``` -### HTTP Caching +### HTTP-Caching -Flight bietet integrierte Unterstützung für HTTP-Level-Caching. Wenn die Caching-Bedingung erfüllt ist, wird Flight eine HTTP `304 Not Modified`-Response zurückgeben. Beim nächsten Mal, wenn der Client die gleiche Ressource anfordert, wird er aufgefordert, seine lokal gecachte Version zu verwenden. +Flight bietet integrierte Unterstützung für HTTP-Level-Caching. Wenn die Caching-Bedingung erfüllt ist, wird Flight eine HTTP `304 Not Modified`-Response zurückgeben. Beim nächsten Mal, wenn der Client dieselbe Ressource anfordert, wird er aufgefordert, seine lokal gecachte Version zu verwenden. -#### Route Level Caching +#### Route-Level-Caching Wenn Sie Ihre gesamte Response cachen möchten, können Sie die `cache()`-Methode verwenden und eine Cache-Zeit übergeben. @@ -363,7 +363,7 @@ Flight::route('/news', function () { ### Last-Modified -Sie können die `lastModified`-Methode verwenden und einen UNIX-Timestamp übergeben, um das Datum und die Zeit zu setzen, zu der eine Seite zuletzt geändert wurde. Der Client wird seinen Cache weiterhin verwenden, bis der Last-Modified-Wert geändert wird. +Sie können die `lastModified`-Methode verwenden und einen UNIX-Timestamp übergeben, um das Datum und die Zeit zu setzen, zu der eine Seite zuletzt geändert wurde. Der Client wird sein Cache weiterhin verwenden, bis der Last-Modified-Wert geändert wird. ```php Flight::route('/news', function () { @@ -385,7 +385,7 @@ Flight::route('/news', function () { Beachten Sie, dass das Aufrufen von entweder `lastModified` oder `etag` beide den Cache-Wert setzt und prüft. Wenn der Cache-Wert zwischen den Anfragen gleich ist, wird Flight sofort eine `HTTP 304`-Response senden und die Verarbeitung stoppen. -### Download a File +### Herunterladen einer Datei _v3.12.0_ @@ -394,21 +394,24 @@ Es gibt eine Hilfsmethode, um eine Datei an den Endbenutzer zu streamen. Sie kö ```php Flight::route('/download', function () { Flight::download('/path/to/file.txt'); + // Ab v3.17.1 können Sie einen benutzerdefinierten Dateinamen für das Download angeben + Flight::download('/path/to/file.txt', 'custom_name.txt'); }); ``` -## See Also -- [Routing](/learn/routing) - Wie man Routes zu Controllern zuweist und Views rendert. +## Siehe auch +- [Routing](/learn/routing) - Wie man Routes auf Controller abbildet und Views rendert. - [Requests](/learn/requests) - Verständnis, wie man eingehende Anfragen handhabt. - [Middleware](/learn/middleware) - Verwendung von Middleware mit Routes für Authentifizierung, Logging usw. -- [Why a Framework?](/learn/why-frameworks) - Verständnis der Vorteile der Verwendung eines Frameworks wie Flight. -- [Extending](/learn/extending) - Wie man Flight mit eigener Funktionalität erweitert. +- [Warum ein Framework?](/learn/why-frameworks) - Verständnis der Vorteile der Verwendung eines Frameworks wie Flight. +- [Erweitern](/learn/extending) - Wie man Flight mit eigener Funktionalität erweitert. -## Troubleshooting -- Wenn Sie Probleme mit nicht funktionierenden Redirects haben, stellen Sie sicher, dass Sie ein `return;` zur Methode hinzufügen. +## Fehlerbehebung +- Wenn Sie Probleme mit nicht funktionierenden Weiterleitungen haben, stellen Sie sicher, dass Sie ein `return;` zur Methode hinzufügen. - `stop()` und `halt()` sind nicht dasselbe. `halt()` stoppt die Ausführung sofort, während `stop()` die Ausführung fortsetzt. ## Changelog -- v3.12.0 - Added downloadFile helper method. -- v3.10.0 - Added `jsonHalt`. -- v1.0 - Initial release. \ No newline at end of file +- v3.17.1 - `$fileName` zu `downloadFile()`-Methode hinzugefügt. +- v3.12.0 - `downloadFile`-Hilfsmethode hinzugefügt. +- v3.10.0 - `jsonHalt` hinzugefügt. +- v1.0 - Erste Veröffentlichung. \ No newline at end of file diff --git a/content/v3/de/learn/routing.md b/content/v3/de/learn/routing.md index 0f25594b..05ee8b69 100644 --- a/content/v3/de/learn/routing.md +++ b/content/v3/de/learn/routing.md @@ -1,12 +1,12 @@ # Routing ## Überblick -Routing in Flight PHP ordnet URL-Muster Callback-Funktionen oder Klassenmethoden zu, um schnelle und einfache Anfragenverarbeitung zu ermöglichen. Es ist für minimalen Overhead, benutzerfreundliche Nutzung für Anfänger und Erweiterbarkeit ohne externe Abhängigkeiten konzipiert. +Routing in Flight PHP ordnet URL-Muster Callback-Funktionen oder Klassenmethoden zu, um eine schnelle und einfache Anforderungsbehandlung zu ermöglichen. Es ist für minimale Overhead, benutzerfreundliche Nutzung für Anfänger und Erweiterbarkeit ohne externe Abhängigkeiten konzipiert. ## Verständnis -Routing ist der Kernmechanismus, der HTTP-Anfragen mit der Anwendungslogik in Flight verbindet. Durch das Definieren von Routen legen Sie fest, wie verschiedene URLs spezifischen Code auslösen, sei es durch Funktionen, Klassenmethoden oder Controller-Aktionen. Das Routing-System von Flight ist flexibel und unterstützt grundlegende Muster, benannte Parameter, reguläre Ausdrücke sowie erweiterte Funktionen wie Dependency Injection und ressourcenorientiertes Routing. Dieser Ansatz hält Ihren Code organisiert und einfach zu warten, während er für Anfänger schnell und einfach bleibt und für fortgeschrittene Nutzer erweiterbar ist. +Routing ist der Kernmechanismus, der HTTP-Anfragen mit Ihrer Anwendungslogik in Flight verbindet. Durch das Definieren von Routen legen Sie fest, wie verschiedene URLs spezifischen Code auslösen, sei es durch Funktionen, Klassenmethoden oder Controller-Aktionen. Das Routing-System von Flight ist flexibel und unterstützt grundlegende Muster, benannte Parameter, reguläre Ausdrücke sowie erweiterte Funktionen wie Dependency Injection und Resourceful Routing. Dieser Ansatz hält Ihren Code organisiert und einfach zu warten, während er für Anfänger schnell und einfach bleibt und für fortgeschrittene Nutzer erweiterbar ist. -> **Hinweis:** Möchten Sie mehr über Routing erfahren? Schauen Sie sich die Seite ["why a framework?"](/learn/why-frameworks) für eine detailliertere Erklärung an. +> **Hinweis:** Möchten Sie mehr über Routing erfahren? Schauen Sie sich die Seite ["why a framework?](/learn/why-frameworks) für eine detailliertere Erklärung an. ## Grundlegende Nutzung @@ -19,7 +19,7 @@ Flight::route('/', function(){ }); ``` -> Routen werden in der Reihenfolge abgeglichen, in der sie definiert werden. Die erste Route, die zu einer Anfrage passt, wird aufgerufen. +> Routen werden in der Reihenfolge abgeglichen, in der sie definiert sind. Die erste Route, die einer Anfrage entspricht, wird aufgerufen. ### Verwendung von Funktionen als Callbacks Der Callback kann jedes aufrufbare Objekt sein. Sie können also eine reguläre Funktion verwenden: @@ -43,11 +43,11 @@ class GreetingController { } Flight::route('/', [ 'GreetingController','hello' ]); -// oder -Flight::route('/', [ GreetingController::class, 'hello' ]); // bevorzugte Methode -// oder +// or +Flight::route('/', [ GreetingController::class, 'hello' ]); // preferred method +// or Flight::route('/', [ 'GreetingController::hello' ]); -// oder +// or Flight::route('/', [ 'GreetingController->hello' ]); ``` @@ -77,11 +77,11 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **Hinweis:** Standardmäßig wird beim Aufruf eines Controllers im Framework die Klasse `flight\Engine` immer injiziert, es sei denn, Sie spezifizieren es über einen [Dependency Injection Container](/learn/dependency-injection-container). +> **Hinweis:** Standardmäßig wird bei Aufruf eines Controllers im Framework die Klasse `flight\Engine` immer injiziert, es sei denn, Sie spezifizieren es über einen [Dependency Injection Container](/learn/dependency-injection-container) ### Methode-spezifisches Routing -Standardmäßig werden Routenmuster gegen alle Anfragemethoden abgeglichen. Sie können auf spezifische Methoden reagieren, indem Sie einen Bezeichner vor die URL setzen. +Standardmäßig werden Routenmuster gegen alle Anfragemethoden abgeglichen. Sie können auf spezifische Methoden reagieren, indem Sie einen Identifier vor die URL setzen. ```php Flight::route('GET /', function () { @@ -100,7 +100,7 @@ Flight::put('/', function() { /* code */ }); Flight::delete('/', function() { /* code */ }); ``` -Sie können auch mehrere Methoden auf einen einzelnen Callback abbilden, indem Sie den `|`-Trenner verwenden: +Sie können auch mehrere Methoden auf einen einzelnen Callback abbilden, indem Sie den `|`-Trennzeichen verwenden: ```php Flight::route('GET|POST /', function () { @@ -108,6 +108,38 @@ Flight::route('GET|POST /', function () { }); ``` +### Spezielle Behandlung für HEAD- und OPTIONS-Anfragen + +Flight bietet integrierte Behandlung für `HEAD`- und `OPTIONS`-HTTP-Anfragen: + +#### HEAD-Anfragen + +- **HEAD-Anfragen** werden genau wie `GET`-Anfragen behandelt, aber Flight entfernt automatisch den Response-Body, bevor er an den Client gesendet wird. +- Das bedeutet, Sie können eine Route für `GET` definieren, und HEAD-Anfragen zur gleichen URL geben nur Header zurück (keinen Inhalt), wie es die HTTP-Standards erwarten. + +```php +Flight::route('GET /info', function() { + echo 'This is some info!'; +}); +// A HEAD request to /info will return the same headers, but no body. +``` + +#### OPTIONS-Anfragen + +`OPTIONS`-Anfragen werden von Flight automatisch für jede definierte Route behandelt. +- Wenn eine OPTIONS-Anfrage empfangen wird, antwortet Flight mit einem `204 No Content`-Status und einem `Allow`-Header, der alle unterstützten HTTP-Methoden für diese Route auflistet. +- Sie müssen keine separate Route für OPTIONS definieren, es sei denn, Sie möchten benutzerdefiniertes Verhalten oder die Response modifizieren. + +```php +// For a route defined as: +Flight::route('GET|POST /users', function() { /* ... */ }); + +// An OPTIONS request to /users will respond with: +// +// Status: 204 No Content +// Allow: GET, POST, HEAD, OPTIONS +``` + ### Verwendung des Router-Objekts Zusätzlich können Sie das Router-Objekt abrufen, das einige Hilfsmethoden für Sie bietet: @@ -151,7 +183,7 @@ Flight::route('/@name/@id', function (string $name, string $id) { }); ``` -Sie können auch reguläre Ausdrücke mit Ihren benannten Parametern kombinieren, indem Sie den `:`-Trenner verwenden: +Sie können auch reguläre Ausdrücke mit Ihren benannten Parametern kombinieren, indem Sie den `:`-Trennzeichen verwenden: ```php Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { @@ -160,11 +192,11 @@ Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { }); ``` -> **Hinweis:** Das Abgleichen von Regex-Gruppen `()` mit positionsbasierten Parametern wird nicht unterstützt. Beispiel: `:'\(` +> **Hinweis:** Das Abgleichen von Regex-Gruppen `()` mit positionalen Parametern wird nicht unterstützt. Ex: `:'\(` #### Wichtige Einschränkung -Im obigen Beispiel scheint es, als ob `@name` direkt mit der Variable `$name` verknüpft ist, aber das ist nicht der Fall. Die Reihenfolge der Parameter in der Callback-Funktion bestimmt, was an sie weitergegeben wird. Wenn Sie die Reihenfolge der Parameter in der Callback-Funktion umkehren, werden auch die Variablen umgekehrt. Hier ein Beispiel: +Während im obigen Beispiel erscheint, als ob `@name` direkt mit der Variable `$name` verknüpft ist, ist das nicht der Fall. Die Reihenfolge der Parameter in der Callback-Funktion bestimmt, was an sie weitergegeben wird. Wenn Sie die Reihenfolge der Parameter in der Callback-Funktion umkehren würden, würden die Variablen ebenfalls umgekehrt. Hier ein Beispiel: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -173,7 +205,7 @@ Flight::route('/@name/@id', function (string $id, string $name) { ``` Und wenn Sie zur folgenden URL gehen: `/bob/123`, wäre die Ausgabe `hello, 123 (bob)!`. -_Seien Sie bitte vorsichtig_, wenn Sie Ihre Routen und Callback-Funktionen einrichten! +_Bitte seien Sie vorsichtig_, wenn Sie Ihre Routen und Callback-Funktionen einrichten! ### Optionale Parameter Sie können benannte Parameter spezifizieren, die optional für das Abgleichen sind, indem Sie Segmente in Klammern setzen. @@ -191,10 +223,10 @@ Flight::route( ); ``` -Jede optionale Parameter, die nicht abgeglichen werden, wird als `NULL` weitergegeben. +Jede optionale Parameter, die nicht abgeglichen wird, wird als `NULL` weitergegeben. ### Wildcard-Routing -Das Abgleichen erfolgt nur auf einzelnen URL-Segmenten. Wenn Sie mehrere Segmente abgleichen möchten, können Sie das `*`-Wildcard verwenden. +Das Abgleichen erfolgt nur auf einzelne URL-Segmente. Wenn Sie mehrere Segmente abgleichen möchten, können Sie das `*`-Wildcard verwenden. ```php Flight::route('/blog/*', function () { @@ -202,7 +234,7 @@ Flight::route('/blog/*', function () { }); ``` -Um alle Anfragen an einen einzelnen Callback zu leiten, können Sie tun: +Um alle Anfragen an einen einzelnen Callback zu routen, können Sie tun: ```php Flight::route('*', function () { @@ -212,8 +244,8 @@ Flight::route('*', function () { ### 404 Not Found Handler -Standardmäßig sendet Flight bei einer nicht gefundenen URL eine sehr einfache und schlichte `HTTP 404 Not Found`-Antwort. -Wenn Sie eine personalisiertere 404-Antwort haben möchten, können Sie Ihre eigene `notFound`-Methode [abbilden](/learn/extending): +Standardmäßig sendet Flight bei einer nicht gefundenen URL eine sehr einfache und schlichte `HTTP 404 Not Found`-Response. +Wenn Sie eine personalisiertere 404-Response haben möchten, können Sie Ihre eigene `notFound`-Methode [mappen](/learn/extending): ```php Flight::map('notFound', function() { @@ -233,10 +265,39 @@ Flight::map('notFound', function() { }); ``` +### Method Not Found Handler + +Standardmäßig sendet Flight bei einer gefundenen URL, aber nicht erlaubten Methode eine sehr einfache und schlichte `HTTP 405 Method Not Allowed`-Response (Ex: Method Not Allowed. Allowed Methods are: GET, POST). Es wird auch ein `Allow`-Header mit den erlaubten Methoden für diese URL enthalten. + +Wenn Sie eine personalisiertere 405-Response haben möchten, können Sie Ihre eigene `methodNotFound`-Methode [mappen](/learn/extending): + +```php +use flight\net\Route; + +Flight::map('methodNotFound', function(Route $route) { + $url = Flight::request()->url; + $methods = implode(', ', $route->methods); + + // You could also use Flight::render() with a custom template. + $output = <<My Custom 405 Method Not Allowed +

The method you have requested for {$url} is not allowed.

+

Allowed Methods are: {$methods}

+ HTML; + + $this->response() + ->clearBody() + ->status(405) + ->setHeader('Allow', $methods) + ->write($output) + ->send(); +}); +``` + ## Erweiterte Nutzung ### Dependency Injection in Routen -Wenn Sie Dependency Injection über einen Container (PSR-11, PHP-DI, Dice usw.) verwenden möchten, ist der einzige Routentyp, bei dem das verfügbar ist, entweder das direkte Erstellen des Objekts selbst und die Verwendung des Containers, um Ihr Objekt zu erstellen, oder Sie können Strings verwenden, um die Klasse und Methode zum Aufrufen zu definieren. Sie können zur [Dependency Injection](/learn/dependency-injection-container)-Seite für weitere Informationen gehen. +Wenn Sie Dependency Injection über einen Container (PSR-11, PHP-DI, Dice usw.) verwenden möchten, ist der einzige Routentyp, bei dem das verfügbar ist, entweder das direkte Erstellen des Objekts selbst und die Verwendung des Containers, um Ihr Objekt zu erstellen, oder Sie können Strings verwenden, um die Klasse und Methode zu definieren, die aufgerufen werden soll. Sie können zur [Dependency Injection](/learn/dependency-injection-container)-Seite für weitere Informationen gehen. Hier ein kurzes Beispiel: @@ -290,7 +351,7 @@ Flight::route('/hello/@id', 'Greeting::hello'); Flight::start(); ``` -### Übergabe der Ausführung an die nächste Route +### Ausführung an nächste Route weitergeben Veraltet Sie können die Ausführung an die nächste passende Route weitergeben, indem Sie `true` aus Ihrer Callback-Funktion zurückgeben. @@ -333,7 +394,7 @@ class UserController { ``` Dies ist besonders hilfreich, wenn sich Ihre URL ändert. Im obigen Beispiel, sagen wir, dass Benutzer zu `/admin/users/@id` verschoben wurden. -Mit Aliasing an Ort und Stelle müssen Sie nicht mehr alle alten URLs in Ihrem Code finden und ändern, da der Alias nun `/admin/users/5` zurückgibt, wie im obigen Beispiel. +Mit Aliasing an Ort und Stelle müssen Sie nicht mehr alle alten URLs in Ihrem Code finden und ändern, da der Alias nun `/admin/users/5` wie im obigen Beispiel zurückgibt. Route-Aliasing funktioniert auch in Gruppen: @@ -345,11 +406,11 @@ Flight::group('/users', function() { }); ``` -### Überprüfen von Routeninformationen -Wenn Sie die passende Routeninformation überprüfen möchten, gibt es 2 Wege, dies zu tun: +### Inspektion von Routeninformationen +Wenn Sie die passende Routeninformation inspizieren möchten, gibt es 2 Wege, das zu tun: 1. Sie können die `executedRoute`-Eigenschaft auf dem `Flight::router()`-Objekt verwenden. -2. Sie können das Routenobjekt anfordern, das an Ihren Callback übergeben wird, indem Sie `true` als dritten Parameter in der Routenmethode übergeben. Das Routenobjekt wird immer der letzte Parameter sein, der an Ihre Callback-Funktion übergeben wird. +2. Sie können das Routenobjekt anfordern, das an Ihren Callback weitergegeben wird, indem Sie `true` als dritten Parameter in der Routenmethode übergeben. Das Routenobjekt wird immer der letzte Parameter sein, der an Ihre Callback-Funktion weitergegeben wird. #### `executedRoute` ```php @@ -379,9 +440,9 @@ Flight::route('/', function() { }); ``` -> **Hinweis:** Die `executedRoute`-Eigenschaft wird nur gesetzt, nachdem eine Route ausgeführt wurde. Wenn Sie versuchen, sie vor der Ausführung einer Route abzurufen, ist sie `NULL`. Sie können executedRoute auch in [Middleware](/learn/middleware) verwenden! +> **Hinweis:** Die `executedRoute`-Eigenschaft wird nur nach der Ausführung einer Route gesetzt. Wenn Sie sie vor der Ausführung einer Route abrufen, ist sie `NULL`. Sie können executedRoute auch in [Middleware](/learn/middleware) verwenden! -#### `true` in der Routendefinition übergeben +#### `true` in Routendefinition übergeben ```php Flight::route('/', function(\flight\net\Route $route) { // Array of HTTP methods matched against @@ -404,12 +465,12 @@ Flight::route('/', function(\flight\net\Route $route) { // Shows the alias assigned to this route $route->alias; -}, true);// <-- Dieser true-Parameter ist das, was das bewirkt +}, true);// <-- This true parameter is what makes that happen ``` ### Routengruppierung und Middleware -Es kann vorkommen, dass Sie verwandte Routen gruppieren möchten (z. B. `/api/v1`). -Sie können dies tun, indem Sie die `group`-Methode verwenden: +Es kann Fälle geben, in denen Sie verwandte Routen gruppieren möchten (z. B. `/api/v1`). +Sie können das tun, indem Sie die `group`-Methode verwenden: ```php Flight::group('/api/v1', function () { @@ -453,7 +514,7 @@ Flight::group('/api', function () { #### Gruppierung mit Objektkontext -Sie können die Routengruppierung immer noch mit dem `Engine`-Objekt auf folgende Weise verwenden: +Sie können Routengruppierung immer noch mit dem `Engine`-Objekt auf folgende Weise verwenden: ```php $app = Flight::app(); @@ -485,18 +546,18 @@ Flight::group('/api/v1', function () { }, [ MyAuthMiddleware::class ]); // or [ new MyAuthMiddleware() ] if you want to use an instance ``` -Weitere Details finden Sie auf der [Group Middleware](/learn/middleware#grouping-middleware)-Seite. +Weitere Details finden Sie auf der [Gruppen-Middleware](/learn/middleware#grouping-middleware)-Seite. -### Ressourcen-Routing -Sie können eine Reihe von Routen für eine Ressource mit der `resource`-Methode erstellen. Dies erstellt eine Reihe von Routen für eine Ressource, die den RESTful-Konventionen folgt. +### Resource Routing +Sie können eine Reihe von Routen für eine Resource mit der `resource`-Methode erstellen. Dies erstellt eine Reihe von Routen für eine Resource, die den RESTful-Konventionen folgt. -Um eine Ressource zu erstellen, tun Sie Folgendes: +Um eine Resource zu erstellen, tun Sie Folgendes: ```php Flight::resource('/users', UsersController::class); ``` -Und im Hintergrund werden die folgenden Routen erstellt: +Und was im Hintergrund passiert, ist, dass es die folgenden Routen erstellt: ```php [ @@ -547,15 +608,15 @@ class UsersController > **Hinweis**: Sie können die neu hinzugefügten Routen mit `runway` anzeigen, indem Sie `php runway routes` ausführen. -#### Anpassen von Ressourcen-Routen +#### Anpassen von Resource-Routen -Es gibt einige Optionen, um die Ressourcen-Routen zu konfigurieren. +Es gibt einige Optionen, um die Resource-Routen zu konfigurieren. ##### Alias-Basis Sie können die `aliasBase` konfigurieren. Standardmäßig ist der Alias der letzte Teil der angegebenen URL. Zum Beispiel würde `/users/` zu einem `aliasBase` von `users` führen. Wenn diese Routen erstellt werden, -sind die Aliase `users.index`, `users.create` usw. Wenn Sie den Alias ändern möchten, setzen Sie `aliasBase` +sind die Aliase `users.index`, `users.create` usw. Wenn Sie den Alias ändern möchten, setzen Sie die `aliasBase` auf den gewünschten Wert. ```php @@ -564,7 +625,7 @@ Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); ##### Only und Except -Sie können auch spezifizieren, welche Routen Sie erstellen möchten, indem Sie die Optionen `only` und `except` verwenden. +Sie können auch spezifizieren, welche Routen Sie erstellen möchten, indem Sie die `only`- und `except`-Optionen verwenden. ```php // Whitelist only these methods and blacklist the rest @@ -576,28 +637,28 @@ Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` -Dies sind im Wesentlichen Whitelist- und Blacklist-Optionen, damit Sie spezifizieren können, welche Routen Sie erstellen möchten. +Diese sind im Wesentlichen Whitelisting- und Blacklisting-Optionen, damit Sie spezifizieren können, welche Routen Sie erstellen möchten. ##### Middleware -Sie können auch Middleware spezifizieren, die auf jeder der Routen ausgeführt wird, die von der `resource`-Methode erstellt werden. +Sie können auch Middleware spezifizieren, die für jede der von der `resource`-Methode erstellten Routen ausgeführt wird. ```php Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]); ``` -### Streaming-Antworten +### Streaming-Responses -Sie können jetzt Antworten an den Client streamen, indem Sie `stream()` oder `streamWithHeaders()` verwenden. -Dies ist nützlich zum Senden großer Dateien, lang laufender Prozesse oder zum Generieren großer Antworten. +Sie können nun Responses an den Client streamen, indem Sie `stream()` oder `streamWithHeaders()` verwenden. +Dies ist nützlich für das Senden großer Dateien, lang laufender Prozesse oder das Generieren großer Responses. Das Streamen einer Route wird etwas anders gehandhabt als eine reguläre Route. -> **Hinweis:** Streaming-Antworten sind nur verfügbar, wenn Sie [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) auf `false` gesetzt haben. +> **Hinweis:** Streaming-Responses sind nur verfügbar, wenn Sie [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) auf `false` gesetzt haben. -#### Stream mit manuellen Headers +#### Stream mit manuellen Headern -Sie können eine Antwort an den Client streamen, indem Sie die `stream()`-Methode auf einer Route verwenden. Wenn Sie -das tun, müssen Sie alle Headers manuell setzen, bevor Sie etwas an den Client ausgeben. +Sie können eine Response an den Client streamen, indem Sie die `stream()`-Methode auf einer Route verwenden. Wenn Sie +das tun, müssen Sie alle Header manuell setzen, bevor Sie etwas an den Client ausgeben. Dies geschieht mit der `header()`-PHP-Funktion oder der `Flight::response()->setRealHeader()`-Methode. ```php @@ -634,9 +695,9 @@ Flight::route('/@filename', function($filename) { })->stream(); ``` -#### Stream mit Headers +#### Stream mit Headern -Sie können auch die `streamWithHeaders()`-Methode verwenden, um die Headers zu setzen, bevor Sie mit dem Streamen beginnen. +Sie können auch die `streamWithHeaders()`-Methode verwenden, um die Header zu setzen, bevor Sie mit dem Streamen beginnen. ```php Flight::route('/stream-users', function() { @@ -674,10 +735,10 @@ Flight::route('/stream-users', function() { - [Dependency Injection](/learn/dependency-injection-container) - Vereinfachung der Objekterstellung und -verwaltung in Routen. - [Why a Framework?](/learn/why-frameworks) - Verständnis der Vorteile der Verwendung eines Frameworks wie Flight. - [Erweitern](/learn/extending) - Wie man Flight mit eigener Funktionalität erweitert, einschließlich der `notFound`-Methode. -- [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - PHP-Funktion für reguläre Ausdrucksabgleichung. +- [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - PHP-Funktion für reguläres Ausdrucksabgleichen. ## Fehlerbehebung -- Routenparameter werden nach Reihenfolge abgeglichen, nicht nach Name. Stellen Sie sicher, dass die Reihenfolge der Callback-Parameter zur Routendefinition passt. +- Routenparameter werden nach Reihenfolge abgeglichen, nicht nach Name. Stellen Sie sicher, dass die Parameterreihenfolge des Callbacks mit der Routendefinition übereinstimmt. - Die Verwendung von `Flight::get()` definiert keine Route; verwenden Sie `Flight::route('GET /...')` für Routing oder den Router-Objektkontext in Gruppen (z. B. `$router->get(...)`). - Die executedRoute-Eigenschaft wird nur nach der Ausführung einer Route gesetzt; sie ist NULL vor der Ausführung. - Streaming erfordert, dass die Legacy-Flight-Output-Buffering-Funktionalität deaktiviert ist (`flight.v2.output_buffering = false`). @@ -685,11 +746,10 @@ Flight::route('/stream-users', function() { ### 404 Not Found oder unerwartetes Routenverhalten -Wenn Sie einen 404 Not Found-Fehler sehen (aber Sie schwören bei Ihrem Leben, dass er wirklich da ist und es kein Tippfehler ist), könnte dies tatsächlich ein Problem damit sein, -dass Sie einen Wert aus Ihrem Routen-Endpunkt zurückgeben, anstatt ihn nur auszugeben. Der Grund dafür ist absichtlich, könnte aber einige Entwickler überraschen. +Wenn Sie einen 404 Not Found-Fehler sehen (aber Sie schwören bei Ihrem Leben, dass er wirklich da ist und es kein Tippfehler ist), könnte das tatsächlich ein Problem damit sein, +dass Sie einen Wert in Ihrem Routenendpunkt zurückgeben, anstatt ihn nur auszugeben. Der Grund dafür ist absichtlich, könnte aber einige Entwickler überraschen. ```php - Flight::route('/hello', function(){ // This might cause a 404 Not Found error return 'Hello World'; @@ -699,12 +759,11 @@ Flight::route('/hello', function(){ Flight::route('/hello', function(){ echo 'Hello World'; }); - ``` -Der Grund dafür ist ein spezieller Mechanismus, der in den Router eingebaut ist und die Rückgabeausgabe als Signal behandelt, um "zur nächsten Route zu gehen". -Sie können das Verhalten in dem [Routing](/learn/routing#passing)-Abschnitt dokumentiert finden. +Der Grund dafür ist ein spezieller Mechanismus, der in den Router integriert ist und die Rückgabe als Signal interpretiert, "zur nächsten Route zu gehen". +Sie können das Verhalten in dem [Routing](/learn/routing#passing)-Abschnitt dokumentiert sehen. -## Änderungsprotokoll -- v3: Hinzugefügt: Ressourcen-Routing, Route-Aliasing und Streaming-Unterstützung, Routengruppen und Middleware-Unterstützung. -- v1: Der Großteil der grundlegenden Funktionen ist verfügbar. \ No newline at end of file +## Changelog +- v3: Hinzugefügt Resource-Routing, Route-Aliasing und Streaming-Unterstützung, Routengruppen und Middleware-Unterstützung. +- v1: Überwiegende Mehrheit der grundlegenden Funktionen verfügbar. \ No newline at end of file diff --git a/content/v3/en/learn/requests.md b/content/v3/en/learn/requests.md index 3e8bad74..d035d5c9 100644 --- a/content/v3/en/learn/requests.md +++ b/content/v3/en/learn/requests.md @@ -198,9 +198,9 @@ The request object provides the following properties: - **host** - The request host name - **servername** - The SERVER_NAME from `$_SERVER` -## URL Helper Methods +## Helper Methods -There are a couple helper methods to piece together parts of a URL for your convenience. +There are a couple helper methods to piece together parts of a URL, or deal with certain headers. ### Full URL @@ -230,6 +230,29 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` +## Negotiate Content Accept Types + +_v3.17.2_ + +You can use the `negotiateContentType()` method to determine the best content type to respond with based on the `Accept` header sent by the client. + +```php + +// Example Accept header: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// The below defines what you support. +$availableTypes = ['application/json', 'application/xml']; +$typeToServe = Flight::request()->negotiateContentType($availableTypes); +if ($typeToServe === 'application/json') { + // Serve JSON response +} elseif ($typeToServe === 'application/xml') { + // Serve XML response +} else { + // Default to something else or throw an error +} +``` + +> **Note:** If none of the available types are found in the `Accept` header, the method will return `null`. If there is no `Accept` header defined, the method will return the first type in the `$availableTypes` array. + ## See Also - [Routing](/learn/routing) - See how to map routes to controllers and render views. - [Responses](/learn/responses) - How to customize HTTP responses. @@ -241,5 +264,6 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); - `request()->ip` and `request()->proxy_ip` can be different if your webserver is behind a proxy, load balancer, etc. ## Changelog +- v3.17.2 - Added negotiateContentType() - v3.12.0 - Added ability to handle file uploads through the request object. - v1.0 - Initial release. \ No newline at end of file diff --git a/content/v3/en/learn/responses.md b/content/v3/en/learn/responses.md index 147411d1..ce68f51c 100644 --- a/content/v3/en/learn/responses.md +++ b/content/v3/en/learn/responses.md @@ -419,6 +419,8 @@ There is a helper method to stream a file to the end user. You can use the `down ```php Flight::route('/download', function () { Flight::download('/path/to/file.txt'); + // As of v3.17.1 you can specify a custom filename for the download + Flight::download('/path/to/file.txt', 'custom_name.txt'); }); ``` @@ -434,6 +436,7 @@ Flight::route('/download', function () { - `stop()` and `halt()` are not the same thing. `halt()` will stop execution immediately, while `stop()` will allow execution to continue. ## Changelog +- v3.17.1 - Added `$fileName` to `downloadFile()` method. - v3.12.0 - Added downloadFile helper method. - v3.10.0 - Added `jsonHalt`. - v1.0 - Initial release. \ No newline at end of file diff --git a/content/v3/en/learn/routing.md b/content/v3/en/learn/routing.md index 41482e03..a6ad594a 100644 --- a/content/v3/en/learn/routing.md +++ b/content/v3/en/learn/routing.md @@ -1,4 +1,3 @@ - # Routing ## Overview @@ -110,6 +109,38 @@ Flight::route('GET|POST /', function () { }); ``` +### Special Handling for HEAD and OPTIONS Requests + +Flight provides built-in handling for `HEAD` and `OPTIONS` HTTP requests: + +#### HEAD Requests + +- **HEAD requests** are treated just like `GET` requests, but Flight automatically removes the response body before sending it to the client. +- This means you can define a route for `GET`, and HEAD requests to the same URL will return only headers (no content), as expected by HTTP standards. + +```php +Flight::route('GET /info', function() { + echo 'This is some info!'; +}); +// A HEAD request to /info will return the same headers, but no body. +``` + +#### OPTIONS Requests + +`OPTIONS` requests are automatically handled by Flight for any defined route. +- When an OPTIONS request is received, Flight responds with a `204 No Content` status and an `Allow` header listing all supported HTTP methods for that route. +- You do not need to define a separate route for OPTIONS unless you want custom behavior or to modify the response. + +```php +// For a route defined as: +Flight::route('GET|POST /users', function() { /* ... */ }); + +// An OPTIONS request to /users will respond with: +// +// Status: 204 No Content +// Allow: GET, POST, HEAD, OPTIONS +``` + ### Using the Router Object Additionally you can grab the Router object which has some helper methods for you to use: @@ -241,6 +272,35 @@ Flight::map('notFound', function() { }); ``` +### Method Not Found Handler + +By default, if a URL is found but the method is not allowed, Flight will send an `HTTP 405 Method Not Allowed` response that is very simple and plain (Ex: Method Not Allowed. Allowed Methods are: GET, POST). It will also include an `Allow` header with the allowed methods for that URL. + +If you want to have a more customized 405 response, you can [map](/learn/extending) your own `methodNotFound` method: + +```php +use flight\net\Route; + +Flight::map('methodNotFound', function(Route $route) { + $url = Flight::request()->url; + $methods = implode(', ', $route->methods); + + // You could also use Flight::render() with a custom template. + $output = <<My Custom 405 Method Not Allowed +

The method you have requested for {$url} is not allowed.

+

Allowed Methods are: {$methods}

+ HTML; + + $this->response() + ->clearBody() + ->status(405) + ->setHeader('Allow', $methods) + ->write($output) + ->send(); +}); +``` + ## Advanced Usage ### Dependency Injection in Routes @@ -703,7 +763,6 @@ If you are seeing a 404 Not Found error (but you swear on your life that it's re with you returning a value in your route endpoint instead of just echoing it. The reason for this is intentional but could sneak up on some developers. ```php - Flight::route('/hello', function(){ // This might cause a 404 Not Found error return 'Hello World'; @@ -713,7 +772,6 @@ Flight::route('/hello', function(){ Flight::route('/hello', function(){ echo 'Hello World'; }); - ``` The reason for this is because of a special mechanism built into the router that handles the return output as a single to "go to the next route". diff --git a/content/v3/es/awesome-plugins/apm.md b/content/v3/es/awesome-plugins/apm.md index 51d8bb4f..8da0326e 100644 --- a/content/v3/es/awesome-plugins/apm.md +++ b/content/v3/es/awesome-plugins/apm.md @@ -1,12 +1,14 @@ -# Documentación de FlightPHP APM +# Documentación de APM de FlightPHP -¡Bienvenido a FlightPHP APM, tu entrenador personal de rendimiento para aplicaciones! Esta guía es tu mapa para configurar, usar y dominar el Monitoreo de Rendimiento de Aplicaciones (APM) con FlightPHP. Ya sea que estés cazando solicitudes lentas o simplemente quieras emocionarte con gráficos de latencia, te tenemos cubierto. ¡Hagamos que tu aplicación sea más rápida, tus usuarios más felices y tus sesiones de depuración una brisa! +¡Bienvenido a FlightPHP APM—el entrenador personal de rendimiento de tu aplicación! Esta guía es tu mapa de ruta para configurar, usar y dominar el Monitoreo de Rendimiento de Aplicaciones (APM) con FlightPHP. Ya sea que estés cazando solicitudes lentas o solo quieras geekearte con gráficos de latencia, te tenemos cubierto. ¡Hagamos que tu app sea más rápida, tus usuarios más felices y tus sesiones de depuración una brisa! + +Mira una [demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) del dashboard para el sitio de Flight Docs. ![FlightPHP APM](/images/apm.png) -## Por qué importa el APM +## Por qué APM importa -Imagina esto: tu aplicación es un restaurante ajetreado. Sin una forma de rastrear cuánto tardan los pedidos o dónde se atasca la cocina, estás adivinando por qué los clientes se van molestos. El APM es tu sous-chef: observa cada paso, desde las solicitudes entrantes hasta las consultas de base de datos, y marca cualquier cosa que te esté ralentizando. ¡Las páginas lentas pierden usuarios (estudios dicen que el 53% rebota si un sitio tarda más de 3 segundos en cargar!) y el APM te ayuda a detectar esos problemas *antes* de que piquen. Es una paz mental proactiva: menos momentos de "¿por qué esto está roto?" y más victorias de "¡mira qué bien funciona esto!". +Imagina esto: tu app es un restaurante concurrido. Sin una forma de rastrear cuánto tiempo tardan los pedidos o dónde se atasca la cocina, estás adivinando por qué los clientes se van gruñendo. APM es tu sous-chef—vigila cada paso, desde las solicitudes entrantes hasta las consultas de base de datos, y marca cualquier cosa que te esté ralentizando. Las páginas lentas pierden usuarios (¡los estudios dicen que el 53% rebota si un sitio tarda más de 3 segundos en cargar!), y APM te ayuda a capturar esos problemas *antes* de que duelan. Es una paz de mente proactiva—menos momentos de “¿por qué esto está roto?”, más victorias de “¡mira qué fluido corre esto!”. ## Instalación @@ -17,55 +19,55 @@ composer require flightphp/apm ``` Necesitarás: -- **PHP 7.4+**: Mantiene la compatibilidad con distribuciones LTS de Linux mientras soporta PHP moderno. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: El framework ligero que estamos mejorando. +- **PHP 7.4+**: Nos mantiene compatibles con distribuciones Linux LTS mientras soporta PHP moderno. +- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: El framework ligero que estamos impulsando. ## Bases de datos compatibles FlightPHP APM actualmente soporta las siguientes bases de datos para almacenar métricas: -- **SQLite3**: Simple, basada en archivos y genial para desarrollo local o aplicaciones pequeñas. Opción predeterminada en la mayoría de las configuraciones. +- **SQLite3**: Simple, basada en archivos, y genial para desarrollo local o apps pequeñas. Opción predeterminada en la mayoría de las configuraciones. - **MySQL/MariaDB**: Ideal para proyectos más grandes o entornos de producción donde necesitas almacenamiento robusto y escalable. -Puedes elegir el tipo de base de datos durante el paso de configuración (véase a continuación). Asegúrate de que tu entorno PHP tenga las extensiones necesarias instaladas (por ejemplo, `pdo_sqlite` o `pdo_mysql`). +Puedes elegir el tipo de base de datos durante el paso de configuración (ver abajo). Asegúrate de que tu entorno PHP tenga las extensiones necesarias instaladas (p.ej., `pdo_sqlite` o `pdo_mysql`). -## Primeros pasos +## Comenzando -Aquí tienes tu guía paso a paso para el APM increíble: +Aquí tienes tu guía paso a paso hacia la genialidad de APM: -### 1. Registra el APM +### 1. Registrar el APM -Agrega esto en tu archivo `index.php` o `services.php` para comenzar a rastrear: +Coloca esto en tu `index.php` o un archivo `services.php` para comenzar el rastreo: ```php -use flight\apm\logger\LoggerFactory; // Obtiene tu configuración (más sobre eso pronto) y configura un registrador, SQLite por defecto +use flight\apm\logger\LoggerFactory; use flight\Apm; $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); $Apm = new Apm($ApmLogger); $Apm->bindEventsToFlightInstance($app); -// Si estás agregando una conexión a la base de datos -// Debe ser PdoWrapper o PdoQueryCapture de las Extensiones Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- Verdadero requerido para habilitar el rastreo en el APM. +// Si estás agregando una conexión de base de datos +// Debe ser PdoWrapper o PdoQueryCapture de Tracy Extensions +$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True requerido para habilitar el rastreo en el APM. $Apm->addPdoConnection($pdo); ``` **¿Qué está pasando aquí?** -- `LoggerFactory::create()` obtiene tu configuración (más sobre eso pronto) y configura un registrador, SQLite por defecto. -- `Apm` es la estrella: escucha los eventos de Flight (solicitudes, rutas, errores, etc.) y recopila métricas. -- `bindEventsToFlightInstance($app)` lo une todo a tu aplicación Flight. +- `LoggerFactory::create()` agarra tu configuración (más sobre eso pronto) y configura un logger—SQLite por defecto. +- `Apm` es la estrella—escucha los eventos de Flight (solicitudes, rutas, errores, etc.) y recolecta métricas. +- `bindEventsToFlightInstance($app)` lo une todo a tu app de Flight. -**Consejo Profesional: Muestreo** -Si tu aplicación está ocupada, registrar *cada* solicitud podría sobrecargar las cosas. Usa una tasa de muestreo (de 0.0 a 1.0): +**Consejo Pro: Muestreo** +Si tu app está ocupada, registrar *cada* solicitud podría sobrecargar las cosas. Usa una tasa de muestreo (0.0 a 1.0): ```php $Apm = new Apm($ApmLogger, 0.1); // Registra el 10% de las solicitudes ``` -Esto mantiene el rendimiento ágil mientras te da datos sólidos. +Esto mantiene el rendimiento ágil mientras aún te da datos sólidos. -### 2. Configúralo +### 2. Configurarlo Ejecuta esto para crear tu `.runway-config.json`: @@ -74,9 +76,9 @@ php vendor/bin/runway apm:init ``` **¿Qué hace esto?** -- Lanza un asistente que pregunta de dónde vienen las métricas crudas (fuente) y a dónde van los datos procesados (destino). -- Predeterminado es SQLite, por ejemplo, `sqlite:/tmp/apm_metrics.sqlite` para la fuente, y otro para el destino. -- Terminarás con una configuración como: +- Lanza un asistente que pregunta de dónde vienen las métricas crudas (fuente) y dónde va la data procesada (destino). +- Predeterminado es SQLite—p.ej., `sqlite:/tmp/apm_metrics.sqlite` para la fuente, otra para el destino. +- Terminarás con una config como: ```json { "apm": { @@ -88,39 +90,39 @@ php vendor/bin/runway apm:init } ``` -> Este proceso también preguntará si quieres ejecutar las migraciones para esta configuración. Si lo estás configurando por primera vez, la respuesta es sí. +> Este proceso también preguntará si quieres ejecutar las migraciones para esta configuración. Si estás configurándolo por primera vez, la respuesta es sí. **¿Por qué dos ubicaciones?** -Las métricas crudas se acumulan rápidamente (piensa en registros sin filtrar). El trabajador las procesa en un destino estructurado para el panel de control. ¡Mantiene las cosas ordenadas! +Las métricas crudas se acumulan rápido (piensa en logs sin filtrar). El worker las procesa en un destino estructurado para el dashboard. ¡Mantiene las cosas ordenadas! -### 3. Procesar métricas con el trabajador +### 3. Procesar métricas con el Worker -El trabajador convierte las métricas crudas en datos listos para el panel. Ejecuta esto una vez: +El worker convierte las métricas crudas en data lista para el dashboard. Ejecútalo una vez: ```bash php vendor/bin/runway apm:worker ``` **¿Qué está haciendo?** -- Lee de tu fuente (por ejemplo, `apm_metrics.sqlite`). +- Lee de tu fuente (p.ej., `apm_metrics.sqlite`). - Procesa hasta 100 métricas (tamaño de lote predeterminado) en tu destino. - Se detiene cuando termina o si no quedan métricas. -**Mantenerlo en ejecución** -Para aplicaciones en vivo, querrás un procesamiento continuo. Aquí tienes tus opciones: +**Mantenerlo ejecutándose** +Para apps en vivo, querrás procesamiento continuo. Aquí tienes tus opciones: - **Modo Daemon**: ```bash php vendor/bin/runway apm:worker --daemon ``` - Se ejecuta para siempre, procesando métricas a medida que llegan. Genial para desarrollo o configuraciones pequeñas. + Se ejecuta para siempre, procesando métricas a medida que llegan. Genial para dev o configuraciones pequeñas. - **Crontab**: Agrega esto a tu crontab (`crontab -e`): ```bash * * * * * php /path/to/project/vendor/bin/runway apm:worker ``` - Se ejecuta cada minuto: perfecto para producción. + Se dispara cada minuto—perfecto para producción. - **Tmux/Screen**: Inicia una sesión desmontable: @@ -129,22 +131,22 @@ Para aplicaciones en vivo, querrás un procesamiento continuo. Aquí tienes tus php vendor/bin/runway apm:worker --daemon # Ctrl+B, luego D para desmontar; `tmux attach -t apm-worker` para reconectar ``` - Mantiene la ejecución incluso si te desconectas. + Lo mantiene ejecutándose incluso si cierras sesión. - **Ajustes personalizados**: ```bash php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 ``` - - `--batch_size 50`: Procesar 50 métricas a la vez. - - `--max_messages 1000`: Detenerse después de 1000 métricas. - - `--timeout 300`: Salir después de 5 minutos. + - `--batch_size 50`: Procesa 50 métricas a la vez. + - `--max_messages 1000`: Se detiene después de 1000 métricas. + - `--timeout 300`: Sale después de 5 minutos. **¿Por qué molestarse?** -Sin el trabajador, tu panel de control está vacío. Es el puente entre los registros crudos y las ideas accionables. +Sin el worker, tu dashboard está vacío. Es el puente entre logs crudos e insights accionables. -### 4. Inicia el panel de control +### 4. Lanzar el Dashboard -Ve los signos vitales de tu aplicación: +Ve los vitales de tu app: ```bash php vendor/bin/runway apm:dashboard @@ -152,7 +154,7 @@ php vendor/bin/runway apm:dashboard **¿Qué es esto?** - Inicia un servidor PHP en `http://localhost:8001/apm/dashboard`. -- Muestra registros de solicitudes, rutas lentas, tasas de error y más. +- Muestra logs de solicitudes, rutas lentas, tasas de error y más. **Personalízalo**: ```bash @@ -164,47 +166,47 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l ¡Abre la URL en tu navegador y explora! -#### Modo de producción +#### Modo Producción -Para producción, es posible que debas probar algunas técnicas para que el panel funcione, ya que probablemente haya firewalls y otras medidas de seguridad. Aquí tienes algunas opciones: +Para producción, podrías tener que probar unas técnicas para hacer que el dashboard funcione, ya que probablemente hay firewalls y otras medidas de seguridad en su lugar. Aquí hay unas opciones: -- **Usa un Proxy Inverso**: Configura Nginx o Apache para reenviar solicitudes al panel. -- **Túnel SSH**: Si puedes SSH en el servidor, usa `ssh -L 8080:localhost:8001 youruser@yourserver` para tunelizar el panel a tu máquina local. -- **VPN**: Si tu servidor está detrás de una VPN, conéctate a ella y accede al panel directamente. -- **Configura el Firewall**: Abre el puerto 8001 para tu IP o la red del servidor (o el puerto que hayas establecido). -- **Configura Apache/Nginx**: Si tienes un servidor web frente a tu aplicación, puedes configurarlo para un dominio o subdominio. Si lo haces, establece la raíz de documentos en `/path/to/your/project/vendor/flightphp/apm/dashboard`. +- **Usa un Proxy Inverso**: Configura Nginx o Apache para reenviar solicitudes al dashboard. +- **Túnel SSH**: Si puedes SSH al servidor, usa `ssh -L 8080:localhost:8001 youruser@yourserver` para tunelizar el dashboard a tu máquina local. +- **VPN**: Si tu servidor está detrás de una VPN, conéctate a ella y accede al dashboard directamente. +- **Configura Firewall**: Abre el puerto 8001 para tu IP o la red del servidor. (o el puerto que hayas configurado). +- **Configura Apache/Nginx**: Si tienes un servidor web frente a tu aplicación, puedes configurarlo para un dominio o subdominio. Si haces esto, configurarás el document root a `/path/to/your/project/vendor/flightphp/apm/dashboard`. -#### ¿Quieres un panel diferente? +#### ¿Quieres un dashboard diferente? -¡Puedes construir tu propio panel si quieres! Mira el directorio `vendor/flightphp/apm/src/apm/presenter` para ideas sobre cómo presentar los datos para tu propio panel. +¡Puedes construir tu propio dashboard si quieres! Mira el directorio vendor/flightphp/apm/src/apm/presenter para ideas sobre cómo presentar la data para tu propio dashboard. -## Características del panel de control +## Características del Dashboard -El panel de control es tu sede del APM: aquí lo que verás: +El dashboard es tu HQ de APM—aquí está lo que verás: -- **Registro de solicitudes**: Cada solicitud con marca de tiempo, URL, código de respuesta y tiempo total. Haz clic en "Detalles" para middleware, consultas y errores. -- **Solicitudes más lentas**: Las 5 principales solicitudes que consumen tiempo (por ejemplo, “/api/heavy” a 2.5s). -- **Rutas más lentas**: Las 5 principales rutas por tiempo promedio: genial para detectar patrones. -- **Tasa de errores**: Porcentaje de solicitudes que fallan (por ejemplo, 2.3% de 500s). -- **Percentiles de latencia**: 95.º (p95) y 99.º (p99) tiempos de respuesta: conoce tus escenarios en el peor caso. -- **Gráfico de códigos de respuesta**: Visualiza 200s, 404s, 500s a lo largo del tiempo. -- **Consultas/Middleware largas**: Las 5 principales llamadas de base de datos lentas y capas de middleware. -- **Aciertos/Fallos de caché**: Con qué frecuencia tu caché salva el día. +- **Log de Solicitudes**: Cada solicitud con timestamp, URL, código de respuesta y tiempo total. Haz clic en “Detalles” para middleware, consultas y errores. +- **Solicitudes Más Lentas**: Top 5 solicitudes que consumen tiempo (p.ej., “/api/heavy” en 2.5s). +- **Rutas Más Lentas**: Top 5 rutas por tiempo promedio—genial para detectar patrones. +- **Tasa de Error**: Porcentaje de solicitudes que fallan (p.ej., 2.3% 500s). +- **Percentiles de Latencia**: 95th (p95) y 99th (p99) tiempos de respuesta—conoce tus escenarios de peor caso. +- **Gráfico de Código de Respuesta**: Visualiza 200s, 404s, 500s a lo largo del tiempo. +- **Consultas/Middleware Largas**: Top 5 llamadas de base de datos lentas y capas de middleware. +- **Cache Hit/Miss**: Cuánto salva tu cache el día. **Extras**: -- Filtra por “Última hora”, “Último día” o “Última semana”. -- Activa el modo oscuro para esas sesiones nocturnas. +- Filtra por “Última Hora”, “Último Día” o “Última Semana”. +- Cambia a modo oscuro para esas sesiones nocturnas. **Ejemplo**: Una solicitud a `/users` podría mostrar: -- Tiempo total: 150ms +- Tiempo Total: 150ms - Middleware: `AuthMiddleware->handle` (50ms) - Consulta: `SELECT * FROM users` (80ms) -- Caché: Acierto en `user_list` (5ms) +- Cache: Hit en `user_list` (5ms) -## Agregar eventos personalizados +## Agregando Eventos Personalizados -Rastrea cualquier cosa, como una llamada a API o un proceso de pago: +Rastrea cualquier cosa—como una llamada API o proceso de pago: ```php use flight\apm\CustomEvent; @@ -217,9 +219,9 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ``` **¿Dónde aparece?** -En los detalles de la solicitud del panel bajo “Eventos personalizados”: expandible con formato JSON bonito. +En los detalles de solicitud del dashboard bajo “Eventos Personalizados”—expandible con formato JSON bonito. -**Caso de uso**: +**Caso de Uso**: ```php $start = microtime(true); $apiResponse = file_get_contents('https://api.example.com/data'); @@ -229,80 +231,80 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -¡Ahora verás si esa API está arrastrando tu aplicación hacia abajo! +¡Ahora verás si esa API está arrastrando tu app hacia abajo! -## Monitoreo de base de datos +## Monitoreo de Base de Datos -Rastrea consultas PDO de esta manera: +Rastrea consultas PDO así: ```php use flight\database\PdoWrapper; -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- Verdadero requerido para habilitar el rastreo en el APM. +$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True requerido para habilitar el rastreo en el APM. $Apm->addPdoConnection($pdo); ``` -**Lo que obtienes**: -- Texto de la consulta (por ejemplo, `SELECT * FROM users WHERE id = ?`) -- Tiempo de ejecución (por ejemplo, 0.015s) -- Conteo de filas (por ejemplo, 42) +**Lo que Obtienes**: +- Texto de consulta (p.ej., `SELECT * FROM users WHERE id = ?`) +- Tiempo de ejecución (p.ej., 0.015s) +- Conteo de filas (p.ej., 42) -**Cuidado**: -- **Opcional**: Omite esto si no necesitas rastreo de DB. -- **Solo PdoWrapper**: PDO central no está enganchado aún, ¡permanece atento! -- **Advertencia de rendimiento**: Registrar cada consulta en un sitio con mucha DB puede ralentizar las cosas. Usa muestreo (`$Apm = new Apm($ApmLogger, 0.1)`) para aligerar la carga. +**Atención**: +- **Opcional**: Sáltate esto si no necesitas rastreo de DB. +- **Solo PdoWrapper**: PDO core no está enganchado aún—¡mantente atento! +- **Advertencia de Rendimiento**: Registrar cada consulta en un sitio pesado en DB puede ralentizar las cosas. Usa muestreo (`$Apm = new Apm($ApmLogger, 0.1)`) para aligerar la carga. -**Salida de ejemplo**: +**Salida de Ejemplo**: - Consulta: `SELECT name FROM products WHERE price > 100` - Tiempo: 0.023s - Filas: 15 -## Opciones del trabajador +## Opciones del Worker -Ajusta el trabajador a tu gusto: +Ajusta el worker a tu gusto: -- `--timeout 300`: Se detiene después de 5 minutos: bueno para pruebas. -- `--max_messages 500`: Limita a 500 métricas: lo mantiene finito. -- `--batch_size 200`: Procesar 200 a la vez: equilibra velocidad y memoria. -- `--daemon`: Se ejecuta sin parar: ideal para monitoreo en vivo. +- `--timeout 300`: Se detiene después de 5 minutos—bueno para pruebas. +- `--max_messages 500`: Limita a 500 métricas—lo mantiene finito. +- `--batch_size 200`: Procesa 200 a la vez—equilibra velocidad y memoria. +- `--daemon`: Se ejecuta sin parar—ideal para monitoreo en vivo. **Ejemplo**: ```bash php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ``` -Se ejecuta durante una hora, procesando 100 métricas a la vez. +Se ejecuta por una hora, procesando 100 métricas a la vez. -## ID de solicitud en la aplicación +## ID de Solicitud en la App -Cada solicitud tiene un ID de solicitud único para rastreo. Puedes usar este ID en tu aplicación para correlacionar registros y métricas. Por ejemplo, puedes agregar el ID de solicitud a una página de error: +Cada solicitud tiene un ID de solicitud único para rastreo. Puedes usar este ID en tu app para correlacionar logs y métricas. Por instancia, puedes agregar el ID de solicitud a una página de error: ```php Flight::map('error', function($message) { - // Obtén el ID de solicitud del encabezado de respuesta X-Flight-Request-Id + // Obtén el ID de solicitud del header de respuesta X-Flight-Request-Id $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - // Además, podrías obtenerlo de la variable de Flight - // Este método no funcionará bien en plataformas swoole u otras asíncronas. + // Adicionalmente podrías obtenerlo de la variable de Flight + // Este método no funcionará bien en swoole u otras plataformas async. // $requestId = Flight::get('apm.request_id'); echo "Error: $message (Request ID: $requestId)"; }); ``` -## Actualización +## Actualizando -Si estás actualizando a una versión más nueva del APM, es posible que haya migraciones de base de datos que necesiten ejecutarse. Puedes hacerlo ejecutando el siguiente comando: +Si estás actualizando a una versión más nueva del APM, hay una posibilidad de que haya migraciones de base de datos que necesiten ejecutarse. Puedes hacerlo ejecutando el siguiente comando: ```bash php vendor/bin/runway apm:migrate ``` -Esto ejecutará cualquier migración necesaria para actualizar el esquema de la base de datos a la última versión. +Esto ejecutará cualquier migración que sea necesaria para actualizar el esquema de la base de datos a la versión más reciente. -**Nota:** Si tu base de datos de APM es grande, estas migraciones podrían tardar un tiempo. Quizás quieras ejecutar este comando durante horas de bajo pico. +**Nota:** Si tu base de datos de APM es grande en tamaño, estas migraciones pueden tardar algo de tiempo en ejecutarse. Podrías querer ejecutar este comando durante horas de bajo pico. -## Eliminación de datos antiguos +## Purgando Datos Antiguos -Para mantener tu base de datos ordenada, puedes eliminar datos antiguos. Esto es especialmente útil si estás ejecutando una aplicación ocupada y quieres mantener el tamaño de la base de datos manejable. +Para mantener tu base de datos ordenada, puedes purgar datos antiguos. Esto es especialmente útil si estás ejecutando una app ocupada y quieres mantener el tamaño de la base de datos manejable. Puedes hacerlo ejecutando el siguiente comando: ```bash @@ -315,31 +317,31 @@ php vendor/bin/runway apm:purge --days 7 ``` Esto eliminará todos los datos más antiguos que 7 días de la base de datos. -## Solución de problemas +## Solución de Problemas ¿Atascado? Prueba estos: -- **¿No hay datos en el panel?** - - ¿Está ejecutándose el trabajador? Verifica `ps aux | grep apm:worker`. - - ¿Coinciden las rutas de configuración? Verifica que los DSNs en `.runway-config.json` apunten a archivos reales. +- **¿No hay datos en el Dashboard?** + - ¿Está el worker ejecutándose? Verifica `ps aux | grep apm:worker`. + - ¿Las rutas de config coinciden? Verifica que los DSNs en `.runway-config.json` apunten a archivos reales. - Ejecuta `php vendor/bin/runway apm:worker` manualmente para procesar métricas pendientes. -- **¿Errores en el trabajador?** - - Echa un vistazo a tus archivos SQLite (por ejemplo, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Verifica los registros de PHP en busca de trazas de pila. +- **¿Errores en el Worker?** + - Mira tus archivos SQLite (p.ej., `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). + - Verifica los logs de PHP para stack traces. -- **¿El panel no inicia?** - - ¿El puerto 8001 está en uso? Usa `--port 8080`. +- **¿El Dashboard no Inicia?** + - ¿Puerto 8001 en uso? Usa `--port 8080`. - ¿PHP no encontrado? Usa `--php-path /usr/bin/php`. - ¿Firewall bloqueando? Abre el puerto o usa `--host localhost`. -- **¿Demasiado lento?** +- **¿Demasiado Lento?** - Baja la tasa de muestreo: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - Reduce el tamaño de lote: `--batch_size 20`. -- **¿No rastreando excepciones/errores?** - - Si tienes [Tracy](https://tracy.nette.org/) habilitado para tu proyecto, anulará el manejo de errores de Flight. Debes deshabilitar Tracy y asegurarte de que `Flight::set('flight.handle_errors', true);` esté establecido. +- **¿No Rastrea Excepciones/Errores?** + - Si tienes [Tracy](https://tracy.nette.org/) habilitado para tu proyecto, sobrescribirá el manejo de errores de Flight. Necesitarás deshabilitar Tracy y luego asegurarte de que `Flight::set('flight.handle_errors', true);` esté configurado. -- **¿No rastreando consultas de base de datos?** +- **¿No Rastrea Consultas de Base de Datos?** - Asegúrate de estar usando `PdoWrapper` para tus conexiones de base de datos. - - Asegúrate de que el último argumento en el constructor sea `true`. \ No newline at end of file + - Asegúrate de hacer el último argumento en el constructor `true`. \ No newline at end of file diff --git a/content/v3/es/learn/ai.md b/content/v3/es/learn/ai.md index 2cd7e267..9049ec31 100644 --- a/content/v3/es/learn/ai.md +++ b/content/v3/es/learn/ai.md @@ -2,20 +2,20 @@ ## Resumen -Flight facilita potenciar tus proyectos PHP con herramientas impulsadas por IA y flujos de trabajo modernos para desarrolladores. Con comandos integrados para conectar con proveedores de LLM (Modelo de Lenguaje Grande) y generar instrucciones de codificación específicas del proyecto con IA, Flight te ayuda a ti y a tu equipo a sacar el máximo provecho de asistentes de IA como GitHub Copilot, Cursor y Windsurf. +Flight facilita potenciar tus proyectos PHP con herramientas impulsadas por IA y flujos de trabajo modernos para desarrolladores. Con comandos integrados para conectar con proveedores de LLM (Modelo de Lenguaje Grande) y generar instrucciones de codificación específicas del proyecto impulsadas por IA, Flight te ayuda a ti y a tu equipo a sacar el máximo provecho de asistentes de IA como GitHub Copilot, Cursor y Windsurf. ## Comprensión -Los asistentes de codificación con IA son más útiles cuando comprenden el contexto, las convenciones y los objetivos de tu proyecto. Los ayudantes de IA de Flight te permiten: +Los asistentes de codificación con IA son más útiles cuando entienden el contexto, las convenciones y los objetivos de tu proyecto. Los ayudantes de IA de Flight te permiten: - Conectar tu proyecto con proveedores populares de LLM (OpenAI, Grok, Claude, etc.) - Generar y actualizar instrucciones específicas del proyecto para herramientas de IA, para que todos reciban ayuda consistente y relevante - Mantener a tu equipo alineado y productivo, con menos tiempo dedicado a explicar el contexto -Estas características están integradas en el CLI principal de Flight y en el proyecto inicial oficial [flightphp/skeleton](https://github.com/flightphp/skeleton). +Estas funciones están integradas en el CLI principal de Flight y en el proyecto inicial oficial [flightphp/skeleton](https://github.com/flightphp/skeleton). ## Uso Básico -### 1. Configuración de Credenciales de LLM +### Configuración de Credenciales de LLM El comando `ai:init` te guía a través de la conexión de tu proyecto con un proveedor de LLM. @@ -40,7 +40,7 @@ Ingresa el nombre del modelo que quieres usar (p.ej. gpt-4, claude-3-opus, etc) Credenciales guardadas en .runway-creds.json ``` -### 2. Generación de Instrucciones Específicas del Proyecto para IA +### Generación de Instrucciones de IA Específicas del Proyecto El comando `ai:generate-instructions` te ayuda a crear o actualizar instrucciones para asistentes de codificación con IA, adaptadas a tu proyecto. @@ -48,7 +48,7 @@ El comando `ai:generate-instructions` te ayuda a crear o actualizar instruccione php runway ai:generate-instructions ``` -Responderás algunas preguntas sobre tu proyecto (descripción, base de datos, plantillas, seguridad, tamaño del equipo, etc.). Flight usa tu proveedor de LLM para generar instrucciones y luego las escribe en: +Responderás a unas pocas preguntas sobre tu proyecto (descripción, base de datos, plantillas, seguridad, tamaño del equipo, etc.). Flight usa tu proveedor de LLM para generar instrucciones y luego las escribe en: - `.github/copilot-instructions.md` (para GitHub Copilot) - `.cursor/rules/project-overview.mdc` (para Cursor) - `.windsurfrules` (para Windsurf) @@ -69,7 +69,7 @@ Ahora, tus herramientas de IA darán sugerencias más inteligentes y relevantes - Puedes personalizar la ubicación de tus archivos de credenciales o instrucciones usando opciones de comando (ver `--help` para cada comando). - Los ayudantes de IA están diseñados para funcionar con cualquier proveedor de LLM que soporte APIs compatibles con OpenAI. -- Si quieres actualizar tus instrucciones a medida que tu proyecto evoluciona, solo vuelve a ejecutar `ai:generate-instructions` y responde los prompts nuevamente. +- Si quieres actualizar tus instrucciones a medida que evoluciona tu proyecto, solo vuelve a ejecutar `ai:generate-instructions` y responde a los prompts nuevamente. ## Ver También @@ -78,7 +78,7 @@ Ahora, tus herramientas de IA darán sugerencias más inteligentes y relevantes ## Solución de Problemas -- Si ves "Missing .runway-creds.json", ejecuta `php runway ai:init` primero. +- Si ves "Falta .runway-creds.json", ejecuta `php runway ai:init` primero. - Asegúrate de que tu clave API sea válida y tenga acceso al modelo seleccionado. - Si las instrucciones no se actualizan, verifica los permisos de archivos en tu directorio de proyecto. diff --git a/content/v3/es/learn/requests.md b/content/v3/es/learn/requests.md index 62ab9d55..c5a38a05 100644 --- a/content/v3/es/learn/requests.md +++ b/content/v3/es/learn/requests.md @@ -8,15 +8,15 @@ Flight encapsula la solicitud HTTP en un solo objeto, que se puede acceder hacie $request = Flight::request(); ``` -## Comprensión +## Entendiendo -Las solicitudes HTTP son uno de los aspectos centrales para entender sobre el ciclo de vida de HTTP. Un usuario realiza una acción en un navegador web o un cliente HTTP, y envían una serie de encabezados, cuerpo, URL, etc. a tu proyecto. Puedes capturar estos encabezados (el idioma del navegador, qué tipo de compresión pueden manejar, el agente de usuario, etc.) y capturar el cuerpo y la URL que se envía a tu aplicación Flight. Estas solicitudes son esenciales para que tu app entienda qué hacer a continuación. +Las solicitudes HTTP son uno de los aspectos principales a entender sobre el ciclo de vida de HTTP. Un usuario realiza una acción en un navegador web o un cliente HTTP, y envían una serie de encabezados, cuerpo, URL, etc. a tu proyecto. Puedes capturar estos encabezados (el idioma del navegador, qué tipo de compresión pueden manejar, el agente de usuario, etc.) y capturar el cuerpo y la URL que se envía a tu aplicación Flight. Estas solicitudes son esenciales para que tu app entienda qué hacer a continuación. ## Uso Básico -PHP tiene varios super globals incluyendo `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` y `$_COOKIE`. Flight abstrae estos en [Collections](/learn/collections) prácticas. Puedes acceder a las propiedades `query`, `data`, `cookies` y `files` como arrays u objetos. +PHP tiene varios super globals incluyendo `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` y `$_COOKIE`. Flight abstrae estos en prácticas [Collections](/learn/collections). Puedes acceder a las propiedades `query`, `data`, `cookies` y `files` como arrays o objetos. -> **Nota:** Se **DESACONSEJA EN ALTO GRADO** usar estos super globals en tu proyecto y deben referenciarse a través del objeto `request()`. +> **Nota:** Se **DESACONSEJA EN ALTO GRADO** usar estos super globals en tu proyecto y deben ser referenciados a través del objeto `request()`. > **Nota:** No hay abstracción disponible para `$_ENV`. @@ -31,7 +31,7 @@ Flight::route('/search', function(){ // o $keyword = Flight::request()->query->keyword; echo "Estás buscando: $keyword"; - // consulta una base de datos o algo más con el $keyword + // consultar una base de datos o algo más con el $keyword }); ``` @@ -47,7 +47,7 @@ Flight::route('POST /submit', function(){ $name = Flight::request()->data->name; $email = Flight::request()->data->email; echo "Enviaste: $name, $email"; - // guarda en una base de datos o algo más con el $name y $email + // guardar en una base de datos o algo más con el $name y $email }); ``` @@ -60,7 +60,7 @@ Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; // o $savedLogin = Flight::request()->cookies->myLoginCookie; - // verifica si realmente está guardado o no y si lo está, inicia sesión automáticamente + // verificar si realmente está guardado o no y si lo está, iniciar sesión automáticamente if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -68,11 +68,11 @@ Flight::route('GET /login', function(){ }); ``` -Para obtener ayuda sobre cómo establecer nuevos valores de cookies, consulta [overclokk/cookie](/awesome-plugins/php-cookie) +Para ayuda sobre cómo establecer nuevos valores de cookies, consulta [overclokk/cookie](/awesome-plugins/php-cookie) ### `$_SERVER` -Hay un acceso directo disponible para acceder al array `$_SERVER` a través del método `getVar()`: +Hay un método abreviado disponible para acceder al array `$_SERVER` a través del método `getVar()`: ```php @@ -84,7 +84,7 @@ $host = Flight::request()->getVar('HTTP_HOST'); Puedes acceder a los archivos subidos a través de la propiedad `files`: ```php -// acceso raw a la propiedad $_FILES. Ver abajo para el enfoque recomendado +// acceso directo a la propiedad $_FILES. Ver abajo para el enfoque recomendado $uploadedFile = Flight::request()->files['myFile']; // o $uploadedFile = Flight::request()->files->myFile; @@ -123,18 +123,18 @@ Flight::route('POST /upload', function(){ ### Cuerpo de la Solicitud -Para obtener el cuerpo raw de la solicitud HTTP, por ejemplo al tratar con solicitudes POST/PUT, puedes hacer: +Para obtener el cuerpo crudo de la solicitud HTTP, por ejemplo al tratar con solicitudes POST/PUT, puedes hacer: ```php Flight::route('POST /users/xml', function(){ $xmlBody = Flight::request()->getBody(); - // haz algo con el XML que fue enviado. + // hacer algo con el XML que fue enviado. }); ``` ### Cuerpo JSON -Si recibes una solicitud con el tipo de contenido `application/json` y los datos de ejemplo de `{"id": 123}` estará disponible desde la propiedad `data`: +Si recibes una solicitud con el tipo de contenido `application/json` y los datos de ejemplo `{"id": 123}`, estará disponible desde la propiedad `data`: ```php $id = Flight::request()->data->id; @@ -168,11 +168,11 @@ $method = Flight::request()->getMethod(); **Nota:** El método `getMethod()` primero extrae el método de `$_SERVER['REQUEST_METHOD']`, luego puede ser sobrescrito por `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` si existe o `$_REQUEST['_method']` si existe. -## Propiedades del Objeto Solicitud +## Propiedades del Objeto de Solicitud -El objeto solicitud proporciona las siguientes propiedades: +El objeto de solicitud proporciona las siguientes propiedades: -- **body** - El cuerpo raw de la solicitud HTTP +- **body** - El cuerpo crudo de la solicitud HTTP - **url** - La URL solicitada - **base** - El subdirectorio padre de la URL - **method** - El método de la solicitud (GET, POST, PUT, DELETE) @@ -189,13 +189,13 @@ El objeto solicitud proporciona las siguientes propiedades: - **files** - Archivos subidos - **secure** - Si la conexión es segura - **accept** - Parámetros de aceptación HTTP -- **proxy_ip** - Dirección IP proxy del cliente. Escanea el array `$_SERVER` para `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` en ese orden. +- **proxy_ip** - Dirección IP del proxy del cliente. Escanea el array `$_SERVER` en busca de `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` en ese orden. - **host** - El nombre de host de la solicitud - **servername** - El SERVER_NAME de `$_SERVER` -## Métodos de Ayuda para URL +## Métodos de Ayuda -Hay un par de métodos de ayuda para ensamblar partes de una URL para tu conveniencia. +Hay un par de métodos de ayuda para ensamblar partes de una URL o tratar con ciertos encabezados. ### URL Completa @@ -214,10 +214,10 @@ Puedes acceder a la URL base usando el método `getBaseUrl()`: // http://example.com/path/to/something/cool?query=yes+thanks $url = Flight::request()->getBaseUrl(); // https://example.com -// Nota, no hay barra final. +// Nota, sin barra final. ``` -## Análisis de Consulta +## Análisis de Consultas Puedes pasar una URL al método `parseQuery()` para analizar la cadena de consulta en un array asociativo: @@ -226,8 +226,31 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` +## Negociación de Tipos de Contenido Aceptados + +_v3.17.2_ + +Puedes usar el método `negotiateContentType()` para determinar el mejor tipo de contenido para responder basado en el encabezado `Accept` enviado por el cliente. + +```php + +// Ejemplo de encabezado Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// Lo de abajo define lo que soportas. +$availableTypes = ['application/json', 'application/xml']; +$typeToServe = Flight::request()->negotiateContentType($availableTypes); +if ($typeToServe === 'application/json') { + // Servir respuesta JSON +} elseif ($typeToServe === 'application/xml') { + // Servir respuesta XML +} else { + // Por defecto a algo más o lanzar un error +} +``` + +> **Nota:** Si ninguno de los tipos disponibles se encuentra en el encabezado `Accept`, el método retornará `null`. Si no hay encabezado `Accept` definido, el método retornará el primer tipo en el array `$availableTypes`. + ## Ver También -- [Routing](/learn/routing) - Ve cómo mapear rutas a controladores y renderizar vistas. +- [Routing](/learn/routing) - Ver cómo mapear rutas a controladores y renderizar vistas. - [Responses](/learn/responses) - Cómo personalizar respuestas HTTP. - [Why a Framework?](/learn/why-frameworks) - Cómo encajan las solicitudes en el panorama general. - [Collections](/learn/collections) - Trabajando con colecciones de datos. @@ -237,5 +260,6 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); - `request()->ip` y `request()->proxy_ip` pueden ser diferentes si tu servidor web está detrás de un proxy, balanceador de carga, etc. ## Registro de Cambios -- v3.12.0 - Agregada la capacidad para manejar subidas de archivos a través del objeto solicitud. +- v3.17.2 - Agregado negotiateContentType() +- v3.12.0 - Agregada la capacidad para manejar subidas de archivos a través del objeto de solicitud. - v1.0 - Lanzamiento inicial. \ No newline at end of file diff --git a/content/v3/es/learn/responses.md b/content/v3/es/learn/responses.md index 1f5798c9..cb2fa45d 100644 --- a/content/v3/es/learn/responses.md +++ b/content/v3/es/learn/responses.md @@ -2,20 +2,19 @@ ## Resumen -Flight ayuda a generar parte de los encabezados de respuesta por ti, pero tú tienes la mayor parte del control sobre lo que envías de vuelta al usuario. La mayoría del tiempo accederás directamente al objeto `response()`, pero Flight tiene algunos métodos auxiliares para establecer algunos de los encabezados de respuesta por ti. +Flight ayuda a generar parte de los encabezados de respuesta por ti, pero tú tienes la mayoría del control sobre lo que envías de vuelta al usuario. La mayoría del tiempo accederás directamente al objeto `response()`, pero Flight tiene algunos métodos auxiliares para configurar algunos de los encabezados de respuesta por ti. ## Comprensión -Después de que el usuario envíe su [solicitud](/learn/requests) a tu aplicación, necesitas generar una respuesta adecuada para ellos. Te han enviado información como el idioma que prefieren, si pueden manejar ciertos tipos de compresión, su agente de usuario, etc., y después de procesar todo, es hora de enviarles de vuelta una respuesta adecuada. Esto puede ser establecer encabezados, generar un cuerpo de HTML o JSON para ellos, o redirigirlos a una página. +Después de que el usuario envíe su [solicitud](/learn/requests) a tu aplicación, necesitas generar una respuesta adecuada para ellos. Te han enviado información como el idioma que prefieren, si pueden manejar ciertos tipos de compresión, su agente de usuario, etc., y después de procesar todo, es hora de enviarles una respuesta adecuada. Esto puede ser configurar encabezados, generar un cuerpo de HTML o JSON para ellos, o redirigirlos a una página. -## Uso Básico +## Uso básico -### Envío de un Cuerpo de Respuesta +### Envío de un cuerpo de respuesta -Flight utiliza `ob_start()` para almacenar en búfer la salida. Esto significa que puedes usar `echo` o `print` para enviar una respuesta al usuario y Flight la capturará y la enviará de vuelta al usuario con los encabezados apropiados. +Flight usa `ob_start()` para almacenar en búfer la salida. Esto significa que puedes usar `echo` o `print` para enviar una respuesta al usuario y Flight la capturará y la enviará de vuelta al usuario con los encabezados apropiados. ```php - // Esto enviará "Hello, World!" al navegador del usuario Flight::route('/', function() { echo "Hello, World!"; @@ -30,13 +29,12 @@ Flight::route('/', function() { Como alternativa, puedes llamar al método `write()` para agregar al cuerpo también. ```php - // Esto enviará "Hello, World!" al navegador del usuario Flight::route('/', function() { // verboso, pero a veces hace el trabajo cuando lo necesitas Flight::response()->write("Hello, World!"); - // si quieres recuperar el cuerpo que has establecido en este punto + // si quieres recuperar el cuerpo que has configurado en este punto // puedes hacerlo así $body = Flight::response()->getBody(); }); @@ -44,7 +42,7 @@ Flight::route('/', function() { ### JSON -Flight proporciona soporte para enviar respuestas JSON y JSONP. Para enviar una respuesta JSON, pasas algunos datos para ser codificados en JSON: +Flight proporciona soporte para enviar respuestas JSON y JSONP. Para enviar una respuesta JSON, pasa algunos datos para que se codifiquen en JSON: ```php Flight::route('/@companyId/users', function(int $companyId) { @@ -58,15 +56,15 @@ Flight::route('/@companyId/users', function(int $companyId) { > **Nota:** Por defecto, Flight enviará un encabezado `Content-Type: application/json` con la respuesta. También usará las banderas `JSON_THROW_ON_ERROR` y `JSON_UNESCAPED_SLASHES` al codificar el JSON. -#### JSON con Código de Estado +#### JSON con código de estado -También puedes pasar un código de estado como el segundo argumento: +También puedes pasar un código de estado como segundo argumento: ```php Flight::json(['id' => 123], 201); ``` -#### JSON con Impresión Bonita +#### JSON con impresión bonita También puedes pasar un argumento en la última posición para habilitar la impresión bonita: @@ -74,14 +72,14 @@ También puedes pasar un argumento en la última posición para habilitar la imp Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT); ``` -#### Cambiar el Orden de los Argumentos de JSON +#### Cambiar el orden de los argumentos JSON `Flight::json()` es un método muy antiguo, pero el objetivo de Flight es mantener la compatibilidad hacia atrás para los proyectos. En realidad es muy simple si quieres rehacer el orden de los argumentos para usar una sintaxis más simple, puedes simplemente remapear el método JSON [como cualquier otro método de Flight](/learn/extending): ```php Flight::map('json', function($data, $code = 200, $options = 0) { - // ahora no tienes que `true, 'utf-8'` cuando uses el método json()! + // ahora no tienes que usar `true, 'utf-8'` al usar el método json()! Flight::_json($data, $code, true, 'utf-8', $options); } @@ -89,22 +87,22 @@ Flight::map('json', function($data, $code = 200, $options = 0) { Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT); ``` -#### JSON y Detener la Ejecución +#### JSON y detención de ejecución _v3.10.0_ -Si quieres enviar una respuesta JSON y detener la ejecución, puedes usar el método `jsonHalt()`. Esto es útil para casos en los que estás verificando tal vez algún tipo de autorización y si el usuario no está autorizado, puedes enviar una respuesta JSON inmediatamente, borrar el contenido del cuerpo existente y detener la ejecución. +Si quieres enviar una respuesta JSON y detener la ejecución, puedes usar el método `jsonHalt()`. Esto es útil para casos en los que estás verificando quizás algún tipo de autorización y si el usuario no está autorizado, puedes enviar una respuesta JSON inmediatamente, limpiar el contenido del cuerpo existente y detener la ejecución. ```php Flight::route('/users', function() { $authorized = someAuthorizationCheck(); - // Verificar si el usuario está autorizado + // Verifica si el usuario está autorizado if($authorized === false) { Flight::jsonHalt(['error' => 'Unauthorized'], 401); - // no exit; necesario aquí. + // no se necesita exit; aquí. } - // Continuar con el resto de la ruta + // Continúa con el resto de la ruta }); ``` @@ -113,16 +111,16 @@ Antes de v3.10.0, tendrías que hacer algo como esto: ```php Flight::route('/users', function() { $authorized = someAuthorizationCheck(); - // Verificar si el usuario está autorizado + // Verifica si el usuario está autorizado if($authorized === false) { Flight::halt(401, json_encode(['error' => 'Unauthorized'])); } - // Continuar con el resto de la ruta + // Continúa con el resto de la ruta }); ``` -### Limpiar un Cuerpo de Respuesta +### Limpieza de un cuerpo de respuesta Si quieres limpiar el cuerpo de la respuesta, puedes usar el método `clearBody`: @@ -138,7 +136,7 @@ Flight::route('/', function() { El caso de uso anterior probablemente no es común, sin embargo podría ser más común si se usara en un [middleware](/learn/middleware). -### Ejecutar un Callback en el Cuerpo de Respuesta +### Ejecución de un callback en el cuerpo de la respuesta Puedes ejecutar un callback en el cuerpo de la respuesta usando el método `addResponseBodyCallback`: @@ -149,17 +147,17 @@ Flight::route('/users', function() { Flight::render('users_table', ['users' => $users]); }); -// Esto comprimirá con gzip todas las respuestas para cualquier ruta +// Esto comprime con gzip todas las respuestas para cualquier ruta Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); ``` -Puedes agregar múltiples callbacks y se ejecutarán en el orden en que se agregaron. Dado que esto puede aceptar cualquier [callable](https://www.php.net/manual/en/language.types.callable.php), puede aceptar un array de clase `[ $class, 'method' ]`, un closure `$strReplace = function($body) { str_replace('hi', 'there', $body); };`, o un nombre de función `'minify'` si tuvieras una función para minificar tu código HTML por ejemplo. +Puedes agregar múltiples callbacks y se ejecutarán en el orden en que se agregaron. Dado que esto puede aceptar cualquier [llamable](https://www.php.net/manual/en/language.types.callable.php), puede aceptar un array de clase `[ $class, 'method' ]`, una closure `$strReplace = function($body) { str_replace('hi', 'there', $body); };`, o un nombre de función `'minify'` si tuvieras una función para minificar tu código HTML por ejemplo. **Nota:** Los callbacks de ruta no funcionarán si estás usando la opción de configuración `flight.v2.output_buffering`. -#### Callback de Ruta Específica +#### Callback de ruta específica Si quisieras que esto solo se aplique a una ruta específica, podrías agregar el callback en la ruta misma: @@ -169,14 +167,14 @@ Flight::route('/users', function() { $users = $db->fetchAll("SELECT * FROM users"); Flight::render('users_table', ['users' => $users]); - // Esto comprimirá con gzip solo la respuesta para esta ruta + // Esto comprime con gzip solo la respuesta para esta ruta Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); }); ``` -#### Opción de Middleware +#### Opción de middleware También puedes usar [middleware](/learn/middleware) para aplicar el callback a todas las rutas a través de middleware: @@ -184,14 +182,14 @@ También puedes usar [middleware](/learn/middleware) para aplicar el callback a // MinifyMiddleware.php class MinifyMiddleware { public function before() { - // Aplicar el callback aquí en el objeto response(). + // Aplica el callback aquí en el objeto response(). Flight::response()->addResponseBodyCallback(function($body) { return $this->minify($body); }); } protected function minify(string $body): string { - // minificar el cuerpo de alguna manera + // minifica el cuerpo de alguna manera return $body; } } @@ -203,9 +201,9 @@ Flight::group('/users', function() { }, [ new MinifyMiddleware() ]); ``` -### Códigos de Estado +### Códigos de estado -Puedes establecer el código de estado de la respuesta usando el método `status`: +Puedes configurar el código de estado de la respuesta usando el método `status`: ```php Flight::route('/@id', function($id) { @@ -219,15 +217,15 @@ Flight::route('/@id', function($id) { }); ``` -Si quieres obtener el código de estado actual, puedes usar el método `status` sin ningún argumento: +Si quieres obtener el código de estado actual, puedes usar el método `status` sin argumentos: ```php Flight::response()->status(); // 200 ``` -### Establecer un Encabezado de Respuesta +### Configuración de un encabezado de respuesta -Puedes establecer un encabezado como el tipo de contenido de la respuesta usando el método `header`: +Puedes configurar un encabezado como el tipo de contenido de la respuesta usando el método `header`: ```php // Esto enviará "Hello, World!" al navegador del usuario en texto plano @@ -239,7 +237,7 @@ Flight::route('/', function() { }); ``` -### Redirigir +### Redirección Puedes redirigir la solicitud actual usando el método `redirect()` y pasando una nueva URL: @@ -251,22 +249,22 @@ Flight::route('/login', function() { if($password !== $passwordConfirm) { Flight::redirect('/new/location'); - return; // esto es necesario para que la funcionalidad de abajo no se ejecute + return; // esto es necesario para que la funcionalidad a continuación no se ejecute } - // agregar el nuevo usuario... + // agrega el nuevo usuario... Flight::db()->runQuery("INSERT INTO users ...."); Flight::redirect('/admin/dashboard'); }); ``` -> **Nota:** Por defecto Flight envía un código de estado HTTP 303 ("See Other"). Puedes establecer opcionalmente un código personalizado: +> **Nota:** Por defecto, Flight envía un código de estado HTTP 303 ("See Other"). Puedes configurar opcionalmente un código personalizado: ```php Flight::redirect('/new/location', 301); // permanente ``` -### Detener la Ejecución de la Ruta +### Detención de la ejecución de la ruta Puedes detener el framework y salir inmediatamente en cualquier punto llamando al método `halt`: @@ -286,15 +284,15 @@ Llamar a `halt` descartará cualquier contenido de respuesta hasta ese punto y d Flight::stop($httpStatusCode = null); ``` -> **Nota:** `Flight::stop()` tiene un comportamiento extraño como que generará la respuesta pero continuará ejecutando tu script lo que podría no ser lo que buscas. Puedes usar `exit` o `return` después de llamar a `Flight::stop()` para prevenir la ejecución adicional, pero generalmente se recomienda usar `Flight::halt()`. +> **Nota:** `Flight::stop()` tiene un comportamiento extraño, como que generará la respuesta pero continuará ejecutando tu script, lo cual podría no ser lo que buscas. Puedes usar `exit` o `return` después de llamar a `Flight::stop()` para prevenir la ejecución adicional, pero en general se recomienda usar `Flight::halt()`. Esto guardará la clave y el valor del encabezado en el objeto de respuesta. Al final del ciclo de vida de la solicitud, construirá los encabezados y enviará una respuesta. -## Uso Avanzado +## Uso avanzado -### Envío de un Encabezado Inmediatamente +### Envío de un encabezado inmediatamente -Puede haber veces en las que necesites hacer algo personalizado con el encabezado y necesites enviar el encabezado en esa misma línea de código con la que estás trabajando. Si estás estableciendo una [ruta transmitida](/learn/routing), esto es lo que necesitarías. Eso se logra a través de `response()->setRealHeader()`. +Puede haber veces en las que necesites hacer algo personalizado con el encabezado y necesites enviar el encabezado en esa misma línea de código con la que estás trabajando. Si estás configurando una [ruta transmitida](/learn/routing), esto es lo que necesitarías. Eso se logra a través de `response()->setRealHeader()`. ```php Flight::route('/', function() { @@ -319,32 +317,32 @@ Entonces, al hacer una solicitud GET usando `?q=my_func`, deberías recibir la s my_func({"id":123}); ``` -Si no pasas un nombre de parámetro de consulta, por defecto será `jsonp`. +Si no pasas un nombre de parámetro de consulta, se usará `jsonp` por defecto. -> **Nota:** Si todavía estás usando solicitudes JSONP en 2025 y más allá, únete al chat y cuéntanos por qué! Nos encanta escuchar algunas buenas historias de batalla/horror! +> **Nota:** Si aún estás usando solicitudes JSONP en 2025 y más allá, únete al chat y cuéntanos por qué! ¡Nos encanta escuchar algunas buenas historias de batalla/horror! -### Limpiar Datos de Respuesta +### Limpieza de datos de respuesta -Puedes limpiar el cuerpo de la respuesta y los encabezados usando el método `clear()`. Esto limpiará cualquier encabezado asignado a la respuesta, limpiará el cuerpo de la respuesta y establecerá el código de estado en `200`. +Puedes limpiar el cuerpo de la respuesta y los encabezados usando el método `clear()`. Esto limpiará cualquier encabezado asignado a la respuesta, limpiará el cuerpo de la respuesta y configurará el código de estado en `200`. ```php Flight::response()->clear(); ``` -#### Limpiar Solo el Cuerpo de Respuesta +#### Limpieza solo del cuerpo de respuesta Si solo quieres limpiar el cuerpo de la respuesta, puedes usar el método `clearBody()`: ```php -// Esto mantendrá cualquier encabezado establecido en el objeto response(). -// Flight::response()->clearBody(); +// Esto aún mantendrá cualquier encabezado configurado en el objeto response(). +Flight::response()->clearBody(); ``` ### Caché HTTP Flight proporciona soporte integrado para caché a nivel HTTP. Si se cumple la condición de caché, Flight devolverá una respuesta HTTP `304 Not Modified`. La próxima vez que el cliente solicite el mismo recurso, se le indicará que use su versión en caché localmente. -#### Caché a Nivel de Ruta +#### Caché a nivel de ruta Si quieres cachear toda tu respuesta, puedes usar el método `cache()` y pasar el tiempo para cachear. @@ -364,9 +362,9 @@ Flight::route('/news', function () { }); ``` -### Última Modificación +### Última modificación -Puedes usar el método `lastModified` y pasar un timestamp UNIX para establecer la fecha y hora en que una página fue modificada por última vez. El cliente continuará usando su caché hasta que el valor de última modificación cambie. +Puedes usar el método `lastModified` y pasar una marca de tiempo UNIX para configurar la fecha y hora en que una página fue modificada por última vez. El cliente continuará usando su caché hasta que el valor de última modificación cambie. ```php Flight::route('/news', function () { @@ -386,9 +384,9 @@ Flight::route('/news', function () { }); ``` -Ten en cuenta que llamar a `lastModified` o `etag` establecerá y verificará ambos el valor de caché. Si el valor de caché es el mismo entre solicitudes, Flight enviará inmediatamente una respuesta `HTTP 304` y detendrá el procesamiento. +Ten en cuenta que llamar a cualquiera de `lastModified` o `etag` configurará y verificará ambos el valor de caché. Si el valor de caché es el mismo entre solicitudes, Flight enviará inmediatamente una respuesta `HTTP 304` y detendrá el procesamiento. -### Descargar un Archivo +### Descarga de un archivo _v3.12.0_ @@ -397,21 +395,24 @@ Hay un método auxiliar para transmitir un archivo al usuario final. Puedes usar ```php Flight::route('/download', function () { Flight::download('/path/to/file.txt'); + // A partir de v3.17.1 puedes especificar un nombre de archivo personalizado para la descarga + Flight::download('/path/to/file.txt', 'custom_name.txt'); }); ``` -## Ver También -- [Routing](/learn/routing) - Cómo mapear rutas a controladores y renderizar vistas. -- [Requests](/learn/requests) - Comprender cómo manejar solicitudes entrantes. +## Ver también +- [Enrutamiento](/learn/routing) - Cómo mapear rutas a controladores y renderizar vistas. +- [Solicitudes](/learn/requests) - Comprender cómo manejar solicitudes entrantes. - [Middleware](/learn/middleware) - Usar middleware con rutas para autenticación, registro, etc. -- [Why a Framework?](/learn/why-frameworks) - Comprender los beneficios de usar un framework como Flight. -- [Extending](/learn/extending) - Cómo extender Flight con tu propia funcionalidad. +- [¿Por qué un framework?](/learn/why-frameworks) - Comprender los beneficios de usar un framework como Flight. +- [Extensión](/learn/extending) - Cómo extender Flight con tu propia funcionalidad. -## Solución de Problemas -- Si tienes problemas con redirecciones que no funcionan, asegúrate de agregar un `return;` al método. +## Solución de problemas +- Si tienes problemas con las redirecciones que no funcionan, asegúrate de agregar un `return;` al método. - `stop()` y `halt()` no son lo mismo. `halt()` detendrá la ejecución inmediatamente, mientras que `stop()` permitirá que la ejecución continúe. -## Registro de Cambios -- v3.12.0 - Agregado método auxiliar downloadFile. +## Registro de cambios +- v3.17.1 - Agregado `$fileName` al método `downloadFile()`. +- v3.12.0 - Agregado método auxiliar `downloadFile`. - v3.10.0 - Agregado `jsonHalt`. - v1.0 - Lanzamiento inicial. \ No newline at end of file diff --git a/content/v3/es/learn/routing.md b/content/v3/es/learn/routing.md index c0623944..b4d2ba7a 100644 --- a/content/v3/es/learn/routing.md +++ b/content/v3/es/learn/routing.md @@ -1,12 +1,12 @@ # Enrutamiento ## Resumen -El enrutamiento en Flight PHP mapea patrones de URL a funciones de devolución de llamada o métodos de clase, permitiendo un manejo rápido y simple de las solicitudes. Está diseñado para un overhead mínimo, un uso amigable para principiantes y extensibilidad sin dependencias externas. +El enrutamiento en Flight PHP mapea patrones de URL a funciones de devolución de llamada o métodos de clase, permitiendo un manejo rápido y simple de solicitudes. Está diseñado para un overhead mínimo, un uso amigable para principiantes y extensibilidad sin dependencias externas. ## Comprensión El enrutamiento es el mecanismo central que conecta las solicitudes HTTP con la lógica de su aplicación en Flight. Al definir rutas, especifica cómo diferentes URLs activan código específico, ya sea a través de funciones, métodos de clase o acciones de controladores. El sistema de enrutamiento de Flight es flexible, soporta patrones básicos, parámetros con nombre, expresiones regulares y características avanzadas como inyección de dependencias y enrutamiento de recursos. Este enfoque mantiene su código organizado y fácil de mantener, mientras permanece rápido y simple para principiantes y extensible para usuarios avanzados. -> **Nota:** ¿Quieres entender más sobre el enrutamiento? Revisa la página ["¿por qué un framework?"](/learn/why-frameworks) para una explicación más detallada. +> **Nota:** ¿Quieres entender más sobre el enrutamiento? Revisa la página ["por qué un framework?"](/learn/why-frameworks) para una explicación más detallada. ## Uso Básico @@ -77,7 +77,7 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **Nota:** Por defecto, cuando se llama a un controlador dentro del framework, la clase `flight\Engine` siempre se inyecta a menos que especifiques a través de un [contenedor de inyección de dependencias](/learn/dependency-injection-container) +> **Nota:** Por defecto, cuando un controlador es llamado dentro del framework, la clase `flight\Engine` siempre se inyecta a menos que especifiques a través de un [contenedor de inyección de dependencias](/learn/dependency-injection-container) ### Enrutamiento Específico de Método @@ -108,6 +108,38 @@ Flight::route('GET|POST /', function () { }); ``` +### Manejo Especial para Solicitudes HEAD y OPTIONS + +Flight proporciona manejo integrado para solicitudes HTTP `HEAD` y `OPTIONS`: + +#### Solicitudes HEAD + +- Las **solicitudes HEAD** se tratan igual que las solicitudes `GET`, pero Flight automáticamente elimina el cuerpo de la respuesta antes de enviarlo al cliente. +- Esto significa que puedes definir una ruta para `GET`, y las solicitudes HEAD a la misma URL devolverán solo encabezados (sin contenido), como se espera en los estándares HTTP. + +```php +Flight::route('GET /info', function() { + echo 'This is some info!'; +}); +// Una solicitud HEAD a /info devolverá los mismos encabezados, pero sin cuerpo. +``` + +#### Solicitudes OPTIONS + +Las solicitudes `OPTIONS` son manejadas automáticamente por Flight para cualquier ruta definida. +- Cuando se recibe una solicitud OPTIONS, Flight responde con un estado `204 No Content` y un encabezado `Allow` que lista todos los métodos HTTP soportados para esa ruta. +- No necesitas definir una ruta separada para OPTIONS a menos que quieras un comportamiento personalizado o modificar la respuesta. + +```php +// Para una ruta definida como: +Flight::route('GET|POST /users', function() { /* ... */ }); + +// Una solicitud OPTIONS a /users responderá con: +// +// Status: 204 No Content +// Allow: GET, POST, HEAD, OPTIONS +``` + ### Usando el Objeto Router Adicionalmente, puedes obtener el objeto Router que tiene algunos métodos auxiliares para que uses: @@ -143,7 +175,7 @@ Flight::route('/user/[0-9]+', function () { Aunque este método está disponible, se recomienda usar parámetros con nombre, o parámetros con nombre con expresiones regulares, ya que son más legibles y fáciles de mantener. ### Parámetros con Nombre -Puedes especificar parámetros con nombre en tus rutas que se pasarán a tu función de devolución de llamada. **Esto es más para la legibilidad de la ruta que para cualquier otra cosa. Por favor, ve la sección a continuación sobre una advertencia importante.** +Puedes especificar parámetros con nombre en tus rutas que se pasarán a tu función de devolución de llamada. **Esto es más para la legibilidad de la ruta que para cualquier otra cosa. Por favor, ve la sección a continuación sobre la advertencia importante.** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -173,7 +205,7 @@ Flight::route('/@name/@id', function (string $id, string $name) { ``` Y si fueras a la siguiente URL: `/bob/123`, la salida sería `hello, 123 (bob)!`. -_Por favor ten cuidado_ cuando configures tus rutas y tus funciones de devolución de llamada! +_Por favor ten cuidado_ cuando estés configurando tus rutas y tus funciones de devolución de llamada! ### Parámetros Opcionales Puedes especificar parámetros con nombre que sean opcionales para la coincidencia envolviendo segmentos en paréntesis. @@ -212,7 +244,7 @@ Flight::route('*', function () { ### Manejador de 404 No Encontrado -Por defecto, si una URL no se puede encontrar, Flight enviará una respuesta `HTTP 404 Not Found` que es muy simple y plana. +Por defecto, si una URL no se encuentra, Flight enviará una respuesta `HTTP 404 Not Found` que es muy simple y plana. Si quieres tener una respuesta 404 más personalizada, puedes [mapear](/learn/extending) tu propio método `notFound`: ```php @@ -233,10 +265,39 @@ Flight::map('notFound', function() { }); ``` +### Manejador de Método No Encontrado + +Por defecto, si una URL se encuentra pero el método no está permitido, Flight enviará una respuesta `HTTP 405 Method Not Allowed` que es muy simple y plana (Ej: Method Not Allowed. Allowed Methods are: GET, POST). También incluirá un encabezado `Allow` con los métodos permitidos para esa URL. + +Si quieres tener una respuesta 405 más personalizada, puedes [mapear](/learn/extending) tu propio método `methodNotFound`: + +```php +use flight\net\Route; + +Flight::map('methodNotFound', function(Route $route) { + $url = Flight::request()->url; + $methods = implode(', ', $route->methods); + + // También podrías usar Flight::render() con una plantilla personalizada. + $output = <<My Custom 405 Method Not Allowed +

The method you have requested for {$url} is not allowed.

+

Allowed Methods are: {$methods}

+ HTML; + + $this->response() + ->clearBody() + ->status(405) + ->setHeader('Allow', $methods) + ->write($output) + ->send(); +}); +``` + ## Uso Avanzado ### Inyección de Dependencias en Rutas -Si quieres usar inyección de dependencias a través de un contenedor (PSR-11, PHP-DI, Dice, etc.), el único tipo de rutas donde eso está disponible es ya sea creando directamente el objeto tú mismo y usando el contenedor para crear tu objeto o puedes usar cadenas para definir la clase y el método a llamar. Puedes ir a la página de [Inyección de Dependencias](/learn/dependency-injection-container) para más información. +Si quieres usar inyección de dependencias a través de un contenedor (PSR-11, PHP-DI, Dice, etc.), el único tipo de rutas donde eso está disponible es ya sea creando directamente el objeto tú mismo y usando el contenedor para crear tu objeto o puedes usar strings para definir la clase y el método a llamar. Puedes ir a la página de [Inyección de Dependencias](/learn/dependency-injection-container) para más información. Aquí hay un ejemplo rápido: @@ -265,7 +326,7 @@ class Greeting // Ve la página de Inyección de Dependencias para más información sobre PSR-11 $dice = new \Dice\Dice(); -// ¡No olvides reasignar la variable con '$dice = '!!!!! +// No olvides reasignar la variable con '$dice = '!!!!! $dice = $dice->addRule('flight\database\PdoWrapper', [ 'shared' => true, 'constructParams' => [ @@ -280,7 +341,7 @@ Flight::registerContainerHandler(function($class, $params) use ($dice) { return $dice->create($class, $params); }); -// Rutas como normal +// Rutas como de costumbre Flight::route('/hello/@id', [ 'Greeting', 'hello' ]); // o Flight::route('/hello/@id', 'Greeting->hello'); @@ -311,14 +372,14 @@ Flight::route('/user/*', function () { Ahora se recomienda usar [middleware](/learn/middleware) para manejar casos de uso complejos como este. ### Alias de Ruta -Al asignar un alias a una ruta, puedes llamar más tarde a ese alias en tu aplicación dinámicamente para que se genere más adelante en tu código (ej: un enlace en una plantilla HTML, o generando una URL de redirección). +Al asignar un alias a una ruta, puedes llamar después a ese alias en tu app dinámicamente para que se genere más tarde en tu código (ej: un enlace en una plantilla HTML, o generando una URL de redirección). ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); // o Flight::route('/users/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view'); -// más adelante en el código en algún lugar +// más tarde en el código en algún lugar class UserController { public function update() { @@ -332,7 +393,7 @@ class UserController { ``` -Esto es especialmente útil si tu URL sucede cambiar. En el ejemplo anterior, digamos que los usuarios se movieron a `/admin/users/@id` en su lugar. +Esto es especialmente útil si tu URL sucede cambiar. En el ejemplo anterior, digamos que users se movió a `/admin/users/@id` en su lugar. Con el alias en su lugar para la ruta, ya no necesitas encontrar todas las URLs antiguas en tu código y cambiarlas porque el alias ahora devolverá `/admin/users/5` como en el ejemplo anterior. El alias de ruta aún funciona en grupos también: @@ -346,7 +407,7 @@ Flight::group('/users', function() { ``` ### Inspeccionando Información de Ruta -Si quieres inspeccionar la información de la ruta coincidente, hay 2 formas en que puedes hacerlo: +Si quieres inspeccionar la información de la ruta coincidente, hay 2 formas de hacerlo: 1. Puedes usar una propiedad `executedRoute` en el objeto `Flight::router()`. 2. Puedes solicitar que el objeto ruta se pase a tu devolución de llamada pasando `true` como el tercer parámetro en el método ruta. El objeto ruta siempre será el último parámetro pasado a tu función de devolución de llamada. @@ -368,7 +429,7 @@ Flight::route('/', function() { // Contiene el contenido de cualquier '*' usado en el patrón de URL $route->splat; - // Muestra la ruta de la url....si realmente la necesitas + // Muestra la ruta de URL....si realmente la necesitas $route->pattern; // Muestra qué middleware está asignado a esto @@ -379,7 +440,7 @@ Flight::route('/', function() { }); ``` -> **Nota:** La propiedad `executedRoute` solo se establecerá después de que una ruta haya sido ejecutada. Si intentas acceder a ella antes de que una ruta haya sido ejecutada, será `NULL`. También puedes usar executedRoute en [middleware](/learn/middleware) ¡así! +> **Nota:** La propiedad `executedRoute` solo se establecerá después de que una ruta haya sido ejecutada. Si intentas acceder a ella antes de que una ruta haya sido ejecutada, será `NULL`. También puedes usar executedRoute en [middleware](/learn/middleware)! #### Pasar `true` a la definición de ruta ```php @@ -396,7 +457,7 @@ Flight::route('/', function(\flight\net\Route $route) { // Contiene el contenido de cualquier '*' usado en el patrón de URL $route->splat; - // Muestra la ruta de la url....si realmente la necesitas + // Muestra la ruta de URL....si realmente la necesitas $route->pattern; // Muestra qué middleware está asignado a esto @@ -551,7 +612,7 @@ class UsersController Hay algunas opciones para configurar las rutas de recursos. -##### Alias Base +##### Base de Alias Puedes configurar el `aliasBase`. Por defecto, el alias es la última parte de la URL especificada. Por ejemplo `/users/` resultaría en un `aliasBase` de `users`. Cuando se crean estas rutas, los alias son `users.index`, `users.create`, etc. Si quieres cambiar el alias, establece el `aliasBase` al valor que quieras. @@ -584,18 +645,17 @@ También puedes especificar middleware para ejecutarse en cada una de las rutas Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]); ``` -### Respuestas de Streaming +### Respuestas en Streaming Ahora puedes transmitir respuestas al cliente usando `stream()` o `streamWithHeaders()`. Esto es útil para enviar archivos grandes, procesos de larga duración o generar respuestas grandes. -Transmitir una ruta se maneja un poco diferente a una ruta regular. +Transmitir una ruta se maneja un poco diferente que una ruta regular. -> **Nota:** Las respuestas de streaming solo están disponibles si tienes [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) establecido en `false`. +> **Nota:** Las respuestas en streaming solo están disponibles si tienes [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) establecido en `false`. -#### Stream con Encabezados Manuales +#### Streaming con Encabezados Manuales -Puedes transmitir una respuesta al cliente usando el método `stream()` en una ruta. Si -haces esto, debes establecer todos los encabezados a mano antes de que salgas cualquier cosa al cliente. +Puedes transmitir una respuesta al cliente usando el método `stream()` en una ruta. Si haces esto, debes establecer todos los encabezados a mano antes de que salgas cualquier cosa al cliente. Esto se hace con la función php `header()` o el método `Flight::response()->setRealHeader()`. ```php @@ -632,7 +692,7 @@ Flight::route('/@filename', function($filename) { })->stream(); ``` -#### Stream con Encabezados +#### Streaming con Encabezados También puedes usar el método `streamWithHeaders()` para establecer los encabezados antes de comenzar a transmitir. @@ -668,25 +728,24 @@ Flight::route('/stream-users', function() { ``` ## Ver También -- [Middleware](/learn/middleware) - Usando middleware con rutas para autenticación, registro, etc. +- [Middleware](/learn/middleware) - Usando middleware con rutas para autenticación, logging, etc. - [Inyección de Dependencias](/learn/dependency-injection-container) - Simplificando la creación y gestión de objetos en rutas. - [¿Por qué un Framework?](/learn/why-frameworks) - Entendiendo los beneficios de usar un framework como Flight. -- [Extendiendo](/learn/extending) - Cómo extender Flight con tu propia funcionalidad incluyendo el método `notFound`. +- [Extensión](/learn/extending) - Cómo extender Flight con tu propia funcionalidad incluyendo el método `notFound`. - [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - Función PHP para coincidencia de expresiones regulares. ## Solución de Problemas -- Los parámetros de ruta se coinciden por orden, no por nombre. Asegúrate de que el orden de los parámetros de la devolución de llamada coincida con la definición de la ruta. +- Los parámetros de ruta se coinciden por orden, no por nombre. Asegúrate de que el orden de los parámetros de devolución de llamada coincida con la definición de ruta. - Usar `Flight::get()` no define una ruta; usa `Flight::route('GET /...')` para enrutamiento o el contexto del objeto Router en grupos (ej. `$router->get(...)`). -- La propiedad executedRoute solo se establece después de que una ruta se ejecuta; es NULL antes de la ejecución. -- El streaming requiere que la funcionalidad de búfer de salida legacy de Flight esté desactivada (`flight.v2.output_buffering = false`). +- La propiedad executedRoute solo se establece después de que una ruta se ejecute; es NULL antes de la ejecución. +- El streaming requiere que la funcionalidad de buffering de salida legacy de Flight esté deshabilitada (`flight.v2.output_buffering = false`). - Para inyección de dependencias, solo ciertas definiciones de ruta soportan instanciación basada en contenedor. ### 404 No Encontrado o Comportamiento de Ruta Inesperado -Si estás viendo un error 404 No Encontrado (pero juras por tu vida que realmente está allí y no es un error tipográfico), esto en realidad podría ser un problema con que devuelvas un valor en tu punto final de ruta en lugar de solo hacer eco de él. La razón para esto es intencional pero podría sorprender a algunos desarrolladores. +Si estás viendo un error 404 No Encontrado (pero juras por tu vida que realmente está ahí y no es un error tipográfico) esto en realidad podría ser un problema con que devuelves un valor en tu punto final de ruta en lugar de solo hacer eco de él. La razón para esto es intencional pero podría sorprender a algunos desarrolladores. ```php - Flight::route('/hello', function(){ // Esto podría causar un error 404 No Encontrado return 'Hello World'; @@ -696,12 +755,11 @@ Flight::route('/hello', function(){ Flight::route('/hello', function(){ echo 'Hello World'; }); - ``` -La razón para esto es debido a un mecanismo especial incorporado en el router que maneja la salida de retorno como una señal para "ir a la siguiente ruta". +La razón para esto es por un mecanismo especial incorporado en el router que maneja la salida de retorno como una señal para "ir a la siguiente ruta". Puedes ver el comportamiento documentado en la sección de [Enrutamiento](/learn/routing#passing). ## Registro de Cambios - v3: Agregado enrutamiento de recursos, alias de ruta y soporte de streaming, grupos de rutas y soporte de middleware. -- v1: La gran mayoría de características básicas disponibles. \ No newline at end of file +- v1: La vasta mayoría de características básicas disponibles. \ No newline at end of file diff --git a/content/v3/fr/awesome-plugins/apm.md b/content/v3/fr/awesome-plugins/apm.md index 77d5bd6b..df1da64c 100644 --- a/content/v3/fr/awesome-plugins/apm.md +++ b/content/v3/fr/awesome-plugins/apm.md @@ -1,41 +1,43 @@ -# Documentation APM FlightPHP +# Documentation FlightPHP APM -Bienvenue dans FlightPHP APM—votre coach personnel pour les performances de votre application ! Ce guide est votre feuille de route pour configurer, utiliser et maîtriser la surveillance des performances des applications (APM) avec FlightPHP. Que vous chassiez les demandes lentes ou que vous souhaitiez vous amuser avec des graphiques de latence, nous vous couvrons. Rendons votre application plus rapide, vos utilisateurs plus heureux et vos sessions de débogage plus faciles ! +Bienvenue dans FlightPHP APM—votre coach personnel de performance pour votre application ! Ce guide est votre feuille de route pour configurer, utiliser et maîtriser la Surveillance de la Performance des Applications (APM) avec FlightPHP. Que vous traquiez des requêtes lentes ou que vous souhaitiez simplement vous enthousiasmer pour des graphiques de latence, nous avons tout ce qu'il vous faut. Rendons votre application plus rapide, vos utilisateurs plus heureux, et vos sessions de débogage plus fluides ! + +Découvrez une [démo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) du tableau de bord pour le site Flight Docs. ![FlightPHP APM](/images/apm.png) -## Pourquoi APM Importe +## Pourquoi l'APM est important -Imaginez ceci : votre application est un restaurant animé. Sans moyen de suivre le temps des commandes ou d'identifier où la cuisine ralentit, vous devinez pourquoi les clients partent mécontents. APM est votre sous-chef—il surveille chaque étape, des demandes entrantes aux requêtes de base de données, et signale tout ce qui vous ralentit. Les pages lentes font perdre des utilisateurs (les études disent que 53 % rebondissent si un site prend plus de 3 secondes à charger !), et APM vous aide à détecter ces problèmes *avant* qu'ils ne fassent mal. C'est une tranquillité d'esprit proactive—moins de moments « pourquoi cela ne fonctionne pas ? », plus de victoires « regardez comme cela fonctionne bien ! ». +Imaginez ceci : votre application est un restaurant animé. Sans moyen de suivre la durée des commandes ou les endroits où la cuisine ralentit, vous devinez pourquoi les clients partent mécontents. L'APM est votre sous-chef—il surveille chaque étape, des requêtes entrantes aux requêtes de base de données, et signale tout ce qui vous ralentit. Les pages lentes font fuir les utilisateurs (des études disent que 53 % rebondissent si un site prend plus de 3 secondes à charger !), et l'APM vous aide à attraper ces problèmes *avant* qu'ils ne piquent. C'est une tranquillité d'esprit proactive—moins de moments « pourquoi c'est cassé ? », plus de victoires « regardez comme ça tourne bien ! ». ## Installation -Démarrez avec Composer : +Commencez avec Composer : ```bash composer require flightphp/apm ``` Vous aurez besoin de : -- **PHP 7.4+** : Garde la compatibilité avec les distributions Linux LTS tout en supportant le PHP moderne. +- **PHP 7.4+** : Nous garde compatible avec les distributions Linux LTS tout en supportant le PHP moderne. - **[FlightPHP Core](https://github.com/flightphp/core) v3.15+** : Le framework léger que nous boostons. -## Bases de Données Prises en Charge +## Bases de données prises en charge FlightPHP APM prend actuellement en charge les bases de données suivantes pour stocker les métriques : -- **SQLite3** : Simple, basé sur un fichier, et idéal pour le développement local ou les petites applications. Option par défaut dans la plupart des configurations. -- **MySQL/MariaDB** : Idéal pour les projets plus importants ou les environnements de production où vous avez besoin d'un stockage robuste et scalable. +- **SQLite3** : Simple, basée sur fichier, et idéale pour le développement local ou les petites applications. Option par défaut dans la plupart des configurations. +- **MySQL/MariaDB** : Idéale pour les projets plus grands ou les environnements de production où vous avez besoin d'un stockage robuste et évolutif. Vous pouvez choisir le type de base de données lors de l'étape de configuration (voir ci-dessous). Assurez-vous que votre environnement PHP a les extensions nécessaires installées (par exemple, `pdo_sqlite` ou `pdo_mysql`). -## Pour Commencer +## Pour commencer -Voici votre guide étape par étape pour l'Awesome APM : +Voici votre guide étape par étape vers l'excellence APM : ### 1. Enregistrer l'APM -Ajoutez cela dans votre `index.php` ou un fichier `services.php` pour commencer à suivre : +Ajoutez ceci dans votre `index.php` ou un fichier `services.php` pour commencer le suivi : ```php use flight\apm\logger\LoggerFactory; @@ -45,35 +47,35 @@ $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); $Apm = new Apm($ApmLogger); $Apm->bindEventsToFlightInstance($app); -// Si vous ajoutez une connexion de base de données -// Doit être PdoWrapper ou PdoQueryCapture des extensions Tracy +// Si vous ajoutez une connexion à la base de données +// Doit être PdoWrapper ou PdoQueryCapture de Tracy Extensions $pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True requis pour activer le suivi dans l'APM. $Apm->addPdoConnection($pdo); ``` -**Qu'est-ce qui se passe ici ?** -- `LoggerFactory::create()` récupère votre configuration (plus de détails bientôt) et configure un journaliseur—SQLite par défaut. -- `Apm` est la star—il écoute les événements de Flight (demandes, routes, erreurs, etc.) et collecte les métriques. +**Que se passe-t-il ici ?** +- `LoggerFactory::create()` récupère votre configuration (plus de détails bientôt) et configure un logger—SQLite par défaut. +- `Apm` est la star—il écoute les événements de Flight (requêtes, routes, erreurs, etc.) et collecte les métriques. - `bindEventsToFlightInstance($app)` lie tout à votre application Flight. **Astuce Pro : Échantillonnage** -Si votre application est occupée, journaliser *toutes* les demandes pourrait surcharger les choses. Utilisez un taux d'échantillonnage (0.0 à 1.0) : +Si votre application est occupée, logger *chaque* requête pourrait surcharger les choses. Utilisez un taux d'échantillonnage (0.0 à 1.0) : ```php -$Apm = new Apm($ApmLogger, 0.1); // Journalise 10 % des demandes +$Apm = new Apm($ApmLogger, 0.1); // Logue 10 % des requêtes ``` -Cela garde les performances fluides tout en vous donnant des données solides. +Cela garde les performances vives tout en vous donnant des données solides. -### 2. Configurez-le +### 2. Le configurer -Exécutez cela pour créer votre `.runway-config.json` : +Exécutez ceci pour créer votre `.runway-config.json` : ```bash php vendor/bin/runway apm:init ``` -**Qu'est-ce que cela fait ?** +**Que fait ceci ?** - Lance un assistant qui demande d'où viennent les métriques brutes (source) et où vont les données traitées (destination). - Par défaut, c'est SQLite—par exemple, `sqlite:/tmp/apm_metrics.sqlite` pour la source, une autre pour la destination. - Vous obtiendrez une configuration comme : @@ -88,12 +90,12 @@ php vendor/bin/runway apm:init } ``` -> Ce processus demandera aussi si vous voulez exécuter les migrations pour cette configuration. Si c'est votre première installation, la réponse est oui. +> Ce processus demandera également si vous voulez exécuter les migrations pour cette configuration. Si vous l'installez pour la première fois, la réponse est oui. **Pourquoi deux emplacements ?** -Les métriques brutes s'accumulent rapidement (pensez à des journaux non filtrés). Le worker les traite dans une destination structurée pour le tableau de bord. Cela garde les choses organisées ! +Les métriques brutes s'accumulent vite (pensez à des logs non filtrés). Le worker les traite en une destination structurée pour le tableau de bord. Cela garde les choses en ordre ! -### 3. Traitez les Métriques avec le Worker +### 3. Traiter les métriques avec le Worker Le worker transforme les métriques brutes en données prêtes pour le tableau de bord. Exécutez-le une fois : @@ -101,22 +103,22 @@ Le worker transforme les métriques brutes en données prêtes pour le tableau d php vendor/bin/runway apm:worker ``` -**Qu'est-ce qu'il fait ?** -- Lit à partir de votre source (par exemple, `apm_metrics.sqlite`). +**Que fait-il ?** +- Lit depuis votre source (par exemple, `apm_metrics.sqlite`). - Traite jusqu'à 100 métriques (taille de lot par défaut) dans votre destination. - S'arrête quand c'est fait ou s'il n'y a plus de métriques. -**Gardez-le en Marche** +**Le garder en cours** Pour les applications en direct, vous voudrez un traitement continu. Voici vos options : - **Mode Daemon** : ```bash php vendor/bin/runway apm:worker --daemon ``` - S'exécute pour toujours, traitant les métriques au fur et à mesure. Idéal pour le dev ou les petites configurations. + Tourne indéfiniment, traitant les métriques au fur et à mesure. Idéal pour le dev ou les petites configurations. - **Crontab** : - Ajoutez cela à votre crontab (`crontab -e`) : + Ajoutez ceci à votre crontab (`crontab -e`) : ```bash * * * * * php /path/to/project/vendor/bin/runway apm:worker ``` @@ -127,22 +129,22 @@ Pour les applications en direct, vous voudrez un traitement continu. Voici vos o ```bash tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon - # Ctrl+B, puis D pour détacher ; `tmux attach -t apm-worker` pour reconnecter + # Ctrl+B, puis D pour détacher ; `tmux attach -t apm-worker` pour se reconnecter ``` - Le garde en marche même si vous vous déconnectez. + Le garde en cours même si vous vous déconnectez. -- **Ajustements Personnalisés** : +- **Ajustements personnalisés** : ```bash php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 ``` - `--batch_size 50` : Traite 50 métriques à la fois. - - `--max_messages 1000` : Arrête après 1000 métriques. + - `--max_messages 1000` : S'arrête après 1000 métriques. - `--timeout 300` : Quitte après 5 minutes. **Pourquoi s'embêter ?** -Sans le worker, votre tableau de bord est vide. C'est le pont entre les journaux bruts et les insights actionnables. +Sans le worker, votre tableau de bord est vide. C'est le pont entre les logs bruts et les insights actionnables. -### 4. Lancez le Tableau de Bord +### 4. Lancer le Tableau de Bord Voyez les signes vitaux de votre application : @@ -152,55 +154,55 @@ php vendor/bin/runway apm:dashboard **Qu'est-ce que c'est ?** - Lance un serveur PHP à `http://localhost:8001/apm/dashboard`. -- Affiche les journaux de demandes, les routes lentes, les taux d'erreurs, et plus. +- Affiche les logs de requêtes, les routes lentes, les taux d'erreur, et plus. -**Personnalisez-le** : +**Le personnaliser** : ```bash php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php ``` -- `--host 0.0.0.0` : Accessible depuis n'importe quelle IP (pratique pour la visualisation à distance). +- `--host 0.0.0.0` : Accessible depuis n'importe quel IP (pratique pour la visualisation à distance). - `--port 8080` : Utilisez un port différent si 8001 est pris. -- `--php-path` : Indiquez le chemin vers PHP s'il n'est pas dans votre PATH. +- `--php-path` : Pointez vers PHP s'il n'est pas dans votre PATH. Ouvrez l'URL dans votre navigateur et explorez ! #### Mode Production -Pour la production, vous devrez peut-être essayer quelques techniques pour faire fonctionner le tableau de bord, car il y a probablement des pare-feu et d'autres mesures de sécurité en place. Voici quelques options : +Pour la production, vous devrez peut-être essayer quelques techniques pour faire tourner le tableau de bord, car il y a probablement des pare-feu et d'autres mesures de sécurité en place. Voici quelques options : -- **Utiliser un Reverse Proxy** : Configurez Nginx ou Apache pour rediriger les demandes vers le tableau de bord. -- **Tunnel SSH** : Si vous pouvez SSH sur le serveur, utilisez `ssh -L 8080:localhost:8001 youruser@yourserver` pour tunneler le tableau de bord vers votre machine locale. -- **VPN** : Si votre serveur est derrière un VPN, connectez-vous et accédez directement au tableau de bord. -- **Configurer le Pare-feu** : Ouvrez le port 8001 pour votre IP ou le réseau du serveur (ou le port que vous avez défini). -- **Configurer Apache/Nginx** : Si vous avez un serveur web devant votre application, configurez-le pour un domaine ou un sous-domaine. Si vous faites cela, définissez le répertoire racine sur `/path/to/your/project/vendor/flightphp/apm/dashboard`. +- **Utiliser un Reverse Proxy** : Configurez Nginx ou Apache pour rediriger les requêtes vers le tableau de bord. +- **Tunnel SSH** : Si vous pouvez vous connecter en SSH au serveur, utilisez `ssh -L 8080:localhost:8001 youruser@yourserver` pour tunneler le tableau de bord vers votre machine locale. +- **VPN** : Si votre serveur est derrière un VPN, connectez-vous-y et accédez directement au tableau de bord. +- **Configurer le Pare-feu** : Ouvrez le port 8001 pour votre IP ou le réseau du serveur. (ou quel que soit le port que vous avez défini). +- **Configurer Apache/Nginx** : Si vous avez un serveur web devant votre application, vous pouvez le configurer pour un domaine ou un sous-domaine. Si vous faites cela, vous définirez la racine des documents à `/path/to/your/project/vendor/flightphp/apm/dashboard` -#### Voulez un Tableau de Bord Différent ? +#### Voulez-vous un tableau de bord différent ? -Vous pouvez construire votre propre tableau de bord si vous voulez ! Regardez le répertoire vendor/flightphp/apm/src/apm/presenter pour des idées sur la façon de présenter les données pour votre propre tableau de bord ! +Vous pouvez construire votre propre tableau de bord si vous le souhaitez ! Regardez le répertoire vendor/flightphp/apm/src/apm/presenter pour des idées sur la façon de présenter les données pour votre propre tableau de bord ! ## Fonctionnalités du Tableau de Bord Le tableau de bord est votre quartier général APM—voici ce que vous verrez : -- **Journal des Demandes** : Chaque demande avec horodatage, URL, code de réponse et temps total. Cliquez sur « Détails » pour les middleware, requêtes et erreurs. -- **Demandes les Plus Lentes** : Les 5 principales demandes qui prennent du temps (par exemple, « /api/heavy » à 2,5 s). -- **Routes les Plus Lentes** : Les 5 routes par temps moyen—super pour repérer les patterns. -- **Taux d'Erreurs** : Pourcentage de demandes qui échouent (par exemple, 2,3 % de 500s). -- **Percentiles de Latence** : 95e (p95) et 99e (p99) temps de réponse—connaissez vos scénarios les plus mauvais. -- **Graphique des Codes de Réponse** : Visualisez les 200s, 404s, 500s au fil du temps. -- **Requêtes/Middleware Longues** : Les 5 principaux appels de base de données lents et les couches de middleware. -- **Taux de Succès/Miss du Cache** : À quelle fréquence votre cache sauve la mise. +- **Log des Requêtes** : Chaque requête avec horodatage, URL, code de réponse, et temps total. Cliquez sur « Détails » pour les middlewares, requêtes, et erreurs. +- **Requêtes les Plus Lentes** : Top 5 des requêtes qui monopolisent le temps (par exemple, « /api/heavy » à 2,5 s). +- **Routes les Plus Lentes** : Top 5 des routes par temps moyen—idéal pour repérer les patterns. +- **Taux d'Erreur** : Pourcentage de requêtes qui échouent (par exemple, 2,3 % de 500). +- **Percentiles de Latence** : 95e (p95) et 99e (p99) temps de réponse—connaissez vos scénarios pires cas. +- **Graphique des Codes de Réponse** : Visualisez les 200, 404, 500 au fil du temps. +- **Requêtes/Middlewares Longs** : Top 5 des appels de base de données lents et des couches de middleware. +- **Taux de Cache Hit/Miss** : À quelle fréquence votre cache sauve la mise. **Extras** : -- Filtrez par « Dernière Heure », « Dernier Jour » ou « Dernière Semaine ». +- Filtrez par « Dernière Heure », « Dernier Jour », ou « Dernière Semaine ». - Basculez en mode sombre pour ces sessions tardives. **Exemple** : -Une demande à `/users` pourrait montrer : +Une requête vers `/users` pourrait montrer : - Temps Total : 150 ms - Middleware : `AuthMiddleware->handle` (50 ms) - Requête : `SELECT * FROM users` (80 ms) -- Cache : Succès sur `user_list` (5 ms) +- Cache : Hit sur `user_list` (5 ms) ## Ajout d'Événements Personnalisés @@ -216,8 +218,8 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ])); ``` -**Où cela apparaît-il ?** -Dans les détails de demande du tableau de bord sous « Événements Personnalisés »—expandable avec un formatage JSON joli. +**Où apparaît-il ?** +Dans les détails de requête du tableau de bord sous « Événements Personnalisés »—extensible avec un formatage JSON joli. **Cas d'Utilisation** : ```php @@ -242,15 +244,15 @@ $pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // < $Apm->addPdoConnection($pdo); ``` -**Ce que Vous Obtenez** : +**Ce Que Vous Obtenez** : - Texte de la requête (par exemple, `SELECT * FROM users WHERE id = ?`) - Temps d'exécution (par exemple, 0,015 s) - Nombre de lignes (par exemple, 42) -**Avertissement** : -- **Optionnel** : Sautez cela si vous n'avez pas besoin de suivi de BD. -- **Seulement PdoWrapper** : Le PDO de base n'est pas encore accroché—restons à l'écoute ! -- **Avertissement de Performance** : Journaliser chaque requête sur un site chargé en BD peut ralentir les choses. Utilisez l'échantillonnage (`$Apm = new Apm($ApmLogger, 0.1)`) pour alléger la charge. +**Attention** : +- **Optionnel** : Sautez ceci si vous n'avez pas besoin de suivi DB. +- **PdoWrapper Seulement** : Le PDO de base n'est pas encore accroché—restez à l'écoute ! +- **Avertissement de Performance** : Logger chaque requête sur un site lourd en DB peut ralentir les choses. Utilisez l'échantillonnage (`$Apm = new Apm($ApmLogger, 0.1)`) pour alléger la charge. **Exemple de Sortie** : - Requête : `SELECT name FROM products WHERE price > 100` @@ -261,48 +263,48 @@ $Apm->addPdoConnection($pdo); Ajustez le worker à votre goût : -- `--timeout 300` : Arrête après 5 minutes—bon pour les tests. +- `--timeout 300` : S'arrête après 5 minutes—bon pour les tests. - `--max_messages 500` : Limite à 500 métriques—le garde fini. - `--batch_size 200` : Traite 200 à la fois—équilibre vitesse et mémoire. -- `--daemon` : S'exécute sans arrêt—idéal pour la surveillance en direct. +- `--daemon` : Tourne non-stop—idéal pour la surveillance en direct. **Exemple** : ```bash php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ``` -S'exécute pendant une heure, traitant 100 métriques à la fois. +Tourne pendant une heure, traitant 100 métriques à la fois. -## ID de Demande dans l'Application +## ID de Requête dans l'Application -Chaque demande a un ID de demande unique pour le suivi. Vous pouvez utiliser cet ID dans votre application pour corréler les journaux et les métriques. Par exemple, vous pouvez ajouter l'ID de demande à une page d'erreur : +Chaque requête a un ID de requête unique pour le suivi. Vous pouvez utiliser cet ID dans votre application pour corréler les logs et les métriques. Par exemple, vous pouvez ajouter l'ID de requête à une page d'erreur : ```php Flight::map('error', function($message) { - // Obtenez l'ID de demande à partir de l'en-tête de réponse X-Flight-Request-Id + // Obtenez l'ID de requête depuis l'en-tête de réponse X-Flight-Request-Id $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - // De plus, vous pourriez le récupérer à partir de la variable Flight - // Cette méthode ne fonctionnera pas bien sur Swoole ou d'autres plateformes asynchrones. + // De plus, vous pourriez le récupérer depuis la variable Flight + // Cette méthode ne fonctionnera pas bien sur swoole ou d'autres plateformes asynchrones. // $requestId = Flight::get('apm.request_id'); - echo "Error: $message (Request ID: $requestId)"; + echo "Erreur : $message (ID de Requête : $requestId)"; }); ``` ## Mise à Niveau -Si vous mettez à niveau vers une version plus récente de l'APM, il y a une chance que des migrations de base de données doivent être exécutées. Vous pouvez le faire en exécutant la commande suivante : +Si vous mettez à niveau vers une version plus récente de l'APM, il est possible qu'il y ait des migrations de base de données à exécuter. Vous pouvez le faire en exécutant la commande suivante : ```bash php vendor/bin/runway apm:migrate ``` -Ceci exécutera toutes les migrations nécessaires pour mettre à jour le schéma de base de données vers la dernière version. +Ceci exécutera toutes les migrations nécessaires pour mettre à jour le schéma de la base de données vers la dernière version. -**Note :** Si votre base de données APM est grande, ces migrations peuvent prendre du temps. Vous voudrez peut-être exécuter cette commande pendant les heures creuses. +**Note :** Si votre base de données APM est grande en taille, ces migrations pourraient prendre un certain temps à s'exécuter. Vous pourriez vouloir exécuter cette commande pendant les heures creuses. -## Purge des Données Anciennes +## Purgage des Anciennes Données -Pour garder votre base de données propre, vous pouvez purger les données anciennes. C'est particulièrement utile si vous exécutez une application occupée et que vous voulez garder la taille de la base de données gérable. +Pour garder votre base de données en ordre, vous pouvez purger les anciennes données. C'est particulièrement utile si vous exécutez une application occupée et que vous voulez garder la taille de la base de données gérable. Vous pouvez le faire en exécutant la commande suivante : ```bash @@ -317,19 +319,19 @@ Ceci supprimera toutes les données plus anciennes que 7 jours de la base de don ## Dépannage -Coincé ? Essayez ces astuces : +Coincé ? Essayez ceci : -- **Pas de Données sur le Tableau de Bord ?** - - Le worker est-il en marche ? Vérifiez `ps aux | grep apm:worker`. - - Les chemins de configuration correspondent ? Vérifiez que les DSNs dans `.runway-config.json` pointent vers des fichiers réels. +- **Pas de Données dans le Tableau de Bord ?** + - Le worker tourne-t-il ? Vérifiez `ps aux | grep apm:worker`. + - Les chemins de configuration correspondent-ils ? Vérifiez que les DSN dans `.runway-config.json` pointent vers des fichiers réels. - Exécutez `php vendor/bin/runway apm:worker` manuellement pour traiter les métriques en attente. - **Erreurs du Worker ?** - Jetez un œil à vos fichiers SQLite (par exemple, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Vérifiez les journaux PHP pour les traces de pile. + - Vérifiez les logs PHP pour les traces de pile. - **Le Tableau de Bord Ne Démarre Pas ?** - - Le port 8001 est-il utilisé ? Utilisez `--port 8080`. + - Port 8001 utilisé ? Utilisez `--port 8080`. - PHP non trouvé ? Utilisez `--php-path /usr/bin/php`. - Pare-feu bloquant ? Ouvrez le port ou utilisez `--host localhost`. @@ -337,9 +339,9 @@ Coincé ? Essayez ces astuces : - Baissez le taux d'échantillonnage : `$Apm = new Apm($ApmLogger, 0.05)` (5 %). - Réduisez la taille du lot : `--batch_size 20`. -- **Ne Suit Pas les Exceptions/Erreurs ?** +- **Pas de Suivi des Exceptions/Erreurs ?** - Si vous avez [Tracy](https://tracy.nette.org/) activé pour votre projet, il remplacera la gestion d'erreurs de Flight. Vous devrez désactiver Tracy et vous assurer que `Flight::set('flight.handle_errors', true);` est défini. -- **Ne Suit Pas les Requêtes de Base de Données ?** - - Assurez-vous d'utiliser `PdoWrapper` pour vos connexions de base de données. - - Assurez-vous que le dernier argument dans le constructeur est `true`. \ No newline at end of file +- **Pas de Suivi des Requêtes de Base de Données ?** + - Assurez-vous d'utiliser `PdoWrapper` pour vos connexions à la base de données. + - Assurez-vous de passer `true` comme dernier argument dans le constructeur. \ No newline at end of file diff --git a/content/v3/fr/learn/ai.md b/content/v3/fr/learn/ai.md index 671608db..86131c21 100644 --- a/content/v3/fr/learn/ai.md +++ b/content/v3/fr/learn/ai.md @@ -2,7 +2,7 @@ ## Aperçu -Flight facilite le renforcement de vos projets PHP avec des outils alimentés par l'IA et des flux de travail de développement modernes. Avec des commandes intégrées pour se connecter aux fournisseurs de LLM (Large Language Model) et générer des instructions de codage IA spécifiques au projet, Flight vous aide, vous et votre équipe, à tirer le meilleur parti des assistants IA comme GitHub Copilot, Cursor et Windsurf. +Flight facilite le renforcement de vos projets PHP avec des outils alimentés par l'IA et des flux de travail modernes pour les développeurs. Avec des commandes intégrées pour se connecter aux fournisseurs de LLM (Large Language Model) et générer des instructions de codage IA spécifiques au projet, Flight vous aide, vous et votre équipe, à tirer le meilleur parti des assistants IA comme GitHub Copilot, Cursor et Windsurf. ## Compréhension @@ -15,9 +15,9 @@ Ces fonctionnalités sont intégrées au CLI principal de Flight et au projet de ## Utilisation de Base -### 1. Configuration des Identifiants LLM +### Configuration des Identifiants LLM -La commande `ai:init` vous guide pour connecter votre projet à un fournisseur de LLM. +La commande `ai:init` vous guide à travers la connexion de votre projet à un fournisseur de LLM. ```bash php runway ai:init @@ -40,7 +40,7 @@ Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: Credentials saved to .runway-creds.json ``` -### 2. Génération d'Instructions IA Spécifiques au Projet +### Génération d'Instructions IA Spécifiques au Projet La commande `ai:generate-instructions` vous aide à créer ou mettre à jour des instructions pour les assistants de codage IA, adaptées à votre projet. @@ -48,7 +48,7 @@ La commande `ai:generate-instructions` vous aide à créer ou mettre à jour des php runway ai:generate-instructions ``` -Vous répondrez à quelques questions sur votre projet (description, base de données, templating, sécurité, taille de l'équipe, etc.). Flight utilise votre fournisseur de LLM pour générer des instructions, puis les écrit dans : +Vous répondrez à quelques questions sur votre projet (description, base de données, templating, sécurité, taille de l'équipe, etc.). Flight utilise votre fournisseur de LLM pour générer les instructions, puis les écrit dans : - `.github/copilot-instructions.md` (pour GitHub Copilot) - `.cursor/rules/project-overview.mdc` (pour Cursor) - `.windsurfrules` (pour Windsurf) diff --git a/content/v3/fr/learn/requests.md b/content/v3/fr/learn/requests.md index f4de2ac8..4ca2e569 100644 --- a/content/v3/fr/learn/requests.md +++ b/content/v3/fr/learn/requests.md @@ -11,13 +11,13 @@ $request = Flight::request(); ## Compréhension -Les requêtes HTTP sont l'un des aspects essentiels à comprendre concernant le cycle de vie HTTP. Un utilisateur effectue une action sur un navigateur web ou un client HTTP, et ils envoient une série d'en-têtes, un corps, une URL, etc. vers votre projet. Vous pouvez capturer ces en-têtes (la langue du navigateur, le type de compression qu'ils peuvent gérer, l'agent utilisateur, etc.) et capturer le corps et l'URL qui sont envoyés à votre application Flight. Ces requêtes sont essentielles pour que votre application comprenne quoi faire ensuite. +Les requêtes HTTP sont l'un des aspects fondamentaux à comprendre concernant le cycle de vie HTTP. Un utilisateur effectue une action dans un navigateur web ou un client HTTP, et ils envoient une série d'en-têtes, un corps, une URL, etc. vers votre projet. Vous pouvez capturer ces en-têtes (la langue du navigateur, le type de compression qu'ils peuvent gérer, l'agent utilisateur, etc.) et capturer le corps et l'URL qui sont envoyés à votre application Flight. Ces requêtes sont essentielles pour que votre application comprenne quoi faire ensuite. ## Utilisation de base -PHP dispose de plusieurs super-globales incluant `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES`, et `$_COOKIE`. Flight abstrait ces éléments en [Collections](/learn/collections) pratiques. Vous pouvez accéder aux propriétés `query`, `data`, `cookies`, et `files` en tant que tableaux ou objets. +PHP possède plusieurs super-globales incluant `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES`, et `$_COOKIE`. Flight abstrait ces éléments en [Collections](/learn/collections) pratiques. Vous pouvez accéder aux propriétés `query`, `data`, `cookies`, et `files` en tant que tableaux ou objets. -> **Note :** Il est **FORTEMENT** déconseillé d'utiliser ces super-globales dans votre projet et elles doivent être référencées via l'objet `request()`. +> **Note :** Il est **TRÈS** déconseillé d'utiliser ces super-globales dans votre projet et elles doivent être référencées via l'objet `request()`. > **Note :** Il n'y a pas d'abstraction disponible pour `$_ENV`. @@ -61,7 +61,7 @@ Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; // ou $savedLogin = Flight::request()->cookies->myLoginCookie; - // vérifier s'il est vraiment sauvegardé ou non et si oui, les connecter automatiquement + // vérifier s'il est vraiment sauvegardé ou non et s'il l'est, les connecter automatiquement if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -73,7 +73,7 @@ Pour de l'aide sur la définition de nouvelles valeurs de cookies, voir [overclo ### `$_SERVER` -Il existe un raccourci disponible pour accéder au tableau `$_SERVER` via la méthode `getVar()` : +Il existe un raccourci pour accéder au tableau `$_SERVER` via la méthode `getVar()` : ```php @@ -97,7 +97,7 @@ Voir [Uploaded File Handler](/learn/uploaded-file) pour plus d'informations. _v3.12.0_ -Vous pouvez traiter les téléchargements de fichiers en utilisant le framework avec certaines méthodes d'aide. Cela se résume essentiellement à extraire les données du fichier de la requête, et à le déplacer vers un nouvel emplacement. +Vous pouvez traiter les téléchargements de fichiers en utilisant le framework avec quelques méthodes d'aide. Cela se résume essentiellement à extraire les données de fichier de la requête et à les déplacer vers un nouvel emplacement. ```php Flight::route('POST /upload', function(){ @@ -120,7 +120,7 @@ Flight::route('POST /upload', function(){ }); ``` -> **Note de sécurité :** Validez et nettoyez toujours les entrées utilisateur, surtout lors du traitement de téléchargements de fichiers. Validez toujours le type d'extensions que vous autorisez à être téléchargées, mais vous devriez également valider les "magic bytes" du fichier pour vous assurer qu'il s'agit réellement du type de fichier que l'utilisateur prétend qu'il est. Il existe des [articles](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [et](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [bibliothèques](https://github.com/RikudouSage/MimeTypeDetector) disponibles pour vous aider avec cela. +> **Note de sécurité :** Validez et nettoyez toujours les entrées utilisateur, surtout lors du traitement des téléchargements de fichiers. Validez toujours le type d'extensions que vous autorisez à être téléchargées, mais vous devriez également valider les "octets magiques" du fichier pour vous assurer qu'il s'agit réellement du type de fichier que l'utilisateur prétend qu'il est. Il existe des [articles](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [et](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [bibliothèques](https://github.com/RikudouSage/MimeTypeDetector) disponibles pour vous aider avec cela. ### Corps de la requête @@ -149,7 +149,7 @@ Vous pouvez accéder aux en-têtes de requête en utilisant la méthode `getHead ```php -// Peut-être que vous avez besoin de l'en-tête Authorization +// Peut-être avez-vous besoin de l'en-tête Authorization $host = Flight::request()->getHeader('Authorization'); // ou $host = Flight::request()->header('Authorization'); @@ -165,14 +165,14 @@ $headers = Flight::request()->headers(); Vous pouvez accéder à la méthode de requête en utilisant la propriété `method` ou la méthode `getMethod()` : ```php -$method = Flight::request()->method; // en réalité peuplé par getMethod() +$method = Flight::request()->method; // en fait peuplée par getMethod() $method = Flight::request()->getMethod(); ``` **Note :** La méthode `getMethod()` récupère d'abord la méthode à partir de `$_SERVER['REQUEST_METHOD']`, puis elle peut être écrasée par `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` si elle existe ou `$_REQUEST['_method']` si elle existe. -## Propriétés de l'objet Requête +## Propriétés de l'objet requête L'objet requête fournit les propriétés suivantes : @@ -181,25 +181,25 @@ L'objet requête fournit les propriétés suivantes : - **base** - Le sous-répertoire parent de l'URL - **method** - La méthode de requête (GET, POST, PUT, DELETE) - **referrer** - L'URL de référence -- **ip** - L'adresse IP du client +- **ip** - Adresse IP du client - **ajax** - Si la requête est une requête AJAX - **scheme** - Le protocole du serveur (http, https) -- **user_agent** - Les informations du navigateur +- **user_agent** - Informations du navigateur - **type** - Le type de contenu - **length** - La longueur du contenu -- **query** - Les paramètres de la chaîne de requête -- **data** - Les données POST ou les données JSON -- **cookies** - Les données de cookies -- **files** - Les fichiers téléchargés +- **query** - Paramètres de la chaîne de requête +- **data** - Données de publication ou données JSON +- **cookies** - Données de cookies +- **files** - Fichiers téléchargés - **secure** - Si la connexion est sécurisée -- **accept** - Les paramètres HTTP accept -- **proxy_ip** - L'adresse IP proxy du client. Parcourt le tableau `$_SERVER` pour `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` dans cet ordre. +- **accept** - Paramètres d'acceptation HTTP +- **proxy_ip** - Adresse IP proxy du client. Parcourt le tableau `$_SERVER` pour `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` dans cet ordre. - **host** - Le nom d'hôte de la requête - **servername** - Le SERVER_NAME à partir de `$_SERVER` -## Méthodes d'aide pour les URL +## Méthodes d'aide -Il existe quelques méthodes d'aide pour assembler des parties d'une URL pour votre commodité. +Il existe quelques méthodes d'aide pour assembler des parties d'une URL ou gérer certains en-têtes. ### URL complète @@ -209,7 +209,6 @@ Vous pouvez accéder à l'URL complète de la requête en utilisant la méthode $url = Flight::request()->getFullUrl(); // https://example.com/some/path?foo=bar ``` - ### URL de base Vous pouvez accéder à l'URL de base en utilisant la méthode `getBaseUrl()` : @@ -230,16 +229,40 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` +## Négociation des types d'acceptation de contenu + +_v3.17.2_ + +Vous pouvez utiliser la méthode `negotiateContentType()` pour déterminer le meilleur type de contenu à répondre en fonction de l'en-tête `Accept` envoyé par le client. + +```php + +// Exemple d'en-tête Accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// Ci-dessous, définissez ce que vous supportez. +$availableTypes = ['application/json', 'application/xml']; +$typeToServe = Flight::request()->negotiateContentType($availableTypes); +if ($typeToServe === 'application/json') { + // Servir une réponse JSON +} elseif ($typeToServe === 'application/xml') { + // Servir une réponse XML +} else { + // Par défaut, utiliser autre chose ou lever une erreur +} +``` + +> **Note :** Si aucun des types disponibles n'est trouvé dans l'en-tête `Accept`, la méthode retournera `null`. S'il n'y a pas d'en-tête `Accept` défini, la méthode retournera le premier type dans le tableau `$availableTypes`. + ## Voir aussi -- [Routing](/learn/routing) - Voir comment mapper les routes aux contrôleurs et rendre les vues. +- [Routing](/learn/routing) - Voir comment mapper des routes vers des contrôleurs et rendre des vues. - [Responses](/learn/responses) - Comment personnaliser les réponses HTTP. - [Why a Framework?](/learn/why-frameworks) - Comment les requêtes s'intègrent dans le tableau global. - [Collections](/learn/collections) - Travailler avec des collections de données. -- [Uploaded File Handler](/learn/uploaded-file) - Gérer les téléchargements de fichiers. +- [Uploaded File Handler](/learn/uploaded-file) - Gestion des téléchargements de fichiers. ## Dépannage - `request()->ip` et `request()->proxy_ip` peuvent être différents si votre serveur web est derrière un proxy, un équilibreur de charge, etc. ## Journal des modifications +- v3.17.2 - Ajout de negotiateContentType() - v3.12.0 - Ajout de la capacité à gérer les téléchargements de fichiers via l'objet requête. - v1.0 - Version initiale. \ No newline at end of file diff --git a/content/v3/fr/learn/responses.md b/content/v3/fr/learn/responses.md index 0217b306..b2d7d6f1 100644 --- a/content/v3/fr/learn/responses.md +++ b/content/v3/fr/learn/responses.md @@ -2,20 +2,20 @@ ## Aperçu -Flight aide à générer une partie des en-têtes de réponse pour vous, mais vous conservez la plupart des contrôles sur ce que vous renvoyez à l'utilisateur. La plupart du temps, vous accéderez directement à l'objet `response()`, mais Flight dispose de quelques méthodes d'assistance pour définir certains en-têtes de réponse pour vous. +Flight aide à générer une partie des en-têtes de réponse pour vous, mais vous conservez la plupart du contrôle sur ce que vous renvoyez à l'utilisateur. La plupart du temps, vous accédez directement à l'objet `response()`, mais Flight propose des méthodes d'assistance pour définir certains en-têtes de réponse pour vous. -## Compréhension +## Comprendre Après que l'utilisateur a envoyé sa [requête](/learn/requests) à votre application, vous devez générer une réponse appropriée pour lui. Ils vous ont envoyé des informations comme la langue qu'ils préfèrent, s'ils peuvent gérer certains types de compression, leur agent utilisateur, etc., et après avoir traité tout cela, il est temps de leur renvoyer une réponse appropriée. Cela peut consister à définir des en-têtes, à sortir un corps de HTML ou de JSON pour eux, ou à les rediriger vers une page. ## Utilisation de base -### Envoi d'un corps de réponse +### Envoyer un corps de réponse -Flight utilise `ob_start()` pour tamponner la sortie. Cela signifie que vous pouvez utiliser `echo` ou `print` pour envoyer une réponse à l'utilisateur et Flight la capturera et la renverra à l'utilisateur avec les en-têtes appropriés. +Flight utilise `ob_start()` pour tamponner la sortie. Cela signifie que vous pouvez utiliser `echo` ou `print` pour envoyer une réponse à l'utilisateur et que Flight la capturera et la renverra à l'utilisateur avec les en-têtes appropriés. ```php -// Ceci enverra "Hello, World!" au navigateur de l'utilisateur +// Cela enverra "Hello, World!" au navigateur de l'utilisateur Flight::route('/', function() { echo "Hello, World!"; }); @@ -29,12 +29,12 @@ Flight::route('/', function() { En alternative, vous pouvez appeler la méthode `write()` pour ajouter au corps également. ```php -// Ceci enverra "Hello, World!" au navigateur de l'utilisateur +// Cela enverra "Hello, World!" au navigateur de l'utilisateur Flight::route('/', function() { - // verbeux, mais fait le travail parfois quand vous en avez besoin + // verbeux, mais cela fait le travail parfois quand vous en avez besoin Flight::response()->write("Hello, World!"); - // si vous voulez récupérer le corps que vous avez défini à ce moment + // si vous voulez récupérer le corps que vous avez défini à ce stade // vous pouvez le faire comme ceci $body = Flight::response()->getBody(); }); @@ -42,7 +42,7 @@ Flight::route('/', function() { ### JSON -Flight fournit un support pour l'envoi de réponses JSON et JSONP. Pour envoyer une réponse JSON, vous +Flight fournit un support pour envoyer des réponses JSON et JSONP. Pour envoyer une réponse JSON, vous passez des données à encoder en JSON : ```php @@ -65,15 +65,15 @@ Vous pouvez également passer un code de statut en tant que deuxième argument : Flight::json(['id' => 123], 201); ``` -#### JSON avec impression jolie +#### JSON avec impression formatée -Vous pouvez également passer un argument à la dernière position pour activer l'impression jolie : +Vous pouvez également passer un argument à la dernière position pour activer l'impression formatée : ```php Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT); ``` -#### Changement de l'ordre des arguments JSON +#### Changer l'ordre des arguments JSON `Flight::json()` est une méthode très ancienne, mais l'objectif de Flight est de maintenir la compatibilité arrière pour les projets. C'est en fait très simple si vous voulez refaire l'ordre des arguments pour utiliser une syntaxe plus simple, @@ -82,11 +82,11 @@ vous pouvez simplement remapper la méthode JSON [comme n'importe quelle autre m ```php Flight::map('json', function($data, $code = 200, $options = 0) { - // maintenant vous n'avez pas à utiliser `true, 'utf-8'` lors de l'utilisation de la méthode json() ! + // maintenant vous n'avez pas besoin de `true, 'utf-8'` quand vous utilisez la méthode json() ! Flight::_json($data, $code, true, 'utf-8', $options); } -// Et maintenant elle peut être utilisée comme ceci +// Et maintenant cela peut être utilisé comme ceci Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT); ``` @@ -102,10 +102,10 @@ et arrêter l'exécution. ```php Flight::route('/users', function() { $authorized = someAuthorizationCheck(); - // Vérifiez si l'utilisateur est autorisé + // Vérifier si l'utilisateur est autorisé if($authorized === false) { Flight::jsonHalt(['error' => 'Unauthorized'], 401); - // pas de exit; nécessaire ici. + // pas de sortie ; nécessaire ici. } // Continuer avec le reste de la route @@ -117,7 +117,7 @@ Avant v3.10.0, vous deviez faire quelque chose comme ceci : ```php Flight::route('/users', function() { $authorized = someAuthorizationCheck(); - // Vérifiez si l'utilisateur est autorisé + // Vérifier si l'utilisateur est autorisé if($authorized === false) { Flight::halt(401, json_encode(['error' => 'Unauthorized'])); } @@ -126,7 +126,7 @@ Flight::route('/users', function() { }); ``` -### Effacement d'un corps de réponse +### Effacer un corps de réponse Si vous voulez effacer le corps de réponse, vous pouvez utiliser la méthode `clearBody` : @@ -142,7 +142,7 @@ Flight::route('/', function() { Le cas d'utilisation ci-dessus n'est probablement pas courant, cependant il pourrait être plus courant si cela était utilisé dans un [middleware](/learn/middleware). -### Exécution d'un rappel sur le corps de réponse +### Exécuter un rappel sur le corps de réponse Vous pouvez exécuter un rappel sur le corps de réponse en utilisant la méthode `addResponseBodyCallback` : @@ -153,13 +153,13 @@ Flight::route('/users', function() { Flight::render('users_table', ['users' => $users]); }); -// Ceci gzippira toutes les réponses pour n'importe quelle route +// Cela gzippera toutes les réponses pour n'importe quelle route Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); ``` -Vous pouvez ajouter plusieurs rappels et ils seront exécutés dans l'ordre où ils ont été ajoutés. Comme cela peut accepter n'importe quel [appelable](https://www.php.net/manual/en/language.types.callable.php), il peut accepter un tableau de classe `[ $class, 'method' ]`, une closure `$strReplace = function($body) { str_replace('hi', 'there', $body); };`, ou un nom de fonction `'minify'` si vous aviez une fonction pour minifier votre code html par exemple. +Vous pouvez ajouter plusieurs rappels et ils seront exécutés dans l'ordre où ils ont été ajoutés. Comme cela peut accepter n'importe quel [appelable](https://www.php.net/manual/en/language.types.callable.php), il peut accepter un tableau de classe `[ $class, 'method' ]`, une closure `$strReplace = function($body) { str_replace('hi', 'there', $body); };`, ou un nom de fonction `'minify'` si vous aviez une fonction pour minifier votre code HTML par exemple. **Note :** Les rappels de route ne fonctionneront pas si vous utilisez l'option de configuration `flight.v2.output_buffering`. @@ -173,7 +173,7 @@ Flight::route('/users', function() { $users = $db->fetchAll("SELECT * FROM users"); Flight::render('users_table', ['users' => $users]); - // Ceci gzippira seulement la réponse pour cette route + // Cela gzippera seulement la réponse pour cette route Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); @@ -182,20 +182,20 @@ Flight::route('/users', function() { #### Option Middleware -Vous pouvez également utiliser [middleware](/learn/middleware) pour appliquer le rappel à toutes les routes via middleware : +Vous pouvez également utiliser le [middleware](/learn/middleware) pour appliquer le rappel à toutes les routes via le middleware : ```php // MinifyMiddleware.php class MinifyMiddleware { public function before() { - // Appliquez le rappel ici sur l'objet response(). + // Appliquer le rappel ici sur l'objet response(). Flight::response()->addResponseBodyCallback(function($body) { return $this->minify($body); }); } protected function minify(string $body): string { - // minifiez le corps d'une manière ou d'une autre + // minifier le corps d'une manière ou d'une autre return $body; } } @@ -229,12 +229,12 @@ Si vous voulez obtenir le code de statut actuel, vous pouvez utiliser la méthod Flight::response()->status(); // 200 ``` -### Définition d'un en-tête de réponse +### Définir un en-tête de réponse Vous pouvez définir un en-tête tel que le type de contenu de la réponse en utilisant la méthode `header` : ```php -// Ceci enverra "Hello, World!" au navigateur de l'utilisateur en texte brut +// Cela enverra "Hello, World!" au navigateur de l'utilisateur en texte brut Flight::route('/', function() { Flight::response()->header('Content-Type', 'text/plain'); // ou @@ -246,7 +246,7 @@ Flight::route('/', function() { ### Redirection Vous pouvez rediriger la requête actuelle en utilisant la méthode `redirect()` et en passant -une nouvelle URL : +un nouvel URL : ```php Flight::route('/login', function() { @@ -259,7 +259,7 @@ Flight::route('/login', function() { return; // ceci est nécessaire pour que la fonctionnalité ci-dessous ne s'exécute pas } - // ajoutez le nouvel utilisateur... + // ajouter le nouvel utilisateur... Flight::db()->runQuery("INSERT INTO users ...."); Flight::redirect('/admin/dashboard'); }); @@ -272,7 +272,7 @@ code personnalisé : Flight::redirect('/new/location', 301); // permanent ``` -### Arrêt de l'exécution de la route +### Arrêter l'exécution de la route Vous pouvez arrêter le framework et sortir immédiatement à n'importe quel point en appelant la méthode `halt` : @@ -286,7 +286,7 @@ Vous pouvez également spécifier un code de statut `HTTP` et un message optionn Flight::halt(200, 'Be right back...'); ``` -L'appel à `halt` rejettera tout contenu de réponse jusqu'à ce point et arrêtera toute exécution. +Appeler `halt` rejettera tout contenu de réponse jusqu'à ce point et arrêtera toute exécution. Si vous voulez arrêter le framework et sortir la réponse actuelle, utilisez la méthode `stop` : ```php @@ -295,15 +295,15 @@ Flight::stop($httpStatusCode = null); > **Note :** `Flight::stop()` a un comportement étrange tel qu'il sortira la réponse mais continuera à exécuter votre script ce qui pourrait ne pas être ce que vous voulez. Vous pouvez utiliser `exit` ou `return` après avoir appelé `Flight::stop()` pour empêcher une exécution supplémentaire, mais il est généralement recommandé d'utiliser `Flight::halt()`. -Ceci sauvegardera la clé et la valeur de l'en-tête dans l'objet de réponse. À la fin du cycle de vie de la requête, +Cela sauvegardera la clé et la valeur de l'en-tête dans l'objet de réponse. À la fin du cycle de vie de la requête, il construira les en-têtes et enverra une réponse. ## Utilisation avancée -### Envoi d'un en-tête immédiatement +### Envoyer un en-tête immédiatement Il peut y avoir des moments où vous devez faire quelque chose de personnalisé avec l'en-tête et vous devez envoyer l'en-tête -sur cette ligne de code même avec laquelle vous travaillez. Si vous définissez une [route streamée](/learn/routing), +sur cette ligne même de code avec laquelle vous travaillez. Si vous définissez une [route streamée](/learn/routing), c'est ce dont vous auriez besoin. Cela est réalisable via `response()->setRealHeader()`. ```php @@ -324,17 +324,17 @@ utilisez pour définir votre fonction de rappel : Flight::jsonp(['id' => 123], 'q'); ``` -Donc, lors d'une requête GET en utilisant `?q=my_func`, vous devriez recevoir la sortie : +Donc, lors de l'envoi d'une requête GET en utilisant `?q=my_func`, vous devriez recevoir la sortie : ```javascript my_func({"id":123}); ``` -Si vous ne passez pas de nom de paramètre de requête, il utilisera par défaut `jsonp`. +Si vous ne passez pas de nom de paramètre de requête, il passera par défaut à `jsonp`. -> **Note :** Si vous utilisez encore des requêtes JSONP en 2025 et au-delà, rejoignez le chat et dites-nous pourquoi ! Nous aimons entendre de bonnes histoires de bataille/horreur ! +> **Note :** Si vous utilisez encore des requêtes JSONP en 2025 et au-delà, rejoignez le chat et dites-nous pourquoi ! Nous adorons entendre de bonnes histoires de batailles/horreurs ! -### Effacement des données de réponse +### Effacer les données de réponse Vous pouvez effacer le corps de réponse et les en-têtes en utilisant la méthode `clear()`. Cela effacera tout en-tête assigné à la réponse, effacera le corps de réponse, et définira le code de statut à `200`. @@ -343,13 +343,12 @@ tout en-tête assigné à la réponse, effacera le corps de réponse, et défini Flight::response()->clear(); ``` -#### Effacement uniquement du corps de réponse +#### Effacer seulement le corps de réponse Si vous voulez seulement effacer le corps de réponse, vous pouvez utiliser la méthode `clearBody()` : ```php -// Ceci gardera toujours les en-têtes définis sur l'objet response(). -// Ceci gardera toujours les en-têtes définis sur l'objet response(). +// Cela gardera toujours les en-têtes définis sur l'objet response(). Flight::response()->clearBody(); ``` @@ -364,13 +363,14 @@ client demandera la même ressource, il sera invité à utiliser sa version mise Si vous voulez mettre en cache toute votre réponse, vous pouvez utiliser la méthode `cache()` et passer le temps de mise en cache. ```php -// Ceci mettra en cache la réponse pendant 5 minutes + +// Cela mettra en cache la réponse pendant 5 minutes Flight::route('/news', function () { Flight::response()->cache(time() + 300); echo 'This content will be cached.'; }); -// En alternative, vous pouvez utiliser une chaîne que vous passeriez +// Alternativement, vous pouvez utiliser une chaîne que vous passeriez // à la méthode strtotime() Flight::route('/news', function () { Flight::response()->cache('+5 minutes'); @@ -380,9 +380,9 @@ Flight::route('/news', function () { ### Last-Modified -Vous pouvez utiliser la méthode `lastModified` et passer un timestamp UNIX pour définir la date +Vous pouvez utiliser la méthode `lastModified` et passer un horodatage UNIX pour définir la date et l'heure à laquelle une page a été modifiée pour la dernière fois. Le client continuera à utiliser son cache jusqu'à -ce que la valeur de dernière modification soit changée. +ce que la valeur de dernière modification change. ```php Flight::route('/news', function () { @@ -407,7 +407,7 @@ Gardez à l'esprit que l'appel à `lastModified` ou `etag` définira et vérifie la valeur de cache. Si la valeur de cache est la même entre les requêtes, Flight enverra immédiatement une réponse `HTTP 304` et arrêtera le traitement. -### Téléchargement d'un fichier +### Télécharger un fichier _v3.12.0_ @@ -416,14 +416,16 @@ Il y a une méthode d'assistance pour streamer un fichier vers l'utilisateur fin ```php Flight::route('/download', function () { Flight::download('/path/to/file.txt'); + // À partir de v3.17.1, vous pouvez spécifier un nom de fichier personnalisé pour le téléchargement + Flight::download('/path/to/file.txt', 'custom_name.txt'); }); ``` ## Voir aussi -- [Routing](/learn/routing) - Comment mapper les routes vers les contrôleurs et rendre les vues. +- [Routing](/learn/routing) - Comment mapper les routes aux contrôleurs et rendre les vues. - [Requests](/learn/requests) - Comprendre comment gérer les requêtes entrantes. - [Middleware](/learn/middleware) - Utiliser le middleware avec les routes pour l'authentification, la journalisation, etc. -- [Why a Framework?](/learn/why-frameworks) - Comprendre les avantages d'utiliser un framework comme Flight. +- [Pourquoi un Framework ?](/learn/why-frameworks) - Comprendre les avantages d'utiliser un framework comme Flight. - [Extending](/learn/extending) - Comment étendre Flight avec votre propre fonctionnalité. ## Dépannage @@ -431,6 +433,7 @@ Flight::route('/download', function () { - `stop()` et `halt()` ne sont pas la même chose. `halt()` arrêtera l'exécution immédiatement, tandis que `stop()` permettra à l'exécution de continuer. ## Journal des modifications +- v3.17.1 - Ajout de `$fileName` à la méthode `downloadFile()`. - v3.12.0 - Ajout de la méthode d'assistance downloadFile. - v3.10.0 - Ajout de `jsonHalt`. - v1.0 - Version initiale. \ No newline at end of file diff --git a/content/v3/fr/learn/routing.md b/content/v3/fr/learn/routing.md index 5d93a37b..fab39a6a 100644 --- a/content/v3/fr/learn/routing.md +++ b/content/v3/fr/learn/routing.md @@ -1,12 +1,12 @@ # Routage ## Aperçu -Le routage dans Flight PHP associe des motifs d'URL à des fonctions de rappel ou des méthodes de classe, permettant un traitement rapide et simple des requêtes. Il est conçu pour un overhead minimal, une utilisation conviviale pour les débutants, et une extensibilité sans dépendances externes. +Le routage dans Flight PHP mappe les motifs d'URL sur des fonctions de rappel ou des méthodes de classe, permettant une gestion rapide et simple des requêtes. Il est conçu pour un impact minimal, une utilisation conviviale pour les débutants, et une extensibilité sans dépendances externes. ## Comprendre -Le routage est le mécanisme central qui connecte les requêtes HTTP à la logique de votre application dans Flight. En définissant des routes, vous spécifiez comment différentes URL déclenchent du code spécifique, que ce soit par des fonctions, des méthodes de classe ou des actions de contrôleur. Le système de routage de Flight est flexible, supportant des motifs basiques, des paramètres nommés, des expressions régulières, et des fonctionnalités avancées comme l'injection de dépendances et le routage de ressources. Cette approche garde votre code organisé et facile à maintenir, tout en restant rapide et simple pour les débutants et extensible pour les utilisateurs avancés. +Le routage est le mécanisme central qui connecte les requêtes HTTP à la logique de votre application dans Flight. En définissant des routes, vous spécifiez comment différentes URL déclenchent du code spécifique, que ce soit via des fonctions, des méthodes de classe, ou des actions de contrôleur. Le système de routage de Flight est flexible, supportant des motifs de base, des paramètres nommés, des expressions régulières, et des fonctionnalités avancées comme l'injection de dépendances et le routage de ressources. Cette approche garde votre code organisé et facile à maintenir, tout en restant rapide et simple pour les débutants et extensible pour les utilisateurs avancés. -> **Note :** Vous voulez en savoir plus sur le routage ? Consultez la page ["pourquoi un framework ?"](https://flightphp.com/learn/why-frameworks) pour une explication plus détaillée. +> **Note :** Vous voulez en savoir plus sur le routage ? Consultez la page ["why a framework?](/learn/why-frameworks)" pour une explication plus détaillée. ## Utilisation de base @@ -77,11 +77,11 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **Note :** Par défaut, lorsqu'un contrôleur est appelé dans le framework, la classe `flight\Engine` est toujours injectée sauf si vous spécifiez autrement via un [conteneur d'injection de dépendances](/learn/dependency-injection-container) +> **Note :** Par défaut, lorsque un contrôleur est appelé dans le framework, la classe `flight\Engine` est toujours injectée sauf si vous spécifiez autrement via un [conteneur d'injection de dépendances](/learn/dependency-injection-container) ### Routage spécifique à la méthode -Par défaut, les motifs de route sont associés à toutes les méthodes de requête. Vous pouvez répondre à des méthodes spécifiques en plaçant un identifiant avant l'URL. +Par défaut, les motifs de route correspondent à toutes les méthodes de requête. Vous pouvez répondre à des méthodes spécifiques en plaçant un identifiant avant l'URL. ```php Flight::route('GET /', function () { @@ -100,7 +100,7 @@ Flight::put('/', function() { /* code */ }); Flight::delete('/', function() { /* code */ }); ``` -Vous pouvez également associer plusieurs méthodes à un seul rappel en utilisant un délimiteur `|` : +Vous pouvez également mapper plusieurs méthodes à un seul rappel en utilisant un délimiteur `|` : ```php Flight::route('GET|POST /', function () { @@ -108,15 +108,47 @@ Flight::route('GET|POST /', function () { }); ``` +### Gestion spéciale pour les requêtes HEAD et OPTIONS + +Flight fournit une gestion intégrée pour les requêtes HTTP `HEAD` et `OPTIONS` : + +#### Requêtes HEAD + +- Les **requêtes HEAD** sont traitées comme des requêtes `GET`, mais Flight supprime automatiquement le corps de la réponse avant de l'envoyer au client. +- Cela signifie que vous pouvez définir une route pour `GET`, et les requêtes HEAD vers la même URL ne renverront que les en-têtes (pas de contenu), comme attendu par les normes HTTP. + +```php +Flight::route('GET /info', function() { + echo 'This is some info!'; +}); +// Une requête HEAD vers /info renverra les mêmes en-têtes, mais pas de corps. +``` + +#### Requêtes OPTIONS + +Les requêtes `OPTIONS` sont automatiquement gérées par Flight pour toute route définie. +- Lorsqu'une requête OPTIONS est reçue, Flight répond avec un statut `204 No Content` et un en-tête `Allow` listant toutes les méthodes HTTP supportées pour cette route. +- Vous n'avez pas besoin de définir une route séparée pour OPTIONS sauf si vous voulez un comportement personnalisé ou modifier la réponse. + +```php +// Pour une route définie comme : +Flight::route('GET|POST /users', function() { /* ... */ }); + +// Une requête OPTIONS vers /users répondra avec : +// +// Status: 204 No Content +// Allow: GET, POST, HEAD, OPTIONS +``` + ### Utiliser l'objet Routeur -De plus, vous pouvez obtenir l'objet Routeur qui dispose de méthodes d'assistance pour vous : +De plus, vous pouvez récupérer l'objet Routeur qui dispose de méthodes d'assistance pour vous : ```php $router = Flight::router(); -// associe toutes les méthodes comme Flight::route() +// mappe toutes les méthodes comme Flight::route() $router->map('/', function() { echo 'hello world!'; }); @@ -143,7 +175,7 @@ Flight::route('/user/[0-9]+', function () { Bien que cette méthode soit disponible, il est recommandé d'utiliser des paramètres nommés, ou des paramètres nommés avec des expressions régulières, car ils sont plus lisibles et plus faciles à maintenir. ### Paramètres nommés -Vous pouvez spécifier des paramètres nommés dans vos routes qui seront passés à votre fonction de rappel. **Ceci est plus pour la lisibilité de la route que pour autre chose. Veuillez voir la section ci-dessous sur une mise en garde importante.** +Vous pouvez spécifier des paramètres nommés dans vos routes qui seront passés à votre fonction de rappel. **Ceci est plus pour la lisibilité de la route que pour toute autre chose. Veuillez voir la section ci-dessous sur l'avertissement important.** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -160,11 +192,11 @@ Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { }); ``` -> **Note :** L'association de groupes regex `()` avec des paramètres positionnels n'est pas prise en charge. Ex : `:'\(` +> **Note :** La correspondance de groupes regex `()` avec des paramètres positionnels n'est pas supportée. Ex : `:'\(` -#### Mise en garde importante +#### Avertissement important -Bien que dans l'exemple ci-dessus, il semble que `@name` soit directement lié à la variable `$name`, ce n'est pas le cas. C'est l'ordre des paramètres dans la fonction de rappel qui détermine ce qui lui est passé. Si vous inversiez l'ordre des paramètres dans la fonction de rappel, les variables seraient également inversées. Voici un exemple : +Bien que dans l'exemple ci-dessus, il semble que `@name` soit directement lié à la variable `$name`, ce n'est pas le cas. L'ordre des paramètres dans la fonction de rappel détermine ce qui lui est passé. Si vous inversiez l'ordre des paramètres dans la fonction de rappel, les variables seraient inversées également. Voici un exemple : ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -172,11 +204,11 @@ Flight::route('/@name/@id', function (string $id, string $name) { }); ``` -Et si vous accédiez à l'URL suivante : `/bob/123`, la sortie serait `hello, 123 (bob)!`. -_Veuillez être prudent_ lorsque vous configurez vos routes et vos fonctions de rappel ! +Et si vous alliez à l'URL suivante : `/bob/123`, la sortie serait `hello, 123 (bob)!`. +_Soyez prudent_ lorsque vous configurez vos routes et vos fonctions de rappel ! ### Paramètres optionnels -Vous pouvez spécifier des paramètres nommés qui sont optionnels pour l'association en enveloppant les segments dans des parenthèses. +Vous pouvez spécifier des paramètres nommés qui sont optionnels pour la correspondance en enveloppant des segments entre parenthèses. ```php Flight::route( @@ -191,10 +223,10 @@ Flight::route( ); ``` -Tout paramètre optionnel qui n'est pas associé sera passé en tant que `NULL`. +Tout paramètre optionnel qui n'est pas correspondant sera passé comme `NULL`. ### Routage avec joker -L'association se fait uniquement sur des segments d'URL individuels. Si vous voulez associer plusieurs segments, vous pouvez utiliser le joker `*`. +La correspondance n'est faite que sur des segments d'URL individuels. Si vous voulez correspondre à plusieurs segments, vous pouvez utiliser le joker `*`. ```php Flight::route('/blog/*', function () { @@ -206,14 +238,14 @@ Pour router toutes les requêtes vers un seul rappel, vous pouvez faire : ```php Flight::route('*', function () { - // Faire quelque chose + // Faites quelque chose }); ``` ### Gestionnaire 404 Non trouvé -Par défaut, si une URL ne peut pas être trouvée, Flight enverra une réponse `HTTP 404 Non trouvé` qui est très simple et basique. -Si vous voulez avoir une réponse 404 plus personnalisée, vous pouvez [associer](/learn/extending) votre propre méthode `notFound` : +Par défaut, si une URL ne peut pas être trouvée, Flight enverra une réponse `HTTP 404 Not Found` qui est très simple et basique. +Si vous voulez une réponse 404 plus personnalisée, vous pouvez [mapper](/learn/extending) votre propre méthode `notFound` : ```php Flight::map('notFound', function() { @@ -221,8 +253,8 @@ Flight::map('notFound', function() { // Vous pourriez aussi utiliser Flight::render() avec un modèle personnalisé. $output = <<Mon 404 Non trouvé personnalisé -

La page que vous avez demandée {$url} n'a pas pu être trouvée.

+

My Custom 404 Not Found

+

The page you have requested {$url} could not be found.

HTML; $this->response() @@ -233,6 +265,35 @@ Flight::map('notFound', function() { }); ``` +### Gestionnaire Méthode non trouvée + +Par défaut, si une URL est trouvée mais que la méthode n'est pas autorisée, Flight enverra une réponse `HTTP 405 Method Not Allowed` qui est très simple et basique (Ex : Method Not Allowed. Allowed Methods are: GET, POST). Elle inclura également un en-tête `Allow` avec les méthodes autorisées pour cette URL. + +Si vous voulez une réponse 405 plus personnalisée, vous pouvez [mapper](/learn/extending) votre propre méthode `methodNotFound` : + +```php +use flight\net\Route; + +Flight::map('methodNotFound', function(Route $route) { + $url = Flight::request()->url; + $methods = implode(', ', $route->methods); + + // Vous pourriez aussi utiliser Flight::render() avec un modèle personnalisé. + $output = <<My Custom 405 Method Not Allowed +

The method you have requested for {$url} is not allowed.

+

Allowed Methods are: {$methods}

+ HTML; + + $this->response() + ->clearBody() + ->status(405) + ->setHeader('Allow', $methods) + ->write($output) + ->send(); +}); +``` + ## Utilisation avancée ### Injection de dépendances dans les routes @@ -253,7 +314,7 @@ class Greeting } public function hello(int $id) { - // faire quelque chose avec $this->pdoWrapper + // do something with $this->pdoWrapper $name = $this->pdoWrapper->fetchField("SELECT name FROM users WHERE id = ?", [ $id ]); echo "Hello, world! My name is {$name}!"; } @@ -296,22 +357,22 @@ Vous pouvez passer l'exécution à la route correspondante suivante en retournan ```php Flight::route('/user/@name', function (string $name) { - // Vérifier une condition + // Vérifiez une condition if ($name !== "Bob") { - // Continuer vers la route suivante + // Continuez à la route suivante return true; } }); Flight::route('/user/*', function () { - // Cela sera appelé + // Ceci sera appelé }); ``` -Il est maintenant recommandé d'utiliser le [middleware](/learn/middleware) pour gérer des cas d'utilisation complexes comme celui-ci. +Il est maintenant recommandé d'utiliser [middleware](/learn/middleware) pour gérer des cas d'utilisation complexes comme celui-ci. ### Aliasing de route -En assignant un alias à une route, vous pouvez plus tard appeler cet alias dans votre application de manière dynamique pour qu'il soit généré plus tard dans votre code (ex : un lien dans un modèle HTML, ou la génération d'une URL de redirection). +En assignant un alias à une route, vous pouvez plus tard appeler cet alias dans votre application de manière dynamique pour qu'il soit généré plus tard dans votre code (ex : un lien dans un modèle HTML, ou générer une URL de redirection). ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); @@ -325,17 +386,17 @@ class UserController { // code pour sauvegarder l'utilisateur... $id = $user['id']; // 5 par exemple - $redirectUrl = Flight::getUrl('user_view', [ 'id' => $id ]); // retournera '/users/5' + $redirectUrl = Flight::getUrl('user_view', [ 'id' => $id ]); // renverra '/users/5' Flight::redirect($redirectUrl); } } ``` -Ceci est particulièrement utile si votre URL change. Dans l'exemple ci-dessus, supposons que les utilisateurs ont été déplacés vers `/admin/users/@id` à la place. -Avec l'aliasing en place pour la route, vous n'avez plus besoin de trouver toutes les anciennes URL dans votre code et de les changer car l'alias retournera maintenant `/admin/users/5` comme dans l'exemple ci-dessus. +Ceci est particulièrement utile si votre URL change. Dans l'exemple ci-dessus, supposons que les utilisateurs ont été déplacés vers `/admin/users/@id` au lieu de cela. +Avec l'aliasing en place pour la route, vous n'avez plus besoin de trouver toutes les anciennes URL dans votre code et de les changer car l'alias renverra maintenant `/admin/users/5` comme dans l'exemple ci-dessus. -L'aliasing de route fonctionne encore dans les groupes : +L'aliasing de route fonctionne encore dans les groupes également : ```php Flight::group('/users', function() { @@ -348,15 +409,15 @@ Flight::group('/users', function() { ### Inspection des informations de route Si vous voulez inspecter les informations de la route correspondante, il y a 2 façons de faire cela : -1. Vous pouvez utiliser la propriété `executedRoute` sur l'objet `Flight::router()`. +1. Vous pouvez utiliser une propriété `executedRoute` sur l'objet `Flight::router()`. 2. Vous pouvez demander que l'objet route soit passé à votre rappel en passant `true` comme troisième paramètre dans la méthode route. L'objet route sera toujours le dernier paramètre passé à votre fonction de rappel. #### `executedRoute` ```php Flight::route('/', function() { $route = Flight::router()->executedRoute; - // Faire quelque chose avec $route - // Tableau des méthodes HTTP associées + // Faites quelque chose avec $route + // Tableau des méthodes HTTP correspondantes $route->methods; // Tableau des paramètres nommés @@ -379,12 +440,12 @@ Flight::route('/', function() { }); ``` -> **Note :** La propriété `executedRoute` ne sera définie qu'après l'exécution d'une route. Si vous essayez d'y accéder avant qu'une route ait été exécutée, elle sera `NULL`. Vous pouvez aussi utiliser executedRoute dans le [middleware](/learn/middleware) ! +> **Note :** La propriété `executedRoute` ne sera définie qu'après qu'une route ait été exécutée. Si vous essayez d'y accéder avant qu'une route ait été exécutée, elle sera `NULL`. Vous pouvez également utiliser executedRoute dans [middleware](/learn/middleware) ! #### Passer `true` à la définition de route ```php Flight::route('/', function(\flight\net\Route $route) { - // Tableau des méthodes HTTP associées + // Tableau des méthodes HTTP correspondantes $route->methods; // Tableau des paramètres nommés @@ -404,7 +465,7 @@ Flight::route('/', function(\flight\net\Route $route) { // Montre l'alias assigné à cette route $route->alias; -}, true);// <-- Ce paramètre true est ce qui rend cela possible +}, true);// <-- Ce paramètre true est ce qui fait que cela arrive ``` ### Groupement de routes et Middleware @@ -460,7 +521,7 @@ $app = Flight::app(); $app->group('/api/v1', function (Router $router) { - // utiliser la variable $router + // utilisez la variable $router $router->get('/users', function () { // Correspond à GET /api/v1/users }); @@ -485,7 +546,7 @@ Flight::group('/api/v1', function () { }, [ MyAuthMiddleware::class ]); // ou [ new MyAuthMiddleware() ] si vous voulez utiliser une instance ``` -Consultez plus de détails sur la page [middleware de groupe](/learn/middleware#grouping-middleware). +Voir plus de détails sur la page [middleware de groupe](/learn/middleware#grouping-middleware). ### Routage de ressources Vous pouvez créer un ensemble de routes pour une ressource en utilisant la méthode `resource`. Cela créera un ensemble de routes pour une ressource qui suit les conventions RESTful. @@ -496,7 +557,7 @@ Pour créer une ressource, faites ceci : Flight::resource('/users', UsersController::class); ``` -Et ce qui se passera en arrière-plan, c'est qu'il créera les routes suivantes : +Et ce qui se passera en arrière-plan est qu'il créera les routes suivantes : ```php [ @@ -545,7 +606,7 @@ class UsersController } ``` -> **Note** : Vous pouvez visualiser les routes nouvellement ajoutées avec `runway` en exécutant `php runway routes`. +> **Note** : Vous pouvez voir les routes nouvellement ajoutées avec `runway` en exécutant `php runway routes`. #### Personnalisation des routes de ressources @@ -554,13 +615,13 @@ Il y a quelques options pour configurer les routes de ressources. ##### Base d'alias Vous pouvez configurer la `aliasBase`. Par défaut, l'alias est la dernière partie de l'URL spécifiée. -Par exemple `/users/` résulterait en une `aliasBase` de `users`. Lorsque ces routes sont créées, les alias sont `users.index`, `users.create`, etc. Si vous voulez changer l'alias, définissez la `aliasBase` à la valeur que vous voulez. +Par exemple, `/users/` résulterait en une `aliasBase` de `users`. Lorsque ces routes sont créées, les alias sont `users.index`, `users.create`, etc. Si vous voulez changer l'alias, définissez la `aliasBase` à la valeur que vous voulez. ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); ``` -##### Seulement et Excepté +##### Only et Except Vous pouvez également spécifier quelles routes vous voulez créer en utilisant les options `only` et `except`. @@ -587,10 +648,10 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid ### Réponses en streaming Vous pouvez maintenant diffuser des réponses au client en utilisant `stream()` ou `streamWithHeaders()`. -Ceci est utile pour envoyer de grands fichiers, des processus à long terme, ou générer de grandes réponses. +Ceci est utile pour envoyer de gros fichiers, des processus à longue durée, ou générer de grandes réponses. Le streaming d'une route est géré un peu différemment d'une route régulière. -> **Note :** Les réponses en streaming ne sont disponibles que si vous avez [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) défini à `false`. +> **Note :** Les réponses en streaming ne sont disponibles que si vous avez [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) défini sur `false`. #### Stream avec en-têtes manuels @@ -606,7 +667,7 @@ Flight::route('/@filename', function($filename) { // évidemment vous devriez sanitiser le chemin et tout ça. $fileNameSafe = basename($filename); - // Si vous avez des en-têtes supplémentaires à définir ici après l'exécution de la route + // Si vous avez des en-têtes supplémentaires à définir ici après que la route ait été exécutée // vous devez les définir avant que quoi que ce soit ne soit échoé. // Ils doivent tous être un appel brut à la fonction header() ou // un appel à Flight::response()->setRealHeader() @@ -620,12 +681,12 @@ Flight::route('/@filename', function($filename) { Flight::halt(404, 'File not found'); } - // définir manuellement la longueur du contenu si vous le souhaitez + // définissez manuellement la longueur du contenu si vous le souhaitez header('Content-Length: '.filesize($filePath)); // ou $response->setRealHeader('Content-Length: '.filesize($filePath)); - // Diffuser le fichier au client pendant qu'il est lu + // Diffusez le fichier au client pendant qu'il est lu readfile($filePath); // C'est la ligne magique ici @@ -658,7 +719,7 @@ Flight::route('/stream-users', function() { } echo '}'; -// C'est ainsi que vous définirez les en-têtes avant de commencer le streaming. +// C'est comme ça que vous définirez les en-têtes avant de commencer le streaming. })->streamWithHeaders([ 'Content-Type' => 'application/json', 'Content-Disposition' => 'attachment; filename="users.json"', @@ -668,14 +729,14 @@ Flight::route('/stream-users', function() { ``` ## Voir aussi -- [Middleware](/learn/middleware) - Utilisation du middleware avec les routes pour l'authentification, la journalisation, etc. -- [Injection de dépendances](/learn/dependency-injection-container) - Simplification de la création et de la gestion d'objets dans les routes. +- [Middleware](/learn/middleware) - Utiliser du middleware avec des routes pour l'authentification, la journalisation, etc. +- [Injection de dépendances](/learn/dependency-injection-container) - Simplifier la création et la gestion d'objets dans les routes. - [Pourquoi un framework ?](/learn/why-frameworks) - Comprendre les avantages d'utiliser un framework comme Flight. - [Extension](/learn/extending) - Comment étendre Flight avec votre propre fonctionnalité incluant la méthode `notFound`. -- [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - Fonction PHP pour l'association d'expressions régulières. +- [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - Fonction PHP pour la correspondance d'expressions régulières. ## Dépannage -- Les paramètres de route sont associés par ordre, pas par nom. Assurez-vous que l'ordre des paramètres du rappel correspond à la définition de la route. +- Les paramètres de route sont correspondus par ordre, pas par nom. Assurez-vous que l'ordre des paramètres du rappel correspond à la définition de la route. - Utiliser `Flight::get()` ne définit pas une route ; utilisez `Flight::route('GET /...')` pour le routage ou le contexte d'objet Routeur dans les groupes (ex. `$router->get(...)`). - La propriété executedRoute n'est définie qu'après l'exécution d'une route ; elle est NULL avant l'exécution. - Le streaming nécessite que la fonctionnalité de mise en tampon de sortie legacy de Flight soit désactivée (`flight.v2.output_buffering = false`). @@ -683,11 +744,9 @@ Flight::route('/stream-users', function() { ### 404 Non trouvé ou comportement de route inattendu -Si vous voyez une erreur 404 Non trouvé (mais vous jurez sur votre vie que c'est vraiment là et que ce n'est pas une faute de frappe), cela pourrait en fait être un problème -avec le fait que vous retournez une valeur dans votre point de terminaison de route au lieu de simplement l'échoer. La raison de cela est intentionnelle mais pourrait surprendre certains développeurs. +Si vous voyez une erreur 404 Non trouvé (mais vous jurez sur votre vie que c'est vraiment là et que ce n'est pas une faute de frappe), cela pourrait en fait être un problème avec le fait que vous retournez une valeur dans votre point de terminaison de route au lieu de juste l'échoer. La raison de cela est intentionnelle mais pourrait surprendre certains développeurs. ```php - Flight::route('/hello', function(){ // Cela pourrait causer une erreur 404 Non trouvé return 'Hello World'; @@ -697,12 +756,11 @@ Flight::route('/hello', function(){ Flight::route('/hello', function(){ echo 'Hello World'; }); - ``` La raison de cela est due à un mécanisme spécial intégré au routeur qui gère la sortie de retour comme un signal pour "aller à la route suivante". Vous pouvez voir le comportement documenté dans la section [Routage](/learn/routing#passing). -## Journal des modifications -- v3 : Ajout du routage de ressources, de l'aliasing de route, du support de streaming, des groupes de routes, et du support de middleware. +## Journal des changements +- v3 : Ajout du routage de ressources, de l'aliasing de route, et du support de streaming, des groupes de routes, et du support de middleware. - v1 : La grande majorité des fonctionnalités de base disponibles. \ No newline at end of file diff --git a/content/v3/id/awesome-plugins/apm.md b/content/v3/id/awesome-plugins/apm.md index d88eb050..0e82137b 100644 --- a/content/v3/id/awesome-plugins/apm.md +++ b/content/v3/id/awesome-plugins/apm.md @@ -1,6206 +1,16 @@ # Dokumentasi FlightPHP APM -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! +Selamat datang di FlightPHP APM—pelatih performa pribadi untuk aplikasi Anda! Panduan ini adalah peta jalan Anda untuk menyiapkan, menggunakan, dan menguasai Application Performance Monitoring (APM) dengan FlightPHP. Baik Anda sedang memburu permintaan lambat atau hanya ingin bersemangat dengan grafik latensi, kami siap membantu. Mari buat aplikasi Anda lebih cepat, pengguna Anda lebih bahagia, dan sesi debugging Anda menjadi mudah! -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week.” -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week.” -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week.” -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week.” -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week.” -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week.” -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week.” -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week.” -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week.” -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week.” -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week”. -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week”. -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week”. -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week”. -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week”. -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week”. -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week”. -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week”. -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! +Lihat [demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) dari dashboard untuk situs Flight Docs. ![FlightPHP APM](/images/apm.png) ## Mengapa APM Penting -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. +Bayangkan ini: aplikasi Anda seperti restoran sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur tersendat, Anda hanya menebak-nebak mengapa pelanggan pergi dengan kesal. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri database, dan menandai apa pun yang memperlambat Anda. Halaman lambat membuat pengguna pergi (studi mengatakan 53% bounce jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah-masalah itu *sebelum* mereka menyakitkan. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?” dan lebih banyak kemenangan “lihat betapa lancarnya ini berjalan!”. -## Pemasangan +## Instalasi Mulai dengan Composer: @@ -6210,405 +20,63 @@ composer require flightphp/apm Anda memerlukan: - **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. +- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Framework ringan yang kami tingkatkan. -## Basis Data yang Didukung +## Database yang Didukung -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: +FlightPHP APM saat ini mendukung database berikut untuk menyimpan metrik: -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. +- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Opsi default di sebagian besar pengaturan. +- **MySQL/MariaDB**: Ideal untuk proyek besar atau lingkungan produksi di mana Anda membutuhkan penyimpanan yang kuat dan skalabel. -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). +Anda dapat memilih jenis database Anda selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terinstal (misalnya, `pdo_sqlite` atau `pdo_mysql`). ## Memulai -Inilah langkah-demi-langkah untuk kehebatan APM: +Berikut langkah demi langkah untuk kehebatan APM: ### 1. Daftarkan APM -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: +Masukkan ini ke dalam file `index.php` atau `services.php` Anda untuk mulai melacak: ```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger +use flight\apm\logger\LoggerFactory; use flight\Apm; -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight +$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); +$Apm = new Apm($ApmLogger); +$Apm->bindEventsToFlightInstance($app); -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy +// Jika Anda menambahkan koneksi database +// Harus berupa PdoWrapper atau PdoQueryCapture dari Tracy Extensions $pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. $Apm->addPdoConnection($pdo); ``` **Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. +- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut nanti) dan menyiapkan logger—SQLite secara default. +- `Apm` adalah bintangnya—ia mendengarkan peristiwa Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. +- `bindEventsToFlightInstance($app)` menghubungkannya semua ke aplikasi Flight Anda. -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): +**Tips Pro: Sampling** +Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani sistem. Gunakan tingkat sampel (0.0 hingga 1.0): ```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan +$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% permintaan ``` Ini menjaga performa tetap cepat sambil tetap memberikan data yang solid. ### 2. Konfigurasikan Itu -Jalankan ini untuk membuat `.runway-config.json`: - -```bash -php vendor/bin/runway apm:init -``` - -**Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). -- Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. -- Anda akan mendapatkan konfigurasi seperti: - ```json - { - "apm": { - "source_type": "sqlite", - "source_db_dsn": "sqlite:/tmp/apm_metrics.sqlite", - "storage_type": "sqlite", - "dest_db_dsn": "sqlite:/tmp/apm_metrics_processed.sqlite" - } - } - ``` - -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. - -**Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! - -### 3. Proses Metrik dengan Worker - -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: - -```bash -php vendor/bin/runway apm:worker -``` - -**Apa yang dilakukannya?** -- Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. - -**Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: - -- **Mode Daemon**: - ```bash - php vendor/bin/runway apm:worker --daemon - ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. - -- **Crontab**: - Tambahkan ini ke crontab Anda (`crontab -e`): - ```bash - * * * * * php /path/to/project/vendor/bin/runway apm:worker - ``` - Berjalan setiap menit—sempurna untuk produksi. - -- **Tmux/Screen**: - Mulai sesi yang dapat dilepas: - ```bash - tmux new -s apm-worker - php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali - ``` - Menjaganya berjalan bahkan jika Anda keluar. - -- **Penyesuaian Kustom**: - ```bash - php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 - ``` - - `--batch_size 50`: Proses 50 metrik sekaligus. - - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. - -**Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. - -### 4. Luncurkan Dasbor - -Lihat vital aplikasi Anda: - -```bash -php vendor/bin/runway apm:dashboard -``` - -**Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. - -**Sesuaikan Itu**: -```bash -php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php -``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. -- `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. - -Kunjungi URL di browser Anda dan jelajahi! - -#### Mode Produksi - -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: - -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. - -#### Ingin dasbor yang berbeda? - -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! - -## Fitur Dasbor - -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: - -- **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. -- **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. -- **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. - -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week”. -- Alihkan mode gelap untuk sesi malam yang larut. - -**Contoh**: -Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms -- Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) - -## Menambahkan Acara Kustom - -Lacak apa saja—seperti panggilan API atau proses pembayaran: - -```php -use flight\apm\CustomEvent; // Impor untuk acara kustom - -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ - 'endpoint' => 'https://api.example.com/users', - 'response_time' => 0.25, - 'status' => 200 -])); -``` - -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. - -**Kasus Penggunaan**: -```php -$start = microtime(true); -$apiResponse = file_get_contents('https://api.example.com/data'); -$app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ - 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, - 'success' => $apiResponse !== false -])); -``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! - -## Pemantauan Basis Data - -Lacak kueri PDO seperti ini: - -```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO - -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang Anda Dapatkan**: -- Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) -- Waktu eksekusi (misalnya, 0.015s) -- Jumlah baris (misalnya, 42) - -**Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. - -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 - -## Opsi Worker - -Sesuaikan worker sesuai keinginan Anda: - -- `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. -- `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. - -**Contoh**: -```bash -php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 -``` -Berjalan selama satu jam, memproses 100 metrik sekaligus. - -## ID Permintaan di Aplikasi - -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: - -```php -Flight::map('error', function($message) { - // Dapatkan ID permintaan dari header respons X-Flight-Request-Id - $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - - // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. - // $requestId = Flight::get('apm.request_id'); - - echo "Error: $message (Request ID: $requestId)"; -}); -``` - -## Meningkatkan - -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:migrate -``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. - -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. - -## Menghapus Data Lama - -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: - -```bash -php vendor/bin/runway apm:purge -``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: - -```bash -php vendor/bin/runway apm:purge --days 7 -``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. - -## Memecahkan Masalah - -Tertahan? Coba ini: - -- **Tidak Ada Data Dasbor?** - - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. - -- **Kesalahan Worker?** - - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Periksa log PHP untuk jejak tumpukan. - -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. - - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - - Firewall memblokir? Buka port atau gunakan `--host localhost`. - -- **Terlalu Lambat?** - - Turunkan tingkat sampel: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Kurangi ukuran batch: `--batch_size 20`. - -- **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. - -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. - - Pastikan Anda membuat argumen terakhir di konstruktor `true`.# Dokumentasi FlightPHP APM - -Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk mengatur, menggunakan, dan menguasai Pemantauan Kinerja Aplikasi (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan yang lambat atau hanya ingin bersemangat dengan grafik latensi, kami sudah menutupinya. Mari buat aplikasi Anda lebih cepat, pengguna lebih bahagia, dan sesi debugging lebih mudah! - -![FlightPHP APM](/images/apm.png) - -## Mengapa APM Penting - -Bayangkan ini: aplikasi Anda seperti restoran yang sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur terganggu, Anda hanya menebak mengapa pelanggan pergi dengan marah. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri basis data, dan menandai apa saja yang memperlambat Anda. Halaman yang lambat kehilangan pengguna (studi mengatakan 53% mundur jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah *sebelum* menyakiti. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?”, lebih banyak kemenangan “lihat betapa licinnya ini berjalan!”. - -## Pemasangan - -Mulai dengan Composer: - -```bash -composer require flightphp/apm -``` - -Anda memerlukan: -- **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Kerangka ringan yang kami tingkatkan. - -## Basis Data yang Didukung - -FlightPHP APM saat ini mendukung basis data berikut untuk menyimpan metrik: - -- **SQLite3**: Sederhana, berbasis file, dan bagus untuk pengembangan lokal atau aplikasi kecil. Pilihan default dalam sebagian besar pengaturan. -- **MySQL/MariaDB**: Ideal untuk proyek yang lebih besar atau lingkungan produksi di mana Anda memerlukan penyimpanan yang kuat dan skalabel. - -Anda dapat memilih tipe basis data selama langkah konfigurasi (lihat di bawah). Pastikan lingkungan PHP Anda memiliki ekstensi yang diperlukan terpasang (misalnya, `pdo_sqlite` atau `pdo_mysql`). - -## Memulai - -Inilah langkah-demi-langkah untuk kehebatan APM: - -### 1. Daftarkan APM - -Masukkan ini ke dalam `index.php` atau file `services.php` untuk mulai melacak: - -```php -use flight\apm\logger\LoggerFactory; // Impor untuk membuat logger -use flight\Apm; - -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Membuat logger dari konfigurasi -$Apm = new Apm($ApmLogger); // Inisialisasi APM -$Apm->bindEventsToFlightInstance($app); // Mengikat acara ke instance Flight - -// Jika Anda menambahkan koneksi basis data -// Harus berupa PdoWrapper atau PdoQueryCapture dari Ekstensi Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. -$Apm->addPdoConnection($pdo); -``` - -**Apa yang terjadi di sini?** -- `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut tentang itu sebentar lagi) dan mengatur logger—SQLite secara default. -- `Apm` adalah bintangnya—ia mendengarkan acara Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. - -**Tip Pro: Pengambilan Sampel** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): - -```php -$Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% dari permintaan -``` - -### 2. Konfigurasikan Itu - -Jalankan ini untuk membuat `.runway-config.json`: +Jalankan ini untuk membuat `.runway-config.json` Anda: ```bash php vendor/bin/runway apm:init ``` **Apa yang dilakukan ini?** -- Meluncurkan wizard yang menanyakan di mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). +- Meluncurkan wizard yang menanyakan dari mana metrik mentah berasal (sumber) dan ke mana data yang diproses pergi (tujuan). - Default adalah SQLite—misalnya, `sqlite:/tmp/apm_metrics.sqlite` untuk sumber, yang lain untuk tujuan. - Anda akan mendapatkan konfigurasi seperti: ```json @@ -6622,14 +90,14 @@ php vendor/bin/runway apm:init } ``` -> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda mengatur ini untuk pertama kalinya, jawabannya adalah ya. +> Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda menyiapkannya untuk pertama kali, jawabannya ya. **Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (pikirkan log yang tidak disaring). Worker memprosesnya menjadi tujuan yang terstruktur untuk dasbor. Menjaga segala sesuatu rapi! +Metrik mentah menumpuk dengan cepat (bayangkan log yang tidak difilter). Worker memprosesnya menjadi tujuan terstruktur untuk dashboard. Menjaga semuanya rapi! ### 3. Proses Metrik dengan Worker -Worker mengubah metrik mentah menjadi data yang siap dasbor. Jalankan sekali: +Worker mengubah metrik mentah menjadi data siap dashboard. Jalankan sekali: ```bash php vendor/bin/runway apm:worker @@ -6638,10 +106,10 @@ php vendor/bin/runway apm:worker **Apa yang dilakukannya?** - Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). - Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. -- Berhenti saat selesai atau jika tidak ada metrik yang tersisa. +- Berhenti ketika selesai atau jika tidak ada metrik yang tersisa. **Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: +Untuk aplikasi langsung, Anda ingin pemrosesan berkelanjutan. Berikut opsi Anda: - **Mode Daemon**: ```bash @@ -6661,9 +129,9 @@ Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: ```bash tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon - # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk menyambung kembali + # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk terhubung kembali ``` - Menjaganya berjalan bahkan jika Anda keluar. + Menjaganya tetap berjalan bahkan jika Anda logout. - **Penyesuaian Kustom**: ```bash @@ -6671,12 +139,12 @@ Untuk aplikasi langsung, Anda ingin pemrosesan kontinu. Berikut pilihan Anda: ``` - `--batch_size 50`: Proses 50 metrik sekaligus. - `--max_messages 1000`: Berhenti setelah 1000 metrik. - - `--timeout 300`: Berhenti setelah 5 menit. + - `--timeout 300`: Keluar setelah 5 menit. **Mengapa repot?** -Tanpa worker, dasbor Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. +Tanpa worker, dashboard Anda kosong. Ini adalah jembatan antara log mentah dan wawasan yang dapat ditindaklanjuti. -### 4. Luncurkan Dasbor +### 4. Luncurkan Dashboard Lihat vital aplikasi Anda: @@ -6686,62 +154,62 @@ php vendor/bin/runway apm:dashboard **Apa ini?** - Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. +- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan lainnya. -**Sesuaikan Itu**: +**Kustomisasi Itu**: ```bash php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php ``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana saja (berguna untuk melihat jarak jauh). -- `--port 8080`: Gunakan port berbeda jika 8001 digunakan. +- `--host 0.0.0.0`: Dapat diakses dari IP mana pun (berguna untuk penampilan jarak jauh). +- `--port 8080`: Gunakan port berbeda jika 8001 sudah digunakan. - `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. -Kunjungi URL di browser Anda dan jelajahi! +Buka URL di browser Anda dan jelajahi! #### Mode Produksi -Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dasbor karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa pilihan: +Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan dashboard karena mungkin ada firewall dan langkah keamanan lainnya. Berikut beberapa opsi: -- **Gunakan Reverse Proxy**: Atur Nginx atau Apache untuk meneruskan permintaan ke dasbor. -- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk mentunnel dasbor ke mesin lokal Anda. -- **VPN**: Jika server Anda di balik VPN, sambungkan ke sana dan akses dasbor langsung. -- **Konfigurasi Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasi Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasikannya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard`. +- **Gunakan Reverse Proxy**: Siapkan Nginx atau Apache untuk meneruskan permintaan ke dashboard. +- **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk menyalurkan dashboard ke mesin lokal Anda. +- **VPN**: Jika server Anda di belakang VPN, hubungkan ke sana dan akses dashboard secara langsung. +- **Konfigurasikan Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). +- **Konfigurasikan Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasinya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard` -#### Ingin dasbor yang berbeda? +#### Ingin dashboard berbeda? -Anda dapat membangun dasbor Anda sendiri jika Anda mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dasbor Anda sendiri! +Anda bisa membangun dashboard sendiri jika mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dashboard Anda sendiri! -## Fitur Dasbor +## Fitur Dashboard -Dasbor adalah markas APM Anda—ini yang akan Anda lihat: +Dashboard adalah markas APM Anda—berikut yang akan Anda lihat: - **Log Permintaan**: Setiap permintaan dengan cap waktu, URL, kode respons, dan waktu total. Klik “Detail” untuk middleware, kueri, dan kesalahan. -- **Permintaan Terlambat**: 5 permintaan teratas yang menghabiskan waktu (misalnya, “/api/heavy” pada 2.5s). -- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk menemukan pola. +- **Permintaan Terlambat**: 5 permintaan teratas yang memakan waktu (misalnya, “/api/heavy” di 2.5s). +- **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk melihat pola. - **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario terburuk Anda. +- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—tahu skenario kasus terburuk Anda. - **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. -- **Kueri/Middleware Panjang**: 5 panggilan basis data lambat dan lapisan middleware teratas. -- **Cache Hit/Miss**: Seberapa sering cache menyelamatkan hari Anda. +- **Kueri/Middleware Panjang**: 5 panggilan database lambat teratas dan lapisan middleware. +- **Cache Hit/Miss**: Seberapa sering cache Anda menyelamatkan hari. -**Ekstra**: -- Filter berdasarkan “Last Hour,” “Last Day,” atau “Last Week”. -- Alihkan mode gelap untuk sesi malam yang larut. +**Tambahan**: +- Filter berdasarkan “Jam Terakhir,” “Hari Terakhir,” atau “Minggu Terakhir.” +- Toggle mode gelap untuk sesi malam larut. **Contoh**: Permintaan ke `/users` mungkin menunjukkan: -- Total Time: 150ms +- Waktu Total: 150ms - Middleware: `AuthMiddleware->handle` (50ms) -- Query: `SELECT * FROM users` (80ms) -- Cache: Hit on `user_list` (5ms) +- Kueri: `SELECT * FROM users` (80ms) +- Cache: Hit pada `user_list` (5ms) -## Menambahkan Acara Kustom +## Menambahkan Peristiwa Kustom Lacak apa saja—seperti panggilan API atau proses pembayaran: ```php -use flight\apm\CustomEvent; // Impor untuk acara kustom +use flight\apm\CustomEvent; $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ 'endpoint' => 'https://api.example.com/users', @@ -6750,8 +218,8 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ])); ``` -**Di mana itu muncul?** -Di detail permintaan dasbor di bawah “Custom Events”—dapat diperluas dengan pemformatan JSON yang bagus. +**Di mana munculnya?** +Di detail permintaan dashboard di bawah “Peristiwa Kustom”—dapat diperluas dengan format JSON yang bagus. **Kasus Penggunaan**: ```php @@ -6763,41 +231,41 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -Sekarang Anda akan melihat jika API itu menarik aplikasi Anda ke bawah! +Sekarang Anda akan melihat jika API itu menyeret aplikasi Anda! -## Pemantauan Basis Data +## Pemantauan Database Lacak kueri PDO seperti ini: ```php -use flight\database\PdoWrapper; // Impor untuk wrapper PDO +use flight\database\PdoWrapper; $pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True diperlukan untuk mengaktifkan pelacakan di APM. $Apm->addPdoConnection($pdo); ``` -**Apa yang Anda Dapatkan**: +**Apa yang Anda Dapat**: - Teks kueri (misalnya, `SELECT * FROM users WHERE id = ?`) - Waktu eksekusi (misalnya, 0.015s) - Jumlah baris (misalnya, 42) **Peringatan**: -- **Opsional**: Lewati ini jika Anda tidak perlu pelacakan DB. -- **Hanya PdoWrapper**: PDO inti belum dihubungkan—tetap ikuti! -- **Peringatan Performa**: Mencatat setiap kueri di situs yang berat DB dapat memperlambat hal-hal. Gunakan pengambilan sampel (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. +- **Opsional**: Lewati ini jika Anda tidak membutuhkan pelacakan DB. +- **Hanya PdoWrapper**: PDO inti belum terhubung—pantau terus! +- **Peringatan Performa**: Mencatat setiap kueri di situs berat DB bisa memperlambat. Gunakan sampling (`$Apm = new Apm($ApmLogger, 0.1)`) untuk meringankan beban. -**Keluaran Contoh**: -- Query: `SELECT name FROM products WHERE price > 100` -- Time: 0.023s -- Rows: 15 +**Contoh Output**: +- Kueri: `SELECT name FROM products WHERE price > 100` +- Waktu: 0.023s +- Baris: 15 ## Opsi Worker Sesuaikan worker sesuai keinginan Anda: - `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. -- `--max_messages 500`: Batas pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Proses 200 sekaligus—menyeimbangkan kecepatan dan memori. +- `--max_messages 500`: Dibatasi pada 500 metrik—menjaganya terbatas. +- `--batch_size 200`: Memproses 200 sekaligus—menyeimbangkan kecepatan dan memori. - `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. **Contoh**: @@ -6808,7 +276,7 @@ Berjalan selama satu jam, memproses 100 metrik sekaligus. ## ID Permintaan di Aplikasi -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk menghubungkan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: +Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk mengkorelasikan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: ```php Flight::map('error', function($message) { @@ -6816,54 +284,54 @@ Flight::map('error', function($message) { $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); // Selain itu, Anda bisa mengambilnya dari variabel Flight - // Metode ini tidak akan berfungsi dengan baik di swoole atau platform async lainnya. + // Metode ini tidak akan bekerja dengan baik di swoole atau platform async lainnya. // $requestId = Flight::get('apm.request_id'); echo "Error: $message (Request ID: $requestId)"; }); ``` -## Meningkatkan +## Upgrade -Jika Anda meningkatkan ke versi APM yang lebih baru, ada kemungkinan migrasi basis data yang perlu dijalankan. Anda dapat melakukannya dengan menjalankan perintah berikut: +Jika Anda sedang meng-upgrade ke versi APM yang lebih baru, ada kemungkinan ada migrasi database yang perlu dijalankan. Anda bisa melakukannya dengan menjalankan perintah berikut: ```bash php vendor/bin/runway apm:migrate ``` -Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema basis data ke versi terbaru. +Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema database ke versi terbaru. -**Catatan:** Jika basis data APM Anda besar, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. +**Catatan:** Jika database APM Anda besar ukurannya, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. -## Menghapus Data Lama +## Membersihkan Data Lama -Untuk menjaga basis data Anda rapi, Anda dapat menghapus data lama. Ini sangat berguna jika Anda menjalankan aplikasi yang sibuk dan ingin menjaga ukuran basis data tetap terkelola. -Anda dapat melakukannya dengan menjalankan perintah berikut: +Untuk menjaga database Anda rapi, Anda bisa membersihkan data lama. Ini sangat berguna jika Anda menjalankan aplikasi sibuk dan ingin menjaga ukuran database tetap terkendali. +Anda bisa melakukannya dengan menjalankan perintah berikut: ```bash php vendor/bin/runway apm:purge ``` -Ini akan menghapus semua data yang lebih lama dari 30 hari dari basis data. Anda dapat menyesuaikan jumlah hari dengan meneruskan nilai berbeda ke opsi `--days`: +Ini akan menghapus semua data lebih tua dari 30 hari dari database. Anda bisa menyesuaikan jumlah hari dengan memberikan nilai berbeda ke opsi `--days`: ```bash php vendor/bin/runway apm:purge --days 7 ``` -Ini akan menghapus semua data yang lebih lama dari 7 hari dari basis data. +Ini akan menghapus semua data lebih tua dari 7 hari dari database. -## Memecahkan Masalah +## Pemecahan Masalah -Tertahan? Coba ini: +Tersangkut? Coba ini: -- **Tidak Ada Data Dasbor?** +- **Tidak Ada Data Dashboard?** - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Jalur konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file asli. - - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik yang tertunda. + - Path konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file nyata. + - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik tertunda. - **Kesalahan Worker?** - Lihat file SQLite Anda (misalnya, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - Periksa log PHP untuk jejak tumpukan. -- **Dasbor Tidak Akan Dimulai?** - - Port 8001 digunakan? Gunakan `--port 8080`. +- **Dashboard Tidak Mau Mulai?** + - Port 8001 sedang digunakan? Gunakan `--port 8080`. - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - Firewall memblokir? Buka port atau gunakan `--host localhost`. @@ -6872,8 +340,8 @@ Tertahan? Coba ini: - Kurangi ukuran batch: `--batch_size 20`. - **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menimpa penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan pastikan `Flight::set('flight.handle_errors', true);` diatur. + - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menggantikan penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan kemudian pastikan bahwa `Flight::set('flight.handle_errors', true);` diatur. -- **Tidak Melacak Kueri Basis Data?** - - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi basis data Anda. +- **Tidak Melacak Kueri Database?** + - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi database Anda. - Pastikan Anda membuat argumen terakhir di konstruktor `true`. \ No newline at end of file diff --git a/content/v3/id/learn/ai.md b/content/v3/id/learn/ai.md index 7e774473..8779ca19 100644 --- a/content/v3/id/learn/ai.md +++ b/content/v3/id/learn/ai.md @@ -2,7 +2,7 @@ ## Gambaran Umum -Flight memudahkan Anda untuk meningkatkan proyek PHP Anda dengan alat berbasis AI dan alur kerja pengembang modern. Dengan perintah bawaan untuk terhubung ke penyedia LLM (Large Language Model) dan menghasilkan instruksi pengkodean AI khusus proyek, Flight membantu Anda dan tim Anda mendapatkan manfaat maksimal dari asisten AI seperti GitHub Copilot, Cursor, dan Windsurf. +Flight memudahkan Anda untuk meningkatkan proyek PHP Anda dengan alat berbasis AI dan alur kerja pengembang modern. Dengan perintah bawaan untuk menghubungkan ke penyedia LLM (Large Language Model) dan menghasilkan instruksi pengkodean AI khusus proyek, Flight membantu Anda dan tim Anda mendapatkan manfaat maksimal dari asisten AI seperti GitHub Copilot, Cursor, dan Windsurf. ## Pemahaman @@ -15,7 +15,7 @@ Fitur-fitur ini dibangun ke dalam CLI inti Flight dan proyek starter resmi [flig ## Penggunaan Dasar -### 1. Menyiapkan Kredensial LLM +### Menyiapkan Kredensial LLM Perintah `ai:init` memandu Anda melalui proses menghubungkan proyek Anda ke penyedia LLM. @@ -40,9 +40,9 @@ Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: Credentials saved to .runway-creds.json ``` -### 2. Menghasilkan Instruksi AI Khusus Proyek +### Menghasilkan Instruksi AI Khusus Proyek -Perintah `ai:generate-instructions` membantu Anda membuat atau memperbarui instruksi untuk asisten pengkodean AI, yang disesuaikan dengan proyek Anda. +Perintah `ai:generate-instructions` membantu Anda membuat atau memperbarui instruksi untuk asisten pengkodean AI, disesuaikan dengan proyek Anda. ```bash php runway ai:generate-instructions diff --git a/content/v3/id/learn/requests.md b/content/v3/id/learn/requests.md index 261c5b3e..16a510e2 100644 --- a/content/v3/id/learn/requests.md +++ b/content/v3/id/learn/requests.md @@ -1,6 +1,6 @@ -# Requests +# Permintaan -## Overview +## Gambaran Umum Flight merangkum permintaan HTTP ke dalam satu objek, yang dapat diakses dengan melakukan: @@ -8,15 +8,15 @@ Flight merangkum permintaan HTTP ke dalam satu objek, yang dapat diakses dengan $request = Flight::request(); ``` -## Understanding +## Pemahaman -Permintaan HTTP adalah salah satu aspek inti yang perlu dipahami tentang siklus hidup HTTP. Pengguna melakukan tindakan pada peramban web atau klien HTTP, dan mereka mengirim serangkaian header, body, URL, dll ke proyek Anda. Anda dapat menangkap header ini (bahasa peramban, jenis kompresi yang dapat ditangani, agen pengguna, dll) dan menangkap body serta URL yang dikirim ke aplikasi Flight Anda. Permintaan ini sangat penting agar aplikasi Anda memahami apa yang harus dilakukan selanjutnya. +Permintaan HTTP adalah salah satu aspek inti yang perlu dipahami tentang siklus hidup HTTP. Pengguna melakukan aksi pada browser web atau klien HTTP, dan mereka mengirim serangkaian header, body, URL, dll ke proyek Anda. Anda dapat menangkap header ini (bahasa browser, jenis kompresi yang dapat ditangani, agen pengguna, dll) dan menangkap body serta URL yang dikirim ke aplikasi Flight Anda. Permintaan ini sangat penting bagi aplikasi Anda untuk memahami apa yang harus dilakukan selanjutnya. -## Basic Usage +## Penggunaan Dasar -PHP memiliki beberapa super globals termasuk `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES`, dan `$_COOKIE`. Flight mengabstraksikan ini menjadi [Collections](/learn/collections) yang berguna. Anda dapat mengakses properti `query`, `data`, `cookies`, dan `files` sebagai array atau objek. +PHP memiliki beberapa super global termasuk `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES`, dan `$_COOKIE`. Flight mengabstraksikan ini menjadi [Collections](/learn/collections) yang berguna. Anda dapat mengakses properti `query`, `data`, `cookies`, dan `files` sebagai array atau objek. -> **Catatan:** Sangat **TIDAK DISARANKAN** menggunakan super globals ini dalam proyek Anda dan sebaiknya dirujuk melalui objek `request()`. +> **Catatan:** Sangat **TIDAK DISARANKAN** untuk menggunakan super global ini di proyek Anda dan seharusnya dirujuk melalui objek `request()`. > **Catatan:** Tidak ada abstraksi yang tersedia untuk `$_ENV`. @@ -28,10 +28,10 @@ Anda dapat mengakses array `$_GET` melalui properti `query`: // GET /search?keyword=something Flight::route('/search', function(){ $keyword = Flight::request()->query['keyword']; - // atau + // or $keyword = Flight::request()->query->keyword; echo "Anda sedang mencari: $keyword"; - // query database atau hal lain dengan $keyword + // query database atau sesuatu yang lain dengan $keyword }); ``` @@ -43,11 +43,11 @@ Anda dapat mengakses array `$_POST` melalui properti `data`: Flight::route('POST /submit', function(){ $name = Flight::request()->data['name']; $email = Flight::request()->data['email']; - // atau + // or $name = Flight::request()->data->name; $email = Flight::request()->data->email; echo "Anda mengirimkan: $name, $email"; - // simpan ke database atau hal lain dengan $name dan $email + // simpan ke database atau sesuatu yang lain dengan $name dan $email }); ``` @@ -58,9 +58,9 @@ Anda dapat mengakses array `$_COOKIE` melalui properti `cookies`: ```php Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; - // atau + // or $savedLogin = Flight::request()->cookies->myLoginCookie; - // periksa apakah benar-benar tersimpan atau tidak dan jika ya, login otomatis + // periksa apakah benar-benar disimpan atau tidak dan jika ya, login otomatis if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -68,7 +68,7 @@ Flight::route('GET /login', function(){ }); ``` -Untuk bantuan dalam menetapkan nilai cookie baru, lihat [overclokk/cookie](/awesome-plugins/php-cookie) +Untuk bantuan tentang pengaturan nilai cookie baru, lihat [overclokk/cookie](/awesome-plugins/php-cookie) ### `$_SERVER` @@ -86,18 +86,17 @@ Anda dapat mengakses file yang diunggah melalui properti `files`: ```php // akses mentah ke properti $_FILES. Lihat di bawah untuk pendekatan yang direkomendasikan $uploadedFile = Flight::request()->files['myFile']; -// atau +// or $uploadedFile = Flight::request()->files->myFile; ``` -Lihat [Uploaded File Handler](/learn/uploaded-file) untuk informasi lebih lanjut. +Lihat [Uploaded File Handler](/learn/uploaded-file) untuk info lebih lanjut. -#### Processing File Uploads +#### Pemrosesan Unggahan File _v3.12.0_ -Anda dapat memproses unggahan file menggunakan framework dengan beberapa metode bantu. Ini pada dasarnya -berkurang untuk menarik data file dari permintaan, dan memindahkannya ke lokasi baru. +Anda dapat memproses unggahan file menggunakan framework dengan beberapa metode pembantu. Pada dasarnya, ini merangkum menarik data file dari permintaan, dan memindahkannya ke lokasi baru. ```php Flight::route('POST /upload', function(){ @@ -120,9 +119,9 @@ Flight::route('POST /upload', function(){ }); ``` -> **Catatan Keamanan:** Selalu validasi dan sanitasi input pengguna, terutama saat berurusan dengan unggahan file. Selalu validasi jenis ekstensi yang akan diizinkan diunggah, tetapi Anda juga harus memvalidasi "magic bytes" file untuk memastikan itu benar-benar jenis file yang diklaim pengguna. Ada [artikel](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [dan](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [library](https://github.com/RikudouSage/MimeTypeDetector) yang tersedia untuk membantu dengan ini. +> **Catatan Keamanan:** Selalu validasi dan sanitasi input pengguna, terutama saat berurusan dengan unggahan file. Selalu validasi jenis ekstensi yang akan diizinkan untuk diunggah, tetapi Anda juga harus memvalidasi "magic bytes" dari file untuk memastikan itu benar-benar jenis file yang diklaim pengguna. Ada [artikel](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [dan](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [library](https://github.com/RikudouSage/MimeTypeDetector) yang tersedia untuk membantu dengan ini. -### Request Body +### Body Permintaan Untuk mendapatkan body permintaan HTTP mentah, misalnya saat berurusan dengan permintaan POST/PUT, Anda dapat melakukan: @@ -134,7 +133,7 @@ Flight::route('POST /users/xml', function(){ }); ``` -### JSON Body +### Body JSON Jika Anda menerima permintaan dengan jenis konten `application/json` dan data contoh `{"id": 123}` itu akan tersedia dari properti `data`: @@ -143,7 +142,7 @@ itu akan tersedia dari properti `data`: $id = Flight::request()->data->id; ``` -### Request Headers +### Header Permintaan Anda dapat mengakses header permintaan menggunakan metode `getHeader()` atau `getHeaders()`: @@ -151,16 +150,16 @@ Anda dapat mengakses header permintaan menggunakan metode `getHeader()` atau `ge // Mungkin Anda membutuhkan header Authorization $host = Flight::request()->getHeader('Authorization'); -// atau +// or $host = Flight::request()->header('Authorization'); // Jika Anda perlu mengambil semua header $headers = Flight::request()->getHeaders(); -// atau +// or $headers = Flight::request()->headers(); ``` -### Request Method +### Metode Permintaan Anda dapat mengakses metode permintaan menggunakan properti `method` atau metode `getMethod()`: @@ -172,9 +171,9 @@ $method = Flight::request()->getMethod(); **Catatan:** Metode `getMethod()` pertama-tama menarik metode dari `$_SERVER['REQUEST_METHOD']`, kemudian dapat ditimpa oleh `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` jika ada atau `$_REQUEST['_method']` jika ada. -## Request Object Properties +## Properti Objek Permintaan -Objek request menyediakan properti berikut: +Objek permintaan menyediakan properti berikut: - **body** - Body permintaan HTTP mentah - **url** - URL yang diminta @@ -184,7 +183,7 @@ Objek request menyediakan properti berikut: - **ip** - Alamat IP klien - **ajax** - Apakah permintaan adalah permintaan AJAX - **scheme** - Protokol server (http, https) -- **user_agent** - Informasi peramban +- **user_agent** - Informasi browser - **type** - Jenis konten - **length** - Panjang konten - **query** - Parameter string query @@ -197,11 +196,11 @@ Objek request menyediakan properti berikut: - **host** - Nama host permintaan - **servername** - SERVER_NAME dari `$_SERVER` -## URL Helper Methods +## Metode Pembantu -Ada beberapa metode bantu untuk menyusun bagian-bagian URL untuk kenyamanan Anda. +Ada beberapa metode pembantu untuk menyusun bagian dari URL, atau berurusan dengan header tertentu. -### Full URL +### URL Lengkap Anda dapat mengakses URL permintaan lengkap menggunakan metode `getFullUrl()`: @@ -209,7 +208,8 @@ Anda dapat mengakses URL permintaan lengkap menggunakan metode `getFullUrl()`: $url = Flight::request()->getFullUrl(); // https://example.com/some/path?foo=bar ``` -### Base URL + +### URL Dasar Anda dapat mengakses URL dasar menggunakan metode `getBaseUrl()`: @@ -220,25 +220,49 @@ $url = Flight::request()->getBaseUrl(); // Perhatikan, tidak ada slash akhir. ``` -## Query Parsing +## Parsing Query -Anda dapat meneruskan URL ke metode `parseQuery()` untuk mengurai string query menjadi array asosiatif: +Anda dapat meneruskan URL ke metode `parseQuery()` untuk mem-parsing string query menjadi array asosiatif: ```php $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` -## See Also +## Negosiasi Jenis Konten Accept + +_v3.17.2_ + +Anda dapat menggunakan metode `negotiateContentType()` untuk menentukan jenis konten terbaik untuk merespons berdasarkan header `Accept` yang dikirim oleh klien. + +```php + +// Contoh header Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// Yang di bawah ini mendefinisikan apa yang Anda dukung. +$availableTypes = ['application/json', 'application/xml']; +$typeToServe = Flight::request()->negotiateContentType($availableTypes); +if ($typeToServe === 'application/json') { + // Layani respons JSON +} elseif ($typeToServe === 'application/xml') { + // Layani respons XML +} else { + // Default ke sesuatu yang lain atau lempar error +} +``` + +> **Catatan:** Jika tidak ada jenis yang tersedia yang ditemukan dalam header `Accept`, metode akan mengembalikan `null`. Jika tidak ada header `Accept` yang didefinisikan, metode akan mengembalikan jenis pertama dalam array `$availableTypes`. + +## Lihat Juga - [Routing](/learn/routing) - Lihat cara memetakan rute ke controller dan render tampilan. - [Responses](/learn/responses) - Cara menyesuaikan respons HTTP. -- [Why a Framework?](/learn/why-frameworks) - Bagaimana permintaan cocok ke dalam gambaran besar. -- [Collections](/learn/collections) - Bekerja dengan koleksi data. +- [Mengapa Framework?](/learn/why-frameworks) - Bagaimana permintaan cocok ke dalam gambaran besar. +- [Collections](/learn/collections) - Bekerja dengan kumpulan data. - [Uploaded File Handler](/learn/uploaded-file) - Menangani unggahan file. -## Troubleshooting +## Pemecahan Masalah - `request()->ip` dan `request()->proxy_ip` bisa berbeda jika webserver Anda berada di belakang proxy, load balancer, dll. ## Changelog -- v3.12.0 - Ditambahkan kemampuan untuk menangani unggahan file melalui objek request. +- v3.17.2 - Menambahkan negotiateContentType() +- v3.12.0 - Menambahkan kemampuan untuk menangani unggahan file melalui objek permintaan. - v1.0 - Rilis awal. \ No newline at end of file diff --git a/content/v3/id/learn/responses.md b/content/v3/id/learn/responses.md index 2abbd9ce..ae1ad5ae 100644 --- a/content/v3/id/learn/responses.md +++ b/content/v3/id/learn/responses.md @@ -1,18 +1,18 @@ # Respons -## Ikhtisar +## Gambaran Umum -Flight membantu menghasilkan sebagian header respons untuk Anda, tetapi Anda memegang sebagian besar kendali atas apa yang Anda kirim kembali ke pengguna. Sebagian besar waktu Anda akan mengakses objek `response()` secara langsung, tetapi Flight memiliki beberapa metode pembantu untuk mengatur sebagian header respons untuk Anda. +Flight membantu menghasilkan sebagian header respons untuk Anda, tetapi Anda memegang sebagian besar kendali atas apa yang Anda kirim kembali ke pengguna. Sebagian besar waktu Anda akan mengakses objek `response()` secara langsung, tetapi Flight memiliki beberapa metode pembantu untuk mengatur beberapa header respons untuk Anda. ## Pemahaman -Setelah pengguna mengirimkan [permintaan](/learn/requests) mereka ke aplikasi Anda, Anda perlu menghasilkan respons yang tepat untuk mereka. Mereka telah mengirimkan informasi seperti bahasa yang mereka sukai, apakah mereka dapat menangani jenis kompresi tertentu, agen pengguna mereka, dll. dan setelah memproses semuanya, saatnya mengirimkan respons yang tepat kembali kepada mereka. Ini bisa berupa pengaturan header, mengeluarkan isi HTML atau JSON untuk mereka, atau mengarahkan mereka ke halaman. +Setelah pengguna mengirimkan [permintaan](/learn/requests) mereka ke aplikasi Anda, Anda perlu menghasilkan respons yang tepat untuk mereka. Mereka telah mengirimkan informasi seperti bahasa yang mereka sukai, apakah mereka dapat menangani jenis kompresi tertentu, agen pengguna mereka, dll., dan setelah memproses semuanya, saatnya mengirimkan respons yang tepat kembali kepada mereka. Ini bisa berupa pengaturan header, mengeluarkan body HTML atau JSON untuk mereka, atau mengarahkan mereka ke halaman. ## Penggunaan Dasar -### Mengirimkan Isi Respons +### Mengirim Body Respons -Flight menggunakan `ob_start()` untuk membuffer output. Ini berarti Anda dapat menggunakan `echo` atau `print` untuk mengirimkan respons ke pengguna dan Flight akan menangkapnya serta mengirimkannya kembali ke pengguna dengan header yang sesuai. +Flight menggunakan `ob_start()` untuk membuffer output. Ini berarti Anda dapat menggunakan `echo` atau `print` untuk mengirim respons ke pengguna dan Flight akan menangkapnya dan mengirimkannya kembali ke pengguna dengan header yang sesuai. ```php // Ini akan mengirim "Hello, World!" ke browser pengguna @@ -26,7 +26,7 @@ Flight::route('/', function() { // Hello, World! ``` -Sebagai alternatif, Anda dapat memanggil metode `write()` untuk menambahkan ke isi juga. +Sebagai alternatif, Anda dapat memanggil metode `write()` untuk menambahkan ke body juga. ```php // Ini akan mengirim "Hello, World!" ke browser pengguna @@ -34,7 +34,7 @@ Flight::route('/', function() { // verbose, tapi kadang-kadang diperlukan saat Anda membutuhkannya Flight::response()->write("Hello, World!"); - // jika Anda ingin mengambil isi yang telah Anda atur pada titik ini + // jika Anda ingin mengambil body yang telah Anda atur pada titik ini // Anda bisa melakukannya seperti ini $body = Flight::response()->getBody(); }); @@ -76,7 +76,7 @@ Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT); #### Mengubah Urutan Argumen JSON `Flight::json()` adalah metode yang sangat lama, tetapi tujuan Flight adalah mempertahankan kompatibilitas mundur -untuk proyek. Sebenarnya sangat sederhana jika Anda ingin mengubah urutan argumen untuk menggunakan sintaks yang lebih sederhana, +untuk proyek. Sebenarnya sangat sederhana jika Anda ingin mengubah urutan argumen untuk menggunakan sintaks yang lebih sederhana, Anda hanya perlu memetakan ulang metode JSON [seperti metode Flight lainnya](/learn/extending): ```php @@ -96,7 +96,7 @@ _v3.10.0_ Jika Anda ingin mengirim respons JSON dan menghentikan eksekusi, Anda dapat menggunakan metode `jsonHalt()`. Ini berguna untuk kasus di mana Anda memeriksa mungkin jenis otorisasi tertentu dan jika -pengguna tidak diotorisasi, Anda dapat mengirim respons JSON segera, membersihkan isi badan +pengguna tidak diotorisasi, Anda dapat mengirim respons JSON segera, membersihkan konten body yang ada dan menghentikan eksekusi. ```php @@ -105,10 +105,10 @@ Flight::route('/users', function() { // Periksa apakah pengguna diotorisasi if($authorized === false) { Flight::jsonHalt(['error' => 'Unauthorized'], 401); - // tidak ada exit; diperlukan di sini. + // no exit; needed here. } - // Lanjutkan dengan sisa rute + // Lanjutkan dengan sisa route }); ``` @@ -122,13 +122,13 @@ Flight::route('/users', function() { Flight::halt(401, json_encode(['error' => 'Unauthorized'])); } - // Lanjutkan dengan sisa rute + // Lanjutkan dengan sisa route }); ``` -### Membersihkan Isi Respons +### Membersihkan Body Respons -Jika Anda ingin membersihkan isi respons, Anda dapat menggunakan metode `clearBody`: +Jika Anda ingin membersihkan body respons, Anda dapat menggunakan metode `clearBody`: ```php Flight::route('/', function() { @@ -142,9 +142,9 @@ Flight::route('/', function() { Kasus penggunaan di atas mungkin tidak umum, namun bisa lebih umum jika ini digunakan dalam [middleware](/learn/middleware). -### Menjalankan Callback pada Isi Respons +### Menjalankan Callback pada Body Respons -Anda dapat menjalankan callback pada isi respons dengan menggunakan metode `addResponseBodyCallback`: +Anda dapat menjalankan callback pada body respons dengan menggunakan metode `addResponseBodyCallback`: ```php Flight::route('/users', function() { @@ -153,19 +153,19 @@ Flight::route('/users', function() { Flight::render('users_table', ['users' => $users]); }); -// Ini akan mengompresi gzip semua respons untuk rute apa pun +// Ini akan mengompresi gzip semua respons untuk route apa pun Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); ``` -Anda dapat menambahkan beberapa callback dan mereka akan dijalankan dalam urutan mereka ditambahkan. Karena ini dapat menerima [callable](https://www.php.net/manual/en/language.types.callable.php) apa pun, ini dapat menerima array kelas `[ $class, 'method' ]`, closure `$strReplace = function($body) { str_replace('hi', 'there', $body); };`, atau nama fungsi `'minify'` jika Anda memiliki fungsi untuk meminimalkan kode html Anda misalnya. +Anda dapat menambahkan beberapa callback dan mereka akan dijalankan dalam urutan yang ditambahkan. Karena ini dapat menerima [callable](https://www.php.net/manual/en/language.types.callable.php) apa pun, ini dapat menerima array kelas `[ $class, 'method' ]`, closure `$strReplace = function($body) { str_replace('hi', 'there', $body); };`, atau nama fungsi `'minify'` jika Anda memiliki fungsi untuk meminify kode html Anda misalnya. -**Catatan:** Callback rute tidak akan berfungsi jika Anda menggunakan opsi konfigurasi `flight.v2.output_buffering`. +**Catatan:** Callback route tidak akan bekerja jika Anda menggunakan opsi konfigurasi `flight.v2.output_buffering`. -#### Callback Rute Spesifik +#### Callback Route Spesifik -Jika Anda ingin ini hanya berlaku untuk rute spesifik, Anda dapat menambahkan callback di dalam rute itu sendiri: +Jika Anda ingin ini hanya berlaku untuk route spesifik, Anda dapat menambahkan callback di route itu sendiri: ```php Flight::route('/users', function() { @@ -173,7 +173,7 @@ Flight::route('/users', function() { $users = $db->fetchAll("SELECT * FROM users"); Flight::render('users_table', ['users' => $users]); - // Ini akan mengompresi gzip hanya respons untuk rute ini + // Ini akan mengompresi gzip hanya respons untuk route ini Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); @@ -182,7 +182,7 @@ Flight::route('/users', function() { #### Opsi Middleware -Anda juga dapat menggunakan [middleware](/learn/middleware) untuk menerapkan callback ke semua rute melalui middleware: +Anda juga dapat menggunakan [middleware](/learn/middleware) untuk menerapkan callback ke semua route melalui middleware: ```php // MinifyMiddleware.php @@ -195,7 +195,7 @@ class MinifyMiddleware { } protected function minify(string $body): string { - // minimalkan isi dengan cara tertentu + // minify body entah bagaimana return $body; } } @@ -243,9 +243,9 @@ Flight::route('/', function() { }); ``` -### Pengalihan +### Redirect -Anda dapat mengalihkan permintaan saat ini dengan menggunakan metode `redirect()` dan meneruskan +Anda dapat mengarahkan ulang permintaan saat ini dengan menggunakan metode `redirect()` dan meneruskan URL baru: ```php @@ -272,9 +272,9 @@ kustom: Flight::redirect('/new/location', 301); // permanen ``` -### Menghentikan Eksekusi Rute +### Menghentikan Eksekusi Route -Anda dapat menghentikan framework dan langsung keluar pada titik mana pun dengan memanggil metode `halt`: +Anda dapat menghentikan framework dan segera keluar pada titik mana pun dengan memanggil metode `halt`: ```php Flight::halt(); @@ -293,9 +293,9 @@ Jika Anda ingin menghentikan framework dan mengeluarkan respons saat ini, gunaka Flight::stop($httpStatusCode = null); ``` -> **Catatan:** `Flight::stop()` memiliki perilaku aneh seperti itu akan mengeluarkan respons tetapi melanjutkan eksekusi skrip Anda yang mungkin bukan yang Anda inginkan. Anda dapat menggunakan `exit` atau `return` setelah memanggil `Flight::stop()` untuk mencegah eksekusi lebih lanjut, tetapi umumnya direkomendasikan untuk menggunakan `Flight::halt()`. +> **Catatan:** `Flight::stop()` memiliki perilaku aneh seperti itu akan mengeluarkan respons tetapi melanjutkan eksekusi skrip Anda yang mungkin bukan yang Anda inginkan. Anda dapat menggunakan `exit` atau `return` setelah memanggil `Flight::stop()` untuk mencegah eksekusi lebih lanjut, tetapi umumnya disarankan untuk menggunakan `Flight::halt()`. -Ini akan menyimpan kunci header dan nilai ke objek respons. Pada akhir siklus hidup permintaan +Ini akan menyimpan kunci dan nilai header ke objek respons. Pada akhir siklus hidup permintaan ini akan membangun header dan mengirim respons. ## Penggunaan Lanjutan @@ -303,7 +303,7 @@ ini akan membangun header dan mengirim respons. ### Mengirim Header Segera Mungkin ada saat-saat ketika Anda perlu melakukan sesuatu yang kustom dengan header dan Anda perlu mengirim header -pada baris kode yang sama yang sedang Anda kerjakan. Jika Anda mengatur [rute streaming](/learn/routing), +pada baris kode yang sama yang Anda kerjakan. Jika Anda mengatur [route yang di-stream](/learn/routing), ini yang Anda butuhkan. Itu dapat dicapai melalui `response()->setRealHeader()`. ```php @@ -324,7 +324,7 @@ gunakan untuk mendefinisikan fungsi callback Anda: Flight::jsonp(['id' => 123], 'q'); ``` -Jadi, saat melakukan permintaan GET menggunakan `?q=my_func`, Anda seharusnya menerima output: +Jadi, saat membuat permintaan GET menggunakan `?q=my_func`, Anda seharusnya menerima output: ```javascript my_func({"id":123}); @@ -332,20 +332,20 @@ my_func({"id":123}); Jika Anda tidak meneruskan nama parameter query, itu akan default ke `jsonp`. -> **Catatan:** Jika Anda masih menggunakan permintaan JSONP pada tahun 2025 dan seterusnya, masuk ke chat dan beri tahu kami mengapa! Kami suka mendengar cerita pertempuran/horor yang bagus! +> **Catatan:** Jika Anda masih menggunakan permintaan JSONP pada 2025 dan seterusnya, lompat ke chat dan beri tahu kami mengapa! Kami suka mendengar cerita pertempuran/horor yang bagus! ### Membersihkan Data Respons -Anda dapat membersihkan isi respons dan header dengan menggunakan metode `clear()`. Ini akan membersihkan -header apa pun yang ditugaskan ke respons, membersihkan isi respons, dan mengatur kode status ke `200`. +Anda dapat membersihkan body respons dan header dengan menggunakan metode `clear()`. Ini akan membersihkan +header apa pun yang ditetapkan ke respons, membersihkan body respons, dan mengatur kode status ke `200`. ```php Flight::response()->clear(); ``` -#### Membersihkan Hanya Isi Respons +#### Membersihkan Hanya Body Respons -Jika Anda hanya ingin membersihkan isi respons, Anda dapat menggunakan metode `clearBody()`: +Jika Anda hanya ingin membersihkan body respons, Anda dapat menggunakan metode `clearBody()`: ```php // Ini masih akan mempertahankan header apa pun yang diatur pada objek response(). @@ -354,11 +354,11 @@ Flight::response()->clearBody(); ### Penyimpanan Cache HTTP -Flight menyediakan dukungan bawaan untuk penyimpanan cache tingkat HTTP. Jika kondisi caching -terpenuhi, Flight akan mengembalikan respons HTTP `304 Not Modified`. Lain kali klien +Flight menyediakan dukungan bawaan untuk caching tingkat HTTP. Jika kondisi caching +terpenuhi, Flight akan mengembalikan respons HTTP `304 Not Modified`. Saat berikutnya klien meminta sumber daya yang sama, mereka akan diminta untuk menggunakan versi cache lokal mereka. -#### Penyimpanan Cache Tingkat Rute +#### Caching Tingkat Route Jika Anda ingin menyimpan cache seluruh respons Anda, Anda dapat menggunakan metode `cache()` dan meneruskan waktu untuk cache. @@ -370,7 +370,7 @@ Flight::route('/news', function () { echo 'This content will be cached.'; }); -// Secara alternatif, Anda dapat menggunakan string yang akan Anda teruskan +// Alternatifnya, Anda dapat menggunakan string yang akan Anda teruskan // ke metode strtotime() Flight::route('/news', function () { Flight::response()->cache('+5 minutes'); @@ -382,7 +382,7 @@ Flight::route('/news', function () { Anda dapat menggunakan metode `lastModified` dan meneruskan timestamp UNIX untuk mengatur tanggal dan waktu halaman terakhir dimodifikasi. Klien akan terus menggunakan cache mereka hingga -nilai terakhir dimodifikasi diubah. +nilai last modified berubah. ```php Flight::route('/news', function () { @@ -393,8 +393,8 @@ Flight::route('/news', function () { ### ETag -Penyimpanan cache `ETag` mirip dengan `Last-Modified`, kecuali Anda dapat menentukan id apa pun yang Anda -inginkan untuk sumber daya: +Caching `ETag` mirip dengan `Last-Modified`, kecuali Anda dapat menentukan id apa pun yang +Anda inginkan untuk sumber daya: ```php Flight::route('/news', function () { @@ -416,21 +416,24 @@ Ada metode pembantu untuk streaming file ke pengguna akhir. Anda dapat menggunak ```php Flight::route('/download', function () { Flight::download('/path/to/file.txt'); + // Mulai v3.17.1 Anda dapat menentukan nama file kustom untuk unduhan + Flight::download('/path/to/file.txt', 'custom_name.txt'); }); ``` ## Lihat Juga -- [Routing](/learn/routing) - Cara memetakan rute ke controller dan merender tampilan. +- [Routing](/learn/routing) - Cara memetakan route ke controller dan merender view. - [Requests](/learn/requests) - Memahami cara menangani permintaan masuk. -- [Middleware](/learn/middleware) - Menggunakan middleware dengan rute untuk autentikasi, logging, dll. +- [Middleware](/learn/middleware) - Menggunakan middleware dengan route untuk autentikasi, logging, dll. - [Mengapa Framework?](/learn/why-frameworks) - Memahami manfaat menggunakan framework seperti Flight. -- [Memperluas](/learn/extending) - Cara memperluas Flight dengan fungsionalitas Anda sendiri. +- [Extending](/learn/extending) - Cara memperluas Flight dengan fungsionalitas Anda sendiri. ## Pemecahan Masalah -- Jika Anda mengalami masalah dengan pengalihan yang tidak berfungsi, pastikan Anda menambahkan `return;` ke metode tersebut. -- `stop()` dan `halt()` bukan hal yang sama. `halt()` akan menghentikan eksekusi segera, sementara `stop()` akan mengizinkan eksekusi berlanjut. +- Jika Anda mengalami masalah dengan redirect yang tidak bekerja, pastikan Anda menambahkan `return;` ke metode. +- `stop()` dan `halt()` bukan hal yang sama. `halt()` akan menghentikan eksekusi segera, sementara `stop()` akan memungkinkan eksekusi berlanjut. ## Changelog +- v3.17.1 - Menambahkan `$fileName` ke metode `downloadFile()`. - v3.12.0 - Menambahkan metode pembantu downloadFile. - v3.10.0 - Menambahkan `jsonHalt`. - v1.0 - Rilis awal. \ No newline at end of file diff --git a/content/v3/id/learn/routing.md b/content/v3/id/learn/routing.md index 9b77cc3e..bfcf3a82 100644 --- a/content/v3/id/learn/routing.md +++ b/content/v3/id/learn/routing.md @@ -1,17 +1,17 @@ # Routing -## Ikhtisar -Routing di Flight PHP memetakan pola URL ke fungsi callback atau metode kelas, memungkinkan penanganan permintaan yang cepat dan sederhana. Dirancang untuk overhead minimal, penggunaan ramah pemula, dan keterluangan tanpa ketergantungan eksternal. +## Overview +Routing di Flight PHP memetakan pola URL ke fungsi callback atau metode kelas, memungkinkan penanganan permintaan yang cepat dan sederhana. Ini dirancang untuk overhead minimal, penggunaan yang ramah pemula, dan keterluangan tanpa ketergantungan eksternal. -## Pemahaman -Routing adalah mekanisme inti yang menghubungkan permintaan HTTP ke logika aplikasi Anda di Flight. Dengan mendefinisikan rute, Anda menentukan bagaimana URL yang berbeda memicu kode spesifik, baik melalui fungsi, metode kelas, atau tindakan controller. Sistem routing Flight fleksibel, mendukung pola dasar, parameter bernama, ekspresi reguler, dan fitur lanjutan seperti injeksi dependensi dan routing sumber daya. Pendekatan ini menjaga kode Anda terorganisir dan mudah dipelihara, sambil tetap cepat dan sederhana untuk pemula serta dapat dikembangkan untuk pengguna lanjutan. +## Understanding +Routing adalah mekanisme inti yang menghubungkan permintaan HTTP ke logika aplikasi Anda di Flight. Dengan mendefinisikan rute, Anda menentukan bagaimana URL yang berbeda memicu kode spesifik, baik melalui fungsi, metode kelas, atau aksi pengontrol. Sistem routing Flight fleksibel, mendukung pola dasar, parameter bernama, ekspresi reguler, dan fitur lanjutan seperti injeksi dependensi dan routing sumber daya. Pendekatan ini menjaga kode Anda terorganisir dan mudah dipelihara, sambil tetap cepat dan sederhana untuk pemula serta dapat dikembangkan untuk pengguna lanjutan. > **Catatan:** Ingin memahami lebih lanjut tentang routing? Lihat halaman ["why a framework?"](/learn/why-frameworks) untuk penjelasan yang lebih mendalam. -## Penggunaan Dasar +## Basic Usage ### Mendefinisikan Rute Sederhana -Routing dasar di Flight dilakukan dengan mencocokkan pola URL dengan fungsi callback atau array dari kelas dan metode. +Routing dasar di Flight dilakukan dengan mencocokkan pola URL dengan fungsi callback atau array kelas dan metode. ```php Flight::route('/', function(){ @@ -19,10 +19,10 @@ Flight::route('/', function(){ }); ``` -> Rute dicocokkan sesuai urutan definisinya. Rute pertama yang cocok dengan permintaan akan dipanggil. +> Rute dicocokkan sesuai urutan yang didefinisikan. Rute pertama yang cocok dengan permintaan akan dipanggil. ### Menggunakan Fungsi sebagai Callback -Callback bisa berupa objek apa pun yang dapat dipanggil. Jadi Anda bisa menggunakan fungsi biasa: +Callback dapat berupa objek apa pun yang dapat dipanggil. Jadi Anda dapat menggunakan fungsi biasa: ```php function hello() { @@ -32,8 +32,8 @@ function hello() { Flight::route('/', 'hello'); ``` -### Menggunakan Kelas dan Metode sebagai Controller -Anda juga bisa menggunakan metode (statis atau tidak) dari kelas: +### Menggunakan Kelas dan Metode sebagai Pengontrol +Anda juga dapat menggunakan metode (statis atau tidak) dari sebuah kelas: ```php class GreetingController { @@ -43,15 +43,15 @@ class GreetingController { } Flight::route('/', [ 'GreetingController','hello' ]); -// atau -Flight::route('/', [ GreetingController::class, 'hello' ]); // metode yang disarankan -// atau +// or +Flight::route('/', [ GreetingController::class, 'hello' ]); // metode yang disukai +// or Flight::route('/', [ 'GreetingController::hello' ]); -// atau +// or Flight::route('/', [ 'GreetingController->hello' ]); ``` -Atau dengan membuat objek terlebih dahulu lalu memanggil metodenya: +Atau dengan membuat objek terlebih dahulu dan kemudian memanggil metode: ```php use flight\Engine; @@ -77,11 +77,12 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **Catatan:** Secara default, ketika controller dipanggil dalam framework, kelas `flight\Engine` selalu diinjeksikan kecuali Anda menentukannya melalui [container injeksi dependensi](/learn/dependency-injection-container) +> **Catatan:** Secara default, ketika pengontrol dipanggil dalam framework, kelas `flight\Engine` selalu disuntikkan kecuali Anda menentukannya melalui [dependency injection container](/learn/dependency-injection-container) ### Routing Khusus Metode -Secara default, pola rute dicocokkan dengan semua metode permintaan. Anda bisa merespons metode spesifik dengan menempatkan pengenal sebelum URL. +Secara default, pola rute dicocokkan dengan semua metode permintaan. Anda dapat merespons +ke metode spesifik dengan menempatkan pengenal sebelum URL. ```php Flight::route('GET /', function () { @@ -92,15 +93,15 @@ Flight::route('POST /', function () { echo 'I received a POST request.'; }); -// Anda tidak bisa menggunakan Flight::get() untuk rute karena itu adalah metode -// untuk mendapatkan variabel, bukan membuat rute. +// You cannot use Flight::get() for routes as that is a method +// to get variables, not create a route. Flight::post('/', function() { /* code */ }); Flight::patch('/', function() { /* code */ }); Flight::put('/', function() { /* code */ }); Flight::delete('/', function() { /* code */ }); ``` -Anda juga bisa memetakan beberapa metode ke satu callback dengan menggunakan pemisah `|`: +Anda juga dapat memetakan beberapa metode ke satu callback dengan menggunakan delimiter `|`: ```php Flight::route('GET|POST /', function () { @@ -108,20 +109,52 @@ Flight::route('GET|POST /', function () { }); ``` +### Penanganan Khusus untuk Permintaan HEAD dan OPTIONS + +Flight menyediakan penanganan bawaan untuk permintaan HTTP `HEAD` dan `OPTIONS`: + +#### Permintaan HEAD + +- **Permintaan HEAD** diperlakukan seperti permintaan `GET`, tetapi Flight secara otomatis menghapus badan respons sebelum mengirimkannya ke klien. +- Ini berarti Anda dapat mendefinisikan rute untuk `GET`, dan permintaan HEAD ke URL yang sama akan mengembalikan hanya header (tanpa konten), sesuai standar HTTP. + +```php +Flight::route('GET /info', function() { + echo 'This is some info!'; +}); +// A HEAD request to /info will return the same headers, but no body. +``` + +#### Permintaan OPTIONS + +Permintaan `OPTIONS` ditangani secara otomatis oleh Flight untuk rute apa pun yang didefinisikan. +- Ketika permintaan OPTIONS diterima, Flight merespons dengan status `204 No Content` dan header `Allow` yang mencantumkan semua metode HTTP yang didukung untuk rute tersebut. +- Anda tidak perlu mendefinisikan rute terpisah untuk OPTIONS kecuali Anda ingin perilaku kustom atau memodifikasi respons. + +```php +// For a route defined as: +Flight::route('GET|POST /users', function() { /* ... */ }); + +// An OPTIONS request to /users will respond with: +// +// Status: 204 No Content +// Allow: GET, POST, HEAD, OPTIONS +``` + ### Menggunakan Objek Router -Selain itu, Anda bisa mengambil objek Router yang memiliki beberapa metode pembantu untuk digunakan: +Selain itu, Anda dapat mengambil objek Router yang memiliki beberapa metode pembantu untuk digunakan: ```php $router = Flight::router(); -// memetakan semua metode seperti Flight::route() +// maps all methods just like Flight::route() $router->map('/', function() { echo 'hello world!'; }); -// permintaan GET +// GET request $router->get('/users', function() { echo 'users'; }); @@ -132,18 +165,21 @@ $router->patch('/users/@id', function() { /* code */}); ``` ### Ekspresi Regulasi (Regex) -Anda bisa menggunakan ekspresi reguler di rute Anda: +Anda dapat menggunakan ekspresi reguler di rute Anda: ```php Flight::route('/user/[0-9]+', function () { - // Ini akan cocok dengan /user/1234 + // This will match /user/1234 }); ``` -Meskipun metode ini tersedia, disarankan untuk menggunakan parameter bernama, atau parameter bernama dengan ekspresi reguler, karena lebih mudah dibaca dan dipelihara. +Meskipun metode ini tersedia, disarankan untuk menggunakan parameter bernama, atau +parameter bernama dengan ekspresi reguler, karena lebih mudah dibaca dan dipelihara. ### Parameter Bernama -Anda bisa menentukan parameter bernama di rute Anda yang akan diteruskan ke fungsi callback Anda. **Ini lebih untuk keterbacaan rute daripada yang lain. Lihat bagian di bawah tentang peringatan penting.** +Anda dapat menentukan parameter bernama di rute Anda yang akan diteruskan ke +fungsi callback Anda. **Ini lebih untuk keterbacaan rute daripada yang lain. +Silakan lihat bagian di bawah tentang peringatan penting.** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -151,20 +187,21 @@ Flight::route('/@name/@id', function (string $name, string $id) { }); ``` -Anda juga bisa menyertakan ekspresi reguler dengan parameter bernama dengan menggunakan pemisah `:`: +Anda juga dapat menyertakan ekspresi reguler dengan parameter bernama Anda dengan menggunakan +delimiter `:`: ```php Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { - // Ini akan cocok dengan /bob/123 - // Tapi tidak akan cocok dengan /bob/12345 + // This will match /bob/123 + // But will not match /bob/12345 }); ``` -> **Catatan:** Pencocokan grup regex `()` dengan parameter posisional tidak didukung. Contoh: `:'\(` +> **Catatan:** Mencocokkan grup regex `()` dengan parameter posisional tidak didukung. Contoh: `:'\(` #### Peringatan Penting -Meskipun dalam contoh di atas, tampaknya `@name` langsung terkait dengan variabel `$name`, sebenarnya tidak. Urutan parameter dalam fungsi callback yang menentukan apa yang diteruskan ke dalamnya. Jika Anda menukar urutan parameter dalam fungsi callback, variabel juga akan bertukar. Berikut contohnya: +Meskipun dalam contoh di atas, tampaknya `@name` langsung terkait dengan variabel `$name`, sebenarnya tidak. Urutan parameter dalam fungsi callback yang menentukan apa yang diteruskan ke dalamnya. Jika Anda menukar urutan parameter dalam fungsi callback, variabel juga akan ditukar. Berikut adalah contoh: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -176,13 +213,14 @@ Dan jika Anda mengunjungi URL berikut: `/bob/123`, outputnya akan menjadi `hello _Harap berhati-hati_ saat menyiapkan rute dan fungsi callback Anda! ### Parameter Opsional -Anda bisa menentukan parameter bernama yang opsional untuk pencocokan dengan membungkus segmen dalam tanda kurung. +Anda dapat menentukan parameter bernama yang opsional untuk pencocokan dengan membungkus +segmen dalam tanda kurung. ```php Flight::route( '/blog(/@year(/@month(/@day)))', function(?string $year, ?string $month, ?string $day) { - // Ini akan cocok dengan URL berikut: + // This will match the following URLS: // /blog/2012/12/10 // /blog/2012/12 // /blog/2012 @@ -194,32 +232,33 @@ Flight::route( Parameter opsional apa pun yang tidak cocok akan diteruskan sebagai `NULL`. ### Routing Wildcard -Pencocokan hanya dilakukan pada segmen URL individual. Jika Anda ingin mencocokkan beberapa segmen, Anda bisa menggunakan wildcard `*`. +Pencocokan hanya dilakukan pada segmen URL individu. Jika Anda ingin mencocokkan beberapa +segmen, Anda dapat menggunakan wildcard `*`. ```php Flight::route('/blog/*', function () { - // Ini akan cocok dengan /blog/2000/02/01 + // This will match /blog/2000/02/01 }); ``` -Untuk merutekan semua permintaan ke satu callback, Anda bisa lakukan: +Untuk merutekan semua permintaan ke satu callback, Anda dapat melakukannya: ```php Flight::route('*', function () { - // Lakukan sesuatu + // Do something }); ``` -### Penanganan 404 Tidak Ditemukan +### Penanganan 404 Not Found Secara default, jika URL tidak ditemukan, Flight akan mengirim respons `HTTP 404 Not Found` yang sangat sederhana dan polos. -Jika Anda ingin respons 404 yang lebih disesuaikan, Anda bisa [memetakan](/learn/extending) metode `notFound` sendiri: +Jika Anda ingin respons 404 yang lebih disesuaikan, Anda dapat [memetakan](/learn/extending) metode `notFound` sendiri: ```php Flight::map('notFound', function() { $url = Flight::request()->url; - // Anda juga bisa menggunakan Flight::render() dengan template kustom. + // You could also use Flight::render() with a custom template. $output = <<My Custom 404 Not Found

The page you have requested {$url} could not be found.

@@ -233,12 +272,45 @@ Flight::map('notFound', function() { }); ``` -## Penggunaan Lanjutan +### Penanganan Metode Tidak Ditemukan + +Secara default, jika URL ditemukan tetapi metode tidak diizinkan, Flight akan mengirim respons `HTTP 405 Method Not Allowed` yang sangat sederhana dan polos (Contoh: Method Not Allowed. Allowed Methods are: GET, POST). Ini juga akan menyertakan header `Allow` dengan metode yang diizinkan untuk URL tersebut. + +Jika Anda ingin respons 405 yang lebih disesuaikan, Anda dapat [memetakan](/learn/extending) metode `methodNotFound` sendiri: + +```php +use flight\net\Route; + +Flight::map('methodNotFound', function(Route $route) { + $url = Flight::request()->url; + $methods = implode(', ', $route->methods); + + // You could also use Flight::render() with a custom template. + $output = <<My Custom 405 Method Not Allowed +

The method you have requested for {$url} is not allowed.

+

Allowed Methods are: {$methods}

+ HTML; + + $this->response() + ->clearBody() + ->status(405) + ->setHeader('Allow', $methods) + ->write($output) + ->send(); +}); +``` + +## Advanced Usage ### Injeksi Dependensi di Rute -Jika Anda ingin menggunakan injeksi dependensi melalui container (PSR-11, PHP-DI, Dice, dll), satu-satunya jenis rute yang tersedia adalah dengan membuat objek secara langsung sendiri dan menggunakan container untuk membuat objek Anda atau Anda bisa menggunakan string untuk mendefinisikan kelas dan metode yang akan dipanggil. Anda bisa kunjungi halaman [Dependency Injection](/learn/dependency-injection-container) untuk informasi lebih lanjut. +Jika Anda ingin menggunakan injeksi dependensi melalui wadah (PSR-11, PHP-DI, Dice, dll), +satu-satunya jenis rute di mana itu tersedia adalah dengan membuat objek secara langsung sendiri +dan menggunakan wadah untuk membuat objek Anda atau Anda dapat menggunakan string untuk mendefinisikan kelas dan +metode yang akan dipanggil. Anda dapat membaca halaman [Dependency Injection](/learn/dependency-injection-container) untuk +informasi lebih lanjut. -Berikut contoh singkat: +Berikut adalah contoh cepat: ```php @@ -253,7 +325,7 @@ class Greeting } public function hello(int $id) { - // lakukan sesuatu dengan $this->pdoWrapper + // do something with $this->pdoWrapper $name = $this->pdoWrapper->fetchField("SELECT name FROM users WHERE id = ?", [ $id ]); echo "Hello, world! My name is {$name}!"; } @@ -261,11 +333,11 @@ class Greeting // index.php -// Siapkan container dengan parameter apa pun yang Anda butuhkan -// Lihat halaman Dependency Injection untuk informasi lebih lanjut tentang PSR-11 +// Setup the container with whatever params you need +// See the Dependency Injection page for more information on PSR-11 $dice = new \Dice\Dice(); -// Jangan lupa untuk menugaskan ulang variabel dengan '$dice = '!!!!! +// Don't forget to reassign the variable with '$dice = '!!!!! $dice = $dice->addRule('flight\database\PdoWrapper', [ 'shared' => true, 'constructParams' => [ @@ -275,64 +347,65 @@ $dice = $dice->addRule('flight\database\PdoWrapper', [ ] ]); -// Daftarkan penanganan container +// Register the container handler Flight::registerContainerHandler(function($class, $params) use ($dice) { return $dice->create($class, $params); }); -// Rute seperti biasa +// Routes like normal Flight::route('/hello/@id', [ 'Greeting', 'hello' ]); -// atau +// or Flight::route('/hello/@id', 'Greeting->hello'); -// atau +// or Flight::route('/hello/@id', 'Greeting::hello'); Flight::start(); ``` -### Mengalihkan Eksekusi ke Rute Berikutnya +### Meneruskan Eksekusi ke Rute Berikutnya Deprecated -Anda bisa mengalihkan eksekusi ke rute pencocokan berikutnya dengan mengembalikan `true` dari fungsi callback Anda. +Anda dapat meneruskan eksekusi ke rute pencocokan berikutnya dengan mengembalikan `true` dari +fungsi callback Anda. ```php Flight::route('/user/@name', function (string $name) { - // Periksa kondisi tertentu + // Check some condition if ($name !== "Bob") { - // Lanjutkan ke rute berikutnya + // Continue to next route return true; } }); Flight::route('/user/*', function () { - // Ini akan dipanggil + // This will get called }); ``` Sekarang disarankan untuk menggunakan [middleware](/learn/middleware) untuk menangani kasus penggunaan kompleks seperti ini. ### Alias Rute -Dengan menetapkan alias ke rute, Anda bisa memanggil alias tersebut di aplikasi Anda secara dinamis untuk dihasilkan nanti di kode Anda (contoh: tautan di template HTML, atau menghasilkan URL redirect). +Dengan menetapkan alias ke rute, Anda dapat memanggil alias tersebut di aplikasi Anda secara dinamis untuk dihasilkan nanti di kode Anda (contoh: tautan di template HTML, atau menghasilkan URL pengalihan). ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); -// atau +// or Flight::route('/users/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view'); -// nanti di suatu tempat di kode +// later in code somewhere class UserController { public function update() { - // kode untuk menyimpan pengguna... - $id = $user['id']; // 5 misalnya + // code to save user... + $id = $user['id']; // 5 for example - $redirectUrl = Flight::getUrl('user_view', [ 'id' => $id ]); // akan mengembalikan '/users/5' + $redirectUrl = Flight::getUrl('user_view', [ 'id' => $id ]); // will return '/users/5' Flight::redirect($redirectUrl); } } ``` -Ini sangat membantu jika URL Anda berubah. Dalam contoh di atas, katakanlah pengguna dipindahkan ke `/admin/users/@id` sebagai gantinya. +Ini sangat membantu jika URL Anda berubah. Dalam contoh di atas, misalkan pengguna dipindahkan ke `/admin/users/@id` sebagai gantinya. Dengan aliasing di tempat untuk rute, Anda tidak lagi perlu mencari semua URL lama di kode Anda dan mengubahnya karena alias sekarang akan mengembalikan `/admin/users/5` seperti dalam contoh di atas. Alias rute masih berfungsi dalam grup juga: @@ -340,112 +413,112 @@ Alias rute masih berfungsi dalam grup juga: ```php Flight::group('/users', function() { Flight::route('/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); - // atau + // or Flight::route('/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view'); }); ``` ### Memeriksa Informasi Rute -Jika Anda ingin memeriksa informasi rute pencocokan, ada 2 cara Anda bisa lakukan ini: +Jika Anda ingin memeriksa informasi rute pencocokan, ada 2 cara yang bisa Anda lakukan: -1. Anda bisa menggunakan properti `executedRoute` pada objek `Flight::router()`. -2. Anda bisa meminta objek rute diteruskan ke callback Anda dengan meneruskan `true` sebagai parameter ketiga dalam metode rute. Objek rute selalu menjadi parameter terakhir yang diteruskan ke fungsi callback Anda. +1. Anda dapat menggunakan properti `executedRoute` pada objek `Flight::router()`. +2. Anda dapat meminta objek rute diteruskan ke callback Anda dengan meneruskan `true` sebagai parameter ketiga dalam metode rute. Objek rute selalu menjadi parameter terakhir yang diteruskan ke fungsi callback Anda. #### `executedRoute` ```php Flight::route('/', function() { $route = Flight::router()->executedRoute; - // Lakukan sesuatu dengan $route - // Array metode HTTP yang dicocokkan + // Do something with $route + // Array of HTTP methods matched against $route->methods; - // Array parameter bernama + // Array of named parameters $route->params; - // Ekspresi reguler pencocokan + // Matching regular expression $route->regex; - // Berisi isi dari '*' apa pun yang digunakan dalam pola URL + // Contains the contents of any '*' used in the URL pattern $route->splat; - // Menunjukkan jalur URL....jika Anda benar-benar membutuhkannya + // Shows the url path....if you really need it $route->pattern; - // Menunjukkan middleware apa yang ditetapkan untuk ini + // Shows what middleware is assigned to this $route->middleware; - // Menunjukkan alias yang ditetapkan untuk rute ini + // Shows the alias assigned to this route $route->alias; }); ``` -> **Catatan:** Properti `executedRoute` hanya akan ditetapkan setelah rute dieksekusi. Jika Anda mencoba mengaksesnya sebelum rute dieksekusi, itu akan menjadi `NULL`. Anda juga bisa menggunakan executedRoute di [middleware](/learn/middleware) juga! +> **Catatan:** Properti `executedRoute` hanya akan diatur setelah rute dieksekusi. Jika Anda mencoba mengaksesnya sebelum rute dieksekusi, itu akan menjadi `NULL`. Anda juga dapat menggunakan executedRoute di [middleware](/learn/middleware) juga! -#### Teruskan `true` ke definisi rute +#### Meneruskan `true` ke definisi rute ```php Flight::route('/', function(\flight\net\Route $route) { - // Array metode HTTP yang dicocokkan + // Array of HTTP methods matched against $route->methods; - // Array parameter bernama + // Array of named parameters $route->params; - // Ekspresi reguler pencocokan + // Matching regular expression $route->regex; - // Berisi isi dari '*' apa pun yang digunakan dalam pola URL + // Contains the contents of any '*' used in the URL pattern $route->splat; - // Menunjukkan jalur URL....jika Anda benar-benar membutuhkannya + // Shows the url path....if you really need it $route->pattern; - // Menunjukkan middleware apa yang ditetapkan untuk ini + // Shows what middleware is assigned to this $route->middleware; - // Menunjukkan alias yang ditetapkan untuk rute ini + // Shows the alias assigned to this route $route->alias; -}, true);// <-- Parameter true ini yang membuatnya terjadi +}, true);// <-- This true parameter is what makes that happen ``` ### Pengelompokan Rute dan Middleware Mungkin ada saatnya Anda ingin mengelompokkan rute terkait bersama (seperti `/api/v1`). -Anda bisa lakukan ini dengan menggunakan metode `group`: +Anda dapat melakukan ini dengan menggunakan metode `group`: ```php Flight::group('/api/v1', function () { Flight::route('/users', function () { - // Cocok dengan /api/v1/users + // Matches /api/v1/users }); Flight::route('/posts', function () { - // Cocok dengan /api/v1/posts + // Matches /api/v1/posts }); }); ``` -Anda bahkan bisa menumpuk grup dari grup: +Anda bahkan dapat menumpuk grup dari grup: ```php Flight::group('/api', function () { Flight::group('/v1', function () { - // Flight::get() mendapatkan variabel, itu tidak menetapkan rute! Lihat konteks objek di bawah + // Flight::get() gets variables, it doesn't set a route! See object context below Flight::route('GET /users', function () { - // Cocok dengan GET /api/v1/users + // Matches GET /api/v1/users }); Flight::post('/posts', function () { - // Cocok dengan POST /api/v1/posts + // Matches POST /api/v1/posts }); Flight::put('/posts/1', function () { - // Cocok dengan PUT /api/v1/posts + // Matches PUT /api/v1/posts }); }); Flight::group('/v2', function () { - // Flight::get() mendapatkan variabel, itu tidak menetapkan rute! Lihat konteks objek di bawah + // Flight::get() gets variables, it doesn't set a route! See object context below Flight::route('GET /users', function () { - // Cocok dengan GET /api/v2/users + // Matches GET /api/v2/users }); }); }); @@ -453,42 +526,43 @@ Flight::group('/api', function () { #### Pengelompokan dengan Konteks Objek -Anda masih bisa menggunakan pengelompokan rute dengan objek `Engine` dengan cara berikut: +Anda masih dapat menggunakan pengelompokan rute dengan objek `Engine` dengan cara berikut: ```php $app = Flight::app(); $app->group('/api/v1', function (Router $router) { - // gunakan variabel $router + // user the $router variable $router->get('/users', function () { - // Cocok dengan GET /api/v1/users + // Matches GET /api/v1/users }); $router->post('/posts', function () { - // Cocok dengan POST /api/v1/posts + // Matches POST /api/v1/posts }); }); ``` -> **Catatan:** Ini adalah metode yang disarankan untuk mendefinisikan rute dan grup dengan objek `$router`. +> **Catatan:** Ini adalah metode yang disukai untuk mendefinisikan rute dan grup dengan objek `$router`. #### Pengelompokan dengan Middleware -Anda juga bisa menetapkan middleware ke grup rute: +Anda juga dapat menetapkan middleware ke grup rute: ```php Flight::group('/api/v1', function () { Flight::route('/users', function () { - // Cocok dengan /api/v1/users + // Matches /api/v1/users }); -}, [ MyAuthMiddleware::class ]); // atau [ new MyAuthMiddleware() ] jika Anda ingin menggunakan instance +}, [ MyAuthMiddleware::class ]); // or [ new MyAuthMiddleware() ] if you want to use an instance ``` Lihat detail lebih lanjut di halaman [group middleware](/learn/middleware#grouping-middleware). ### Routing Sumber Daya -Anda bisa membuat set rute untuk sumber daya menggunakan metode `resource`. Ini akan membuat set rute untuk sumber daya yang mengikuti konvensi RESTful. +Anda dapat membuat set rute untuk sumber daya menggunakan metode `resource`. Ini akan membuat +set rute untuk sumber daya yang mengikuti konvensi RESTful. Untuk membuat sumber daya, lakukan hal berikut: @@ -496,7 +570,7 @@ Untuk membuat sumber daya, lakukan hal berikut: Flight::resource('/users', UsersController::class); ``` -Dan yang akan terjadi di belakang adalah membuat rute berikut: +Dan yang akan terjadi di latar belakang adalah itu akan membuat rute berikut: ```php [ @@ -510,7 +584,7 @@ Dan yang akan terjadi di belakang adalah membuat rute berikut: ] ``` -Dan controller Anda akan menggunakan metode berikut: +Dan pengontrol Anda akan menggunakan metode berikut: ```php class UsersController @@ -545,16 +619,18 @@ class UsersController } ``` -> **Catatan**: Anda bisa melihat rute yang baru ditambahkan dengan `runway` dengan menjalankan `php runway routes`. +> **Catatan**: Anda dapat melihat rute yang baru ditambahkan dengan `runway` dengan menjalankan `php runway routes`. #### Menyesuaikan Rute Sumber Daya Ada beberapa opsi untuk mengonfigurasi rute sumber daya. -##### Alias Dasar +##### Alias Base -Anda bisa mengonfigurasi `aliasBase`. Secara default, alias adalah bagian terakhir dari URL yang ditentukan. -Misalnya `/users/` akan menghasilkan `aliasBase` dari `users`. Saat rute ini dibuat, aliasnya adalah `users.index`, `users.create`, dll. Jika Anda ingin mengubah alias, tetapkan `aliasBase` ke nilai yang Anda inginkan. +Anda dapat mengonfigurasi `aliasBase`. Secara default alias adalah bagian terakhir dari URL yang ditentukan. +Misalnya `/users/` akan menghasilkan `aliasBase` dari `users`. Ketika rute ini dibuat, +aliasnya adalah `users.index`, `users.create`, dll. Jika Anda ingin mengubah alias, atur `aliasBase` +ke nilai yang Anda inginkan. ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); @@ -562,23 +638,23 @@ Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); ##### Only dan Except -Anda juga bisa menentukan rute mana yang ingin Anda buat dengan menggunakan opsi `only` dan `except`. +Anda juga dapat menentukan rute mana yang ingin Anda buat dengan menggunakan opsi `only` dan `except`. ```php -// Daftar putih hanya metode ini dan daftar hitam sisanya +// Whitelist only these methods and blacklist the rest Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' ] ]); ``` ```php -// Daftar hitam hanya metode ini dan daftar putih sisanya +// Blacklist only these methods and whitelist the rest Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` -Ini pada dasarnya opsi daftar putih dan daftar hitam sehingga Anda bisa menentukan rute mana yang ingin dibuat. +Ini pada dasarnya opsi whitelisting dan blacklisting sehingga Anda dapat menentukan rute mana yang ingin Anda buat. ##### Middleware -Anda juga bisa menentukan middleware yang akan dijalankan pada setiap rute yang dibuat oleh metode `resource`. +Anda juga dapat menentukan middleware yang akan dijalankan pada setiap rute yang dibuat oleh metode `resource`. ```php Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]); @@ -586,16 +662,16 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid ### Respons Streaming -Anda sekarang bisa streaming respons ke klien menggunakan `stream()` atau `streamWithHeaders()`. -Ini berguna untuk mengirim file besar, proses jangka panjang, atau menghasilkan respons besar. +Anda sekarang dapat streaming respons ke klien menggunakan `stream()` atau `streamWithHeaders()`. +Ini berguna untuk mengirim file besar, proses yang berjalan lama, atau menghasilkan respons besar. Streaming rute ditangani sedikit berbeda daripada rute biasa. -> **Catatan:** Respons streaming hanya tersedia jika Anda memiliki [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) yang ditetapkan ke `false`. +> **Catatan:** Respons streaming hanya tersedia jika Anda memiliki [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) yang diatur ke `false`. #### Stream dengan Header Manual -Anda bisa streaming respons ke klien dengan menggunakan metode `stream()` pada rute. Jika Anda -melakukannya, Anda harus menetapkan semua header secara manual sebelum Anda mengeluarkan apa pun ke klien. +Anda dapat streaming respons ke klien dengan menggunakan metode `stream()` pada rute. Jika Anda +melakukan ini, Anda harus mengatur semua header secara manual sebelum Anda mengeluarkan apa pun ke klien. Ini dilakukan dengan fungsi php `header()` atau metode `Flight::response()->setRealHeader()`. ```php @@ -603,15 +679,15 @@ Flight::route('/@filename', function($filename) { $response = Flight::response(); - // jelas Anda akan membersihkan jalur dan sebagainya. + // obviously you would sanitize the path and whatnot. $fileNameSafe = basename($filename); - // Jika Anda memiliki header tambahan untuk ditetapkan di sini setelah rute dieksekusi - // Anda harus mendefinisikannya sebelum apa pun diekstrak. - // Semuanya harus panggilan mentah ke fungsi header() atau - // panggilan ke Flight::response()->setRealHeader() + // If you have additional headers to set here after the route has executed + // you must define them before anything is echoed out. + // They must all be a raw call to the header() function or + // a call to Flight::response()->setRealHeader() header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); - // atau + // or $response->setRealHeader('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); $filePath = '/some/path/to/files/'.$fileNameSafe; @@ -620,29 +696,29 @@ Flight::route('/@filename', function($filename) { Flight::halt(404, 'File not found'); } - // tetapkan panjang konten secara manual jika Anda suka + // manually set the content length if you'd like header('Content-Length: '.filesize($filePath)); - // atau + // or $response->setRealHeader('Content-Length: '.filesize($filePath)); - // Stream file ke klien saat dibaca + // Stream the file to the client as it's read readfile($filePath); -// Ini adalah baris ajaib di sini +// This is the magic line here })->stream(); ``` #### Stream dengan Header -Anda juga bisa menggunakan metode `streamWithHeaders()` untuk menetapkan header sebelum Anda mulai streaming. +Anda juga dapat menggunakan metode `streamWithHeaders()` untuk mengatur header sebelum Anda mulai streaming. ```php Flight::route('/stream-users', function() { - // Anda bisa menambahkan header tambahan apa pun yang Anda inginkan di sini - // Anda hanya harus menggunakan header() atau Flight::response()->setRealHeader() + // you can add any additional headers you want here + // you just must use header() or Flight::response()->setRealHeader() - // bagaimanapun Anda menarik data Anda, hanya sebagai contoh... + // however you pull your data, just as an example... $users_stmt = Flight::db()->query("SELECT id, first_name, last_name FROM users"); echo '{'; @@ -653,55 +729,53 @@ Flight::route('/stream-users', function() { echo ','; } - // Ini diperlukan untuk mengirim data ke klien + // This is required to send the data to the client ob_flush(); } echo '}'; -// Ini cara Anda menetapkan header sebelum Anda mulai streaming. +// This is how you'll set the headers before you start streaming. })->streamWithHeaders([ 'Content-Type' => 'application/json', 'Content-Disposition' => 'attachment; filename="users.json"', - // kode status opsional, default ke 200 + // optional status code, defaults to 200 'status' => 200 ]); ``` -## Lihat Juga +## See Also - [Middleware](/learn/middleware) - Menggunakan middleware dengan rute untuk autentikasi, logging, dll. - [Dependency Injection](/learn/dependency-injection-container) - Menyederhanakan pembuatan dan pengelolaan objek di rute. - [Why a Framework?](/learn/why-frameworks) - Memahami manfaat menggunakan framework seperti Flight. - [Extending](/learn/extending) - Cara memperluas Flight dengan fungsionalitas sendiri termasuk metode `notFound`. - [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - Fungsi PHP untuk pencocokan ekspresi reguler. -## Pemecahan Masalah +## Troubleshooting - Parameter rute dicocokkan berdasarkan urutan, bukan nama. Pastikan urutan parameter callback cocok dengan definisi rute. - Menggunakan `Flight::get()` tidak mendefinisikan rute; gunakan `Flight::route('GET /...')` untuk routing atau konteks objek Router di grup (misalnya `$router->get(...)`). -- Properti executedRoute hanya ditetapkan setelah rute dieksekusi; itu NULL sebelum eksekusi. +- Properti executedRoute hanya diatur setelah rute dieksekusi; itu NULL sebelum eksekusi. - Streaming memerlukan fungsionalitas output buffering Flight lama dinonaktifkan (`flight.v2.output_buffering = false`). -- Untuk injeksi dependensi, hanya definisi rute tertentu yang mendukung instansiasi berbasis container. +- Untuk injeksi dependensi, hanya definisi rute tertentu yang mendukung instansiasi berbasis wadah. -### 404 Tidak Ditemukan atau Perilaku Rute Tak Terduga +### 404 Not Found atau Perilaku Rute yang Tidak Terduga -Jika Anda melihat kesalahan 404 Tidak Ditemukan (tapi Anda bersumpah dengan nyawa Anda bahwa itu benar-benar ada dan bukan kesalahan ketik) ini sebenarnya bisa jadi masalah -dengan Anda mengembalikan nilai di endpoint rute Anda daripada hanya mengekstraknya. Alasan untuk ini disengaja tapi bisa menyelinap pada beberapa pengembang. +Jika Anda melihat kesalahan 404 Not Found (tetapi Anda bersumpah dengan hidup Anda bahwa itu benar-benar ada dan bukan kesalahan ketik) ini sebenarnya bisa menjadi masalah +dengan Anda mengembalikan nilai di endpoint rute Anda daripada hanya mencetaknya. Alasan untuk ini disengaja tetapi bisa menyelinap pada beberapa pengembang. ```php - Flight::route('/hello', function(){ - // Ini mungkin menyebabkan kesalahan 404 Tidak Ditemukan + // This might cause a 404 Not Found error return 'Hello World'; }); -// Yang mungkin Anda inginkan +// What you probably want Flight::route('/hello', function(){ echo 'Hello World'; }); - ``` Alasan untuk ini adalah karena mekanisme khusus yang dibangun ke dalam router yang menangani output return sebagai sinyal untuk "pergi ke rute berikutnya". -Anda bisa melihat perilaku yang didokumentasikan di bagian [Routing](/learn/routing#passing). +Anda dapat melihat perilaku yang didokumentasikan di bagian [Routing](/learn/routing#passing). ## Changelog - v3: Menambahkan routing sumber daya, alias rute, dan dukungan streaming, grup rute, dan dukungan middleware. diff --git a/content/v3/ja/awesome-plugins/apm.md b/content/v3/ja/awesome-plugins/apm.md index c979b98c..20194b6c 100644 --- a/content/v3/ja/awesome-plugins/apm.md +++ b/content/v3/ja/awesome-plugins/apm.md @@ -1,41 +1,43 @@ # FlightPHP APM ドキュメント -FlightPHP APM にようこそ—あなたのアプリのパーソナルパフォーマンスコーチです! このガイドは、Application Performance Monitoring (APM) を FlightPHP で設定し、使用し、習得するためのロードマップです。 遅いリクエストを追いかける場合でも、レイテンシチャートに熱中したい場合でも、私たちがカバーします。 アプリをより速くし、ユーザーをより幸せにし、デバッグセッションを簡単にするために進みましょう! +FlightPHP APM へようこそ—アプリのパーソナルパフォーマンスコーチです!このガイドは、FlightPHP を使用したアプリケーション パフォーマンス モニタリング (APM) の設定、使用、マスターするためのロードマップです。遅いリクエストを追跡したり、レイテンシ チャートに没頭したりするかどうかにかかわらず、私たちがカバーします。アプリを速くし、ユーザーを幸せにし、デバッグ セッションを楽にしましょう! + +Flight Docs サイトのダッシュボードの [デモ](https://flightphp-docs-apm.sky-9.com/apm/dashboard) をご覧ください。 ![FlightPHP APM](/images/apm.png) -## APM の重要性 +## APM が重要な理由 -想像してみてください:あなたのアプリは忙しいレストランです。 オーダーにどれだけ時間がかかるかを追跡する方法がない、またはキッチンがどこで詰まっているのかわからない場合、顧客が不機嫌になって去る理由を推測するだけです。 APM はあなたの副料理長のようなものです—着信リクエストからデータベースクエリまですべてのステップを監視し、遅延を引き起こすものをフラグします。 遅いページはユーザーを失います(研究によると、サイトの読み込みに 3 秒以上かかると 53% が離脱します!)、そして APM はそれらの問題を *事前に* キャッチします。 これは積極的な安心—「なぜこれは壊れているの?」という瞬間を少なくし、「これがどれほどスムーズに動くか!」という勝利を増やします。 +これを想像してください:アプリが忙しいレストランです。注文にかかる時間を追跡したり、キッチンがどこで詰まっているかを追跡する方法がないと、顧客が不機嫌になって去る理由を推測するだけです。APM はあなたの副シェフです—受信リクエストからデータベース クエリまで、すべてのステップを監視し、遅延を引き起こすものをフラグ付けします。遅いページはユーザーを失います(研究によると、サイトの読み込みに 3 秒以上かかると 53% がバウンス!)、APM はそれらの問題を *事前に* キャッチするのに役立ちます。それは積極的な安心感です—「これが壊れているのはなぜ?」という瞬間が少なくなり、「これがどれだけスムーズに動作するか見て!」という勝利が増えます。 ## インストール -Composer で始めましょう: +Composer で開始してください: ```bash composer require flightphp/apm ``` 必要なもの: -- **PHP 7.4+**: LTS Linux ディストリビューションとの互換性を保ちつつ、現代的な PHP をサポートします。 -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: 私たちがブーストする軽量フレームワークです。 +- **PHP 7.4+**:LTS Linux ディストリビューションとの互換性を保ちつつ、モダンな PHP をサポートします。 +- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**:私たちが強化する軽量フレームワークです。 -## サポートされているデータベース +## サポートされるデータベース -FlightPHP APM は、現在、以下のデータベースをメトリクスの保存にサポートしています: +FlightPHP APM は、現在、指標を保存するための以下のデータベースをサポートしています: -- **SQLite3**: シンプルでファイルベースのもの、または小規模アプリのローカル開発に最適。 ほとんどのセットアップでデフォルトのオプションです。 -- **MySQL/MariaDB**: 大規模プロジェクトやプロダクション環境で堅牢でスケーラブルなストレージが必要な場合に理想的です。 +- **SQLite3**:シンプルでファイルベースで、ローカル開発や小規模アプリに最適です。ほとんどのセットアップでデフォルト オプションです。 +- **MySQL/MariaDB**:大規模プロジェクトや本番環境で堅牢でスケーラブルなストレージが必要な場合に理想的です。 -構成ステップ(以下を参照)でデータベースの種類を選択できます。 PHP 環境に必要な拡張(例: `pdo_sqlite` または `pdo_mysql`)をインストールされていることを確認してください。 +構成ステップ(以下を参照)でデータベース タイプを選択できます。PHP 環境に必要な拡張機能がインストールされていることを確認してください(例:`pdo_sqlite` または `pdo_mysql`)。 -## 始め方 +## 開始方法 -APM の素晴らしさをステップバイステップで: +APM の素晴らしさへのステップバイステップです: ### 1. APM を登録する -`index.php` または `services.php` ファイルにこれを追加して追跡を開始します: +`index.php` または `services.php` ファイルにこれを追加して追跡を開始してください: ```php use flight\apm\logger\LoggerFactory; @@ -45,38 +47,38 @@ $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); $Apm = new Apm($ApmLogger); $Apm->bindEventsToFlightInstance($app); -// もしデータベース接続を追加する場合 -// これは Tracy Extensions からの PdoWrapper または PdoQueryCapture でなければなりません -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True を指定して APM での追跡を有効にします。 +// データベース接続を追加する場合 +// Tracy Extensions からの PdoWrapper または PdoQueryCapture である必要があります +$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- APM で追跡を有効にするために True が必要です。 $Apm->addPdoConnection($pdo); ``` -**ここで何が起こっているのか?** -- `LoggerFactory::create()` はあなたの構成を入手し(すぐに詳しく)、ロガーをセットアップします—デフォルトで SQLite。 -- `Apm` はスター—it は Flight のイベント(リクエスト、ルート、エラーなど)を監視し、メトリクスを収集します。 -- `bindEventsToFlightInstance($app)` はすべてを Flight アプリに結びつけます。 +**ここで何が起こっていますか?** +- `LoggerFactory::create()` は構成を取得(まもなく詳述)し、ロガーをセットアップします—デフォルトで SQLite です。 +- `Apm` はスターです—Flight のイベント(リクエスト、ルート、エラーなど)を監視し、指標を収集します。 +- `bindEventsToFlightInstance($app)` はこれをすべて Flight アプリに結びつけます。 -**プロチップ: サンプリング** -アプリが忙しい場合、*すべての* リクエストをログに残すとオーバーロードになる可能性があります。 サンプル率(0.0 から 1.0)を使用します: +**プロ ティップ: サンプリング** +アプリが忙しい場合、*すべての* リクエストをログにするとオーバーロードする可能性があります。サンプル レート(0.0 から 1.0)を使用してください: ```php -$Apm = new Apm($ApmLogger, 0.1); // 10% のリクエストをログに残します +$Apm = new Apm($ApmLogger, 0.1); // リクエストの 10% をログにします ``` -これでパフォーマンスを維持しつつ、しっかりしたデータを取得できます。 +これにより、パフォーマンスを維持しつつ、堅実なデータを取得できます。 -### 2. それを構成する +### 2. 構成する -`.runway-config.json` を作成するためにこれを実行します: +`.runway-config.json` を作成するためにこれを実行してください: ```bash php vendor/bin/runway apm:init ``` -**これは何をするのか?** -- 生のメトリクスのソースと処理されたデータの宛先を尋ねるウィザードを起動します。 -- デフォルトは SQLite—例: `sqlite:/tmp/apm_metrics.sqlite` がソース、もう一つが宛先。 -- 以下のような構成ができます: +**これは何をしますか?** +- 生の指標のソース(source)と処理されたデータの宛先(destination)を尋ねるウィザードを起動します。 +- デフォルトは SQLite—例:ソース用に `sqlite:/tmp/apm_metrics.sqlite`、宛先用に別のもの。 +- 次のような構成が得られます: ```json { "apm": { @@ -88,123 +90,123 @@ php vendor/bin/runway apm:init } ``` -> このプロセスは、このセットアップの移行を実行するかどうかを尋ねます。 初めて設定する場合、答えは yes です。 +> このプロセスは、このセットアップのマイグレーションを実行するかどうかも尋ねます。初めて設定する場合、答えは yes です。 -**なぜ 2 つの場所が必要なのか?** -生のメトリクスは急速に積み上がります(フィルタリングされていないログを考えて)。 ワーカーがそれを構造化された宛先でダッシュボード用に処理します。 すべてを整頓します! +**なぜ 2 つの場所ですか?** +生の指標は急速に蓄積されます(フィルタリングされていないログを想像してください)。ワーカーがこれを構造化された宛先のダッシュボードに処理します。整理を保ちます! -### 3. ワーカーでメトリクスを処理する +### 3. ワーカーで指標を処理する -ワーカーは生のメトリクスをダッシュボード対応のデータに変換します。 1 度実行します: +ワーカーは生の指標をダッシュボード対応データに変換します。一度実行してください: ```bash php vendor/bin/runway apm:worker ``` -**これは何をしているのか?** -- ソース(例: `apm_metrics.sqlite`)から読み込みます。 -- 最大 100 メトリクス(デフォルトのバッチサイズ)を宛先に処理します。 -- 完了するか、メトリクスが残っていない場合に停止します。 +**何をしていますか?** +- ソースから読み込みます(例:`apm_metrics.sqlite`)。 +- 最大 100 指標(デフォルト バッチ サイズ)を宛先に処理します。 +- 完了するか、指標が残っていない場合に停止します。 -**それを継続的に実行する** -ライブアプリの場合、継続的な処理を望むでしょう。 オプションは: +**継続実行する** +ライブ アプリの場合、継続的な処理を望みます。オプションはこちらです: -- **デーモンモード**: +- **デーモン モード**: ```bash php vendor/bin/runway apm:worker --daemon ``` - 常に実行し、到着したメトリクスを処理します。 開発や小規模セットアップに最適。 + 指標が来るたびに永遠に実行します。開発や小規模セットアップに最適です。 -- **Crontab**: - あなたの crontab にこれを追加(`crontab -e`): +- **Crontab**: + crontab に追加してください(`crontab -e`): ```bash * * * * * php /path/to/project/vendor/bin/runway apm:worker ``` - 毎分実行—プロダクションに最適。 + 毎分実行—本番に最適です。 -- **Tmux/Screen**: +- **Tmux/Screen**: 分離可能なセッションを開始: ```bash tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon - # Ctrl+B, then D で分離; `tmux attach -t apm-worker` で再接続 + # Ctrl+B, 続いて D で分離;`tmux attach -t apm-worker` で再接続 ``` - ログアウトしても実行を継続。 + ログアウトしても実行を続けます。 -- **カスタム調整**: +- **カスタム調整**: ```bash php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 ``` - - `--batch_size 50`: 50 メトリクスを一度に処理。 - - `--max_messages 1000`: 1000 メトリクス後に停止。 - - `--timeout 300`: 5 分後に終了。 + - `--batch_size 50`:一度に 50 指標を処理。 + - `--max_messages 1000`:1000 指標後に停止。 + - `--timeout 300`:5 分後に終了。 -**なぜそれが必要なのか?** -ワーカーがないと、ダッシュボードは空です。 これは生のログと実用的な洞察の間の架け橋です。 +**なぜ面倒を見るのですか?** +ワーカーがないと、ダッシュボードは空です。生のログと実用的な洞察の橋渡しです。 ### 4. ダッシュボードを起動する -アプリのバイタルサインを表示: +アプリのバイタル サインを表示: ```bash php vendor/bin/runway apm:dashboard ``` -**これは何?** -- `http://localhost:8001/apm/dashboard` で PHP サーバーを起動。 -- リクエストログ、遅いルート、エラーレートなどを表示。 +**これは何ですか?** +- `http://localhost:8001/apm/dashboard` で PHP サーバーを起動します。 +- リクエスト ログ、遅いルート、エラー レートなどを表示します。 -**それをカスタマイズ**: +**カスタマイズ**: ```bash php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php ``` -- `--host 0.0.0.0`: 任意の IP からアクセス可能(リモート表示に便利)。 -- `--port 8080`: 8001 が使用中の場合、異なるポートを使用。 -- `--php-path`: PATH にない場合、PHP を指す。 +- `--host 0.0.0.0`:任意の IP からアクセス可能(リモート表示に便利)。 +- `--port 8080`:8001 が使用されている場合に別のポートを使用。 +- `--php-path`:PATH にない場合に PHP を指定。 -ブラウザで URL を開いて探検! +ブラウザで URL にアクセスして探索してください! -#### プロダクションモード +#### 本番モード -プロダクションでは、ファイアウォールや他のセキュリティ対策があるため、ダッシュボードを実行するためにいくつかの手法を試す必要があるかもしれません。 オプションは: +本番では、ファイアウォールや他のセキュリティ対策があるため、ダッシュボードを実行するためにいくつかのテクニックを試す必要があるかもしれません。オプションはこちらです: -- **リバースプロキシを使用**: Nginx または Apache を設定してリクエストをダッシュボードに転送。 -- **SSH トンネル**: サーバーに SSH でアクセスできる場合、`ssh -L 8080:localhost:8001 youruser@yourserver` を使用してダッシュボードをローカルマシンにトンネル。 -- **VPN**: サーバーが VPN の背後にあり、接続して直接ダッシュボードにアクセス。 -- **ファイアウォールを構成**: ポート 8001 をあなたの IP またはサーバーのネットワーク用に開く(または設定したポート)。 -- **Apache/Nginx を構成**: アプリケーションの前にウェブサーバーがある場合、ドメインまたはサブドメインに構成。 これを行う場合、文書ルートを `/path/to/your/project/vendor/flightphp/apm/dashboard` に設定。 +- **リバース プロキシを使用**:Nginx または Apache をセットアップして、ダッシュボードへのリクエストを転送します。 +- **SSH トンネル**:サーバーに SSH でアクセスできる場合、`ssh -L 8080:localhost:8001 youruser@yourserver` を使用して、ダッシュボードをローカル マシンにトンネルします。 +- **VPN**:サーバーが VPN の背後にある場合、それに接続してダッシュボードに直接アクセスします。 +- **ファイアウォール構成**:ポート 8001 を自分の IP またはサーバーのネットワーク用に開放します。(または設定したポート)。 +- **Apache/Nginx 構成**:アプリケーションの前にウェブ サーバーがある場合、ドメインまたはサブドメインに構成できます。これを行う場合、ドキュメント ルートを `/path/to/your/project/vendor/flightphp/apm/dashboard` に設定します。 -#### 異なるダッシュボードを望む? +#### 別のダッシュボードが欲しいですか? -独自のダッシュボードを作成できます! vendor/flightphp/apm/src/apm/presenter ディレクトリを調べて、データを表示するためのアイデアを得てください! +自分のダッシュボードを構築できます!vendor/flightphp/apm/src/apm/presenter ディレクトリを参照して、自分のダッシュボードでデータを提示する方法のアイデアを得てください! ## ダッシュボードの機能 -ダッシュボードはあなたの APM HQ—以下が見えます: +ダッシュボードは APM の本部です—ここで見えるものは: -- **リクエストログ**: タイムスタンプ、URL、レスポンスコード、合計時間を持つすべてのリクエスト。 「詳細」をクリックしてミドルウェア、クエリ、エラーを表示。 -- **最も遅いリクエスト**: 時間を消費するトップ 5 リクエスト(例: 「/api/heavy」 at 2.5s)。 -- **最も遅いルート**: 平均時間によるトップ 5 ルート—パターンを特定するのに最適。 -- **エラーレート**: 失敗するリクエストの割合(例: 2.3% 500s)。 -- **レイテンシパーセンタイル**: 95th (p95) と 99th (p99) レスポンス時間—最悪のシナリオを知る。 -- **レスポンスコードチャート**: 時間経過による 200s、404s、500s の視覚化。 -- **長いクエリ/ミドルウェア**: トップ 5 の遅いデータベース呼び出しとミドルウェアレイヤー。 -- **キャッシュヒット/ミス**: キャッシュが活躍する頻度。 +- **リクエスト ログ**:タイムスタンプ、URL、レスポンス コード、合計時間付きのすべてのリクエスト。「詳細」をクリックしてミドルウェア、クエリ、エラーを表示。 +- **最も遅いリクエスト**:時間を消費する上位 5 つのリクエスト(例:`/api/heavy` が 2.5s)。 +- **最も遅いルート**:平均時間による上位 5 つのルート—パターンを特定するのに最適。 +- **エラー レート**:失敗するリクエストのパーセンテージ(例:2.3% の 500s)。 +- **レイテンシ パーセンタイル**:95 番目 (p95) と 99 番目 (p99) のレスポンス時間—最悪の場合のシナリオを知る。 +- **レスポンス コード チャート**:時間経過による 200s、404s、500s を可視化。 +- **長いクエリ/ミドルウェア**:上位 5 つの遅いデータベース コールとミドルウェア レイヤー。 +- **キャッシュ ヒット/ミス**:キャッシュがどれだけ役立つか。 -**エクストラ**: -- 「直近 1 時間」「直近 1 日」「直近 1 週間」でフィルタリング。 -- 深夜セッション用のダークモードを切り替え。 +**追加機能**: +- 「最終 1 時間」、「最終 1 日」、「最終 1 週間」でフィルタリング。 +- 深夜のセッション用にダーク モードを切り替え。 -**例**: -`/users` へのリクエストは次のように表示: +**例**: +`/users` へのリクエストは以下を表示するかもしれません: - 合計時間: 150ms - ミドルウェア: `AuthMiddleware->handle` (50ms) - クエリ: `SELECT * FROM users` (80ms) -- キャッシュ: `user_list` のヒット (5ms) +- キャッシュ: `user_list` でヒット (5ms) -## カスタムイベントの追加 +## カスタム イベントの追加 -API 呼び出しや支払いプロセスなど、任意のものを追跡: +API コールや支払いプロセスなど、何でも追跡: ```php use flight\apm\CustomEvent; @@ -216,10 +218,10 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ])); ``` -**どこに表示されるのか?** -ダッシュボードのリクエスト詳細の下の「カスタムイベント」—展開可能できれいな JSON フォーマット。 +**どこに表示されますか?** +ダッシュボードのリクエスト詳細の「カスタム イベント」下—プリティ JSON 形式で展開可能。 -**使用例**: +**使用例**: ```php $start = microtime(true); $apiResponse = file_get_contents('https://api.example.com/data'); @@ -229,60 +231,60 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -これでその API がアプリを引き下げるかどうかを確認できます! +これで、その API がアプリを遅くしているかどうかを確認できます! -## データベース監視 +## データベース モニタリング PDO クエリをこのように追跡: ```php use flight\database\PdoWrapper; -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True を指定して APM での追跡を有効にします。 +$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- APM で追跡を有効にするために True が必要です。 $Apm->addPdoConnection($pdo); ``` -**何を得るのか**: -- クエリテキスト(例: `SELECT * FROM users WHERE id = ?`) -- 実行時間(例: 0.015s) -- 行数(例: 42) +**何が得られますか?** +- クエリ テキスト(例:`SELECT * FROM users WHERE id = ?`) +- 実行時間(例:0.015s) +- 行数(例:42) -**注意**: -- **オプション**: DB 追跡が必要ない場合、スキップ。 -- **PdoWrapper のみ**: コア PDO はまだフックされていません—待機中! -- **パフォーマンス警告**: DB が重いサイトですべてのクエリをログに残すと遅くなる可能性があります。 サンプリング(`$Apm = new Apm($ApmLogger, 0.1)`)を使用して負荷を軽減。 +**注意**: +- **オプション**:DB 追跡が必要ない場合スキップ。 +- **PdoWrapper のみ**:コア PDO はまだフックされていません—続報をお待ちください! +- **パフォーマンス警告**:DB 重いサイトですべてのクエリをログにすると遅くなる可能性があります。サンプリング(`$Apm = new Apm($ApmLogger, 0.1)`)を使用して負荷を軽減。 -**例の出力**: +**出力例**: - クエリ: `SELECT name FROM products WHERE price > 100` - 時間: 0.023s - 行: 15 -## ワーカーオプション +## ワーカーのオプション ワーカーを好みに調整: -- `--timeout 300`: 5 分後に停止—テストに良い。 -- `--max_messages 500`: 500 メトリクスでキャップ。 -- `--batch_size 200`: 200 を一度に処理—速度とメモリのバランス。 -- `--daemon`: 止まらず実行—ライブ監視に理想的。 +- `--timeout 300`:5 分後に停止—テストに適しています。 +- `--max_messages 500`:500 指標で上限—有限に保ちます。 +- `--batch_size 200`:一度に 200 を処理—速度とメモリのバランス。 +- `--daemon`:非停止で実行—ライブ モニタリングに理想的。 -**例**: +**例**: ```bash php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ``` -1 時間実行し、100 メトリクスを一度に処理。 +1 時間実行、一度に 100 指標を処理。 ## アプリ内のリクエスト ID -各リクエストに一意のリクエスト ID が付与され、ログとメトリクスの相関に使用できます。 例: エラーページにリクエスト ID を追加: +各リクエストには追跡のためのユニークなリクエスト ID があります。この ID をアプリで使用してログと指標を相関させることができます。例えば、エラー ページにリクエスト ID を追加できます: ```php Flight::map('error', function($message) { - // レスポンスヘッダー X-Flight-Request-Id からリクエスト ID を取得 + // レスポンス ヘッダー X-Flight-Request-Id からリクエスト ID を取得 $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); // また、Flight 変数から取得することもできます - // この方法は swoole や他の非同期プラットフォームではうまく動作しない可能性があります。 + // この方法は swoole や他の非同期プラットフォームではうまく動作しません。 // $requestId = Flight::get('apm.request_id'); echo "Error: $message (Request ID: $requestId)"; @@ -291,55 +293,55 @@ Flight::map('error', function($message) { ## アップグレード -APM の新しいバージョンにアップグレードする場合、データベースの移行を実行する必要がある可能性があります。 以下のコマンドで実行: +APM の新しいバージョンにアップグレードする場合、データベース マイグレーションを実行する必要がある可能性があります。以下のコマンドを実行してこれを行います: ```bash php vendor/bin/runway apm:migrate ``` -これはデータベーススキーマを最新バージョンに更新するための必要な移行を実行します。 +これにより、データベース スキーマを最新バージョンに更新するために必要なすべてのマイグレーションが実行されます。 -**注記:** APM データベースが大きい場合、これらの移行には時間がかかる可能性があります。 オフピーク時に実行することを検討してください。 +**注意:** APM データベースのサイズが大きい場合、これらのマイグレーションは実行に時間がかかる可能性があります。オフピーク時間にこのコマンドを実行することを検討してください。 ## 古いデータの消去 -データベースを整頓するために、古いデータを消去できます。 これは忙しいアプリを実行していて、データベースのサイズを管理したい場合に特に便利です。 -以下のコマンドで実行: +データベースを整理するために、古いデータを消去できます。これは、忙しいアプリを実行していてデータベースのサイズを管理しやすくしたい場合に特に有用です。 +以下のコマンドを実行してこれを行います: ```bash php vendor/bin/runway apm:purge ``` -これはデータベースから 30 日より古いすべてのデータを削除します。 `--days` オプションで日数を調整: +これにより、データベースから 30 日より古いすべてのデータが削除されます。`--days` オプションに異なる値を渡すことで、日数を調整できます: ```bash php vendor/bin/runway apm:purge --days 7 ``` -これは 7 日より古いすべてのデータを削除します。 +これにより、データベースから 7 日より古いすべてのデータが削除されます。 ## トラブルシューティング -困った? これを試してください: +困っていますか?これを試してください: - **ダッシュボードにデータがない?** - - ワーカーが実行中か? `ps aux | grep apm:worker` で確認。 - - 構成パスが一致するか? `.runway-config.json` の DSN が実際のファイルを示しているか確認。 - - `php vendor/bin/runway apm:worker` を手動で実行して保留中のメトリクスを処理。 + - ワーカーが実行中ですか?`ps aux | grep apm:worker` をチェック。 + - 構成パスが一致しますか?`.runway-config.json` の DSN が実際のファイルにポイントしていることを確認。 + - 保留中の指標を処理するために `php vendor/bin/runway apm:worker` を手動で実行。 -- **ワーカーエラー?** - - SQLite ファイルを覗く(例: `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`)。 - - PHP ログでスタックトレースを確認。 +- **ワーカーのエラー?** + - SQLite ファイルを確認(例:`sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`)。 + - PHP ログでスタック トレースを確認。 -- **ダッシュボードが起動しない?** - - ポート 8001 が使用中か? `--port 8080` を使用。 - - PHP が見つからない? `--php-path /usr/bin/php` を使用。 - - ファイアウォールがブロック? ポートを開くか `--host localhost` を使用。 +- **ダッシュボードが開始されない?** + - ポート 8001 が使用中?`--port 8080` を使用。 + - PHP が見つからない?`--php-path /usr/bin/php` を使用。 + - ファイアウォールがブロック?ポートを開放するか、`--host localhost` を使用。 - **遅すぎる?** - - サンプル率を下げる: `$Apm = new Apm($ApmLogger, 0.05)` (5%)。 - - バッチサイズを減らす: `--batch_size 20`。 + - サンプル レートを下げる:`$Apm = new Apm($ApmLogger, 0.05)` (5%)。 + - バッチ サイズを減らす:`--batch_size 20`。 -- **例外/エラーを追跡していない?** - - [Tracy](https://tracy.nette.org/) がプロジェクトで有効になっている場合、Flight のエラー処理をオーバーライドします。 Tracy を無効にし、`Flight::set('flight.handle_errors', true);` を設定。 +- **例外/エラーが追跡されない?** + - プロジェクトで [Tracy](https://tracy.nette.org/) が有効の場合、Flight のエラー処理をオーバーライドします。Tracy を無効にして、`Flight::set('flight.handle_errors', true);` が設定されていることを確認してください。 -- **データベースクエリを追跡していない?** - - `PdoWrapper` をデータベース接続で使用していることを確認。 +- **データベース クエリが追跡されない?** + - データベース接続に `PdoWrapper` を使用していることを確認。 - コンストラクタの最後の引数を `true` にしていることを確認。 \ No newline at end of file diff --git a/content/v3/ja/learn/ai.md b/content/v3/ja/learn/ai.md index fe2c7c05..d5fd5579 100644 --- a/content/v3/ja/learn/ai.md +++ b/content/v3/ja/learn/ai.md @@ -1,48 +1,48 @@ -# Flight での AI と開発者エクスペリエンス +# Flight を使った AI と開発者エクスペリエンス ## 概要 -Flight は、AI 駆動のツールと現代的な開発者ワークフローで PHP プロジェクトを強化することを容易にします。LLM (Large Language Model) プロバイダへの接続のための組み込みコマンドと、プロジェクト固有の AI コーディング指示を生成するためのコマンドにより、Flight は GitHub Copilot、Cursor、Windsurf などの AI アシスタントを最大限に活用するのに役立ちます。 +Flight は、AI 駆動のツールと現代的な開発者ワークフローを使用して PHP プロジェクトを強化することを容易にします。LLM (Large Language Model) プロバイダへの接続やプロジェクト固有の AI コーディング指示の生成のための組み込みコマンドにより、Flight は GitHub Copilot、Cursor、Windsurf などの AI アシスタントから最大限の効果を得るのをあなたとあなたのチームを支援します。 ## 理解 -AI コーディングアシスタントは、プロジェクトのコンテキスト、慣習、目標を理解しているときに最も役立ちます。Flight の AI ヘルパーを使用すると、次のことができます: -- プロジェクトを人気の LLM プロバイダ (OpenAI、Grok、Claude など) に接続 -- AI ツール向けのプロジェクト固有の指示を生成および更新し、一貫性のある関連性の高いヘルプを提供 -- チームを揃え、生産性を維持し、コンテキストの説明に費やす時間を減らす +AI コーディングアシスタントは、プロジェクトのコンテキスト、慣習、目標を理解しているときに最も役立ちます。Flight の AI ヘルパーは以下のことを可能にします: +- プロジェクトを人気の LLM プロバイダ (OpenAI、Grok、Claude など) に接続する +- AI ツール向けのプロジェクト固有の指示を生成および更新する。これにより、誰もが一貫した関連性の高いヘルプを得られる +- コンテキストの説明に費やす時間を減らし、チームを一致させ生産性を高める これらの機能は、Flight コア CLI と公式の [flightphp/skeleton](https://github.com/flightphp/skeleton) スタータープロジェクトに組み込まれています。 ## 基本的な使用方法 -### 1. LLM 認証情報の設定 +### LLM 認証情報の設定 -`ai:init` コマンドは、プロジェクトを LLM プロバイダに接続するための手順を案内します。 +`ai:init` コマンドは、プロジェクトを LLM プロバイダに接続するためのガイドを提供します。 ```bash php runway ai:init ``` -プロンプトで次のように求められます: +以下のプロンプトが表示されます: - プロバイダを選択 (OpenAI、Grok、Claude など) - API キーを入力 - ベース URL とモデル名を設定 -これにより、プロジェクトルートに `.runway-creds.json` ファイルが作成され (`.gitignore` に追加されることを確認)、。 +これにより、プロジェクトルートに `.runway-creds.json` ファイルが作成され (`.gitignore` に含まれることを確認)、。 **例:** ``` Welcome to AI Init! -どの LLM API を使用しますか? [1] openai, [2] grok, [3] claude: 1 -LLM API のベース URL を入力 [https://api.openai.com]: -openai の API キーを入力: sk-... -使用するモデル名を入力 (例: gpt-4, claude-3-opus など) [gpt-4o]: -.runway-creds.json に認証情報を保存しました +Which LLM API do you want to use? [1] openai, [2] grok, [3] claude: 1 +Enter the base URL for the LLM API [https://api.openai.com]: +Enter your API key for openai: sk-... +Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: +Credentials saved to .runway-creds.json ``` -### 2. プロジェクト固有の AI 指示の生成 +### プロジェクト固有の AI 指示の生成 -`ai:generate-instructions` コマンドは、プロジェクトに合わせて調整された AI コーディングアシスタント向けの指示を作成または更新するのに役立ちます。 +`ai:generate-instructions` コマンドは、プロジェクトに合わせた AI コーディングアシスタント向けの指示を作成または更新するのを支援します。 ```bash php runway ai:generate-instructions @@ -55,21 +55,21 @@ php runway ai:generate-instructions **例:** ``` -プロジェクトの目的を説明してください? My awesome API -どのデータベースを使用する予定ですか? MySQL -どの HTML テンプレートエンジンを使用する予定ですか (該当する場合)? latte -このプロジェクトでセキュリティが重要な要素ですか? (y/n) y +Please describe what your project is for? My awesome API +What database are you planning on using? MySQL +What HTML templating engine will you plan on using (if any)? latte +Is security an important element of this project? (y/n) y ... -AI 指示を正常に更新しました。 +AI instructions updated successfully. ``` -これで、AI ツールはプロジェクトの実ニーズに基づいた、より賢く関連性の高い提案を提供します。 +これで、AI ツールはプロジェクトの実ニーズに基づいたより賢く関連性の高い提案を提供します。 ## 高度な使用方法 -- コマンドオプションを使用して、認証情報や指示ファイルの場所をカスタマイズできます (各コマンドの `--help` を参照)。 -- AI ヘルパーは、OpenAI 互換 API をサポートする任意の LLM プロバイダで動作するように設計されています。 -- プロジェクトが進化したら指示を更新したい場合、`ai:generate-instructions` を再実行してプロンプトに答えてください。 +- コマンドオプションを使用して認証情報や指示ファイルの場所をカスタマイズできます (各コマンドの `--help` を参照)。 +- AI ヘルパーは、OpenAI 互換 API をサポートする任意の LLM プロバイダで動作するよう設計されています。 +- プロジェクトが進化したら指示を更新したい場合、`ai:generate-instructions` を再実行してプロンプトに再度答えてください。 ## 関連項目 @@ -79,9 +79,9 @@ AI 指示を正常に更新しました。 ## トラブルシューティング - 「Missing .runway-creds.json」が表示された場合、まず `php runway ai:init` を実行してください。 -- API キーが有効で、選択したモデルにアクセス可能であることを確認してください。 -- 指示が更新されない場合、プロジェクトディレクトリのファイルパーミッションを確認してください。 +- API キーが有効で選択したモデルにアクセス可能であることを確認してください。 +- 指示が更新されない場合、プロジェクトディレクトリのファイル権限を確認してください。 ## 変更履歴 -- v3.16.0 – AI 統合のための `ai:init` と `ai:generate-instructions` CLI コマンドを追加。 \ No newline at end of file +- v3.16.0 – AI 統合のための `ai:init` および `ai:generate-instructions` CLI コマンドを追加。 \ No newline at end of file diff --git a/content/v3/ja/learn/requests.md b/content/v3/ja/learn/requests.md index 246e088f..2f32548d 100644 --- a/content/v3/ja/learn/requests.md +++ b/content/v3/ja/learn/requests.md @@ -10,13 +10,13 @@ $request = Flight::request(); ## 理解 -HTTP リクエストは、HTTP ライフサイクルの理解に不可欠なコア要素の一つです。ユーザーがウェブブラウザや HTTP クライアントでアクションを実行すると、ヘッダー、本文、URL などをプロジェクトに送信します。これらのヘッダー(ブラウザの言語、対応する圧縮タイプ、ユーザーエージェントなど)をキャプチャし、Flight アプリケーションに送信された本文と URL をキャプチャできます。これらのリクエストは、アプリが次に何をするかを理解するために不可欠です。 +HTTP リクエストは、HTTP ライフサイクルの理解に不可欠な核心的な要素の一つです。ユーザーがウェブブラウザや HTTP クライアントでアクションを実行すると、ヘッダー、本文、URL などをプロジェクトに送信します。これらのヘッダー(ブラウザの言語、扱える圧縮の種類、ユーザーエージェントなど)をキャプチャし、Flight アプリケーションに送信される本文と URL をキャプチャできます。これらのリクエストは、アプリが次に何をするかを理解するために不可欠です。 ## 基本的な使用方法 -PHP には、`$_GET`、`$_POST`、`$_REQUEST`、`$_SERVER`、`$_FILES`、`$_COOKIE` などのスーパーグローバルがあります。Flight はこれらを便利な [Collections](/learn/collections) に抽象化します。`query`、`data`、`cookies`、`files` プロパティを配列またはオブジェクトとしてアクセスできます。 +PHP には `$_GET`、`$_POST`、`$_REQUEST`、`$_SERVER`、`$_FILES`、`$_COOKIE` などのスーパーグローバル変数があります。Flight はこれらを便利な [Collections](/learn/collections) に抽象化します。`query`、`data`、`cookies`、`files` プロパティを配列またはオブジェクトとしてアクセスできます。 -> **注意:** プロジェクトでこれらのスーパーグローバルを使用することは**強く**推奨されず、`request()` オブジェクト経由で参照する必要があります。 +> **注意:** プロジェクトでこれらのスーパーグローバル変数を使用することは**強く**推奨されず、`request()` オブジェクト経由で参照する必要があります。 > **注意:** `$_ENV` の抽象化は利用できません。 @@ -30,8 +30,8 @@ Flight::route('/search', function(){ $keyword = Flight::request()->query['keyword']; // または $keyword = Flight::request()->query->keyword; - echo "You are searching for: $keyword"; - // $keyword でデータベースをクエリするか他の処理 + echo "検索中: $keyword"; + // $keyword でデータベースをクエリしたり、他の操作を行ったりします }); ``` @@ -46,8 +46,8 @@ Flight::route('POST /submit', function(){ // または $name = Flight::request()->data->name; $email = Flight::request()->data->email; - echo "You submitted: $name, $email"; - // $name と $email でデータベースに保存するか他の処理 + echo "送信された内容: $name, $email"; + // $name と $email でデータベースに保存したり、他の操作を行ったりします }); ``` @@ -60,7 +60,7 @@ Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; // または $savedLogin = Flight::request()->cookies->myLoginCookie; - // 本当に保存されているかをチェックし、保存されていれば自動ログイン + // 保存されているかどうかを確認し、保存されていれば自動的にログインします if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -68,7 +68,7 @@ Flight::route('GET /login', function(){ }); ``` -新しいクッキー値の設定に関するヘルプについては、[overclokk/cookie](/awesome-plugins/php-cookie) を参照してください。 +新しいクッキー値の設定方法については、[overclokk/cookie](/awesome-plugins/php-cookie) を参照してください。 ### `$_SERVER` @@ -83,7 +83,7 @@ $host = Flight::request()->getVar('HTTP_HOST'); アップロードされたファイルは `files` プロパティ経由でアクセスできます: ```php -// $_FILES プロパティへの生のアクセス。推奨アプローチは以下を参照 +// $_FILES プロパティへの直接アクセス。推奨されるアプローチは以下を参照 $uploadedFile = Flight::request()->files['myFile']; // または $uploadedFile = Flight::request()->files->myFile; @@ -95,7 +95,7 @@ $uploadedFile = Flight::request()->files->myFile; _v3.12.0_ -フレームワークを使用して、ヘルパーメソッドでファイルアップロードを処理できます。基本的に、リクエストからファイルデータを取得し、新しい場所に移動するだけです。 +フレームワークのヘルパーメソッドを使用してファイルアップロードを処理できます。基本的に、リクエストからファイルデータを取得し、新しい場所に移動させるだけです。 ```php Flight::route('POST /upload', function(){ @@ -106,7 +106,7 @@ Flight::route('POST /upload', function(){ }); ``` -複数のファイルがアップロードされた場合、ループで処理できます: +複数のファイルをアップロードした場合、それらをループで処理できます: ```php Flight::route('POST /upload', function(){ @@ -118,22 +118,22 @@ Flight::route('POST /upload', function(){ }); ``` -> **セキュリティ注意:** ユーザー入力の検証とサニタイズを常に実行してください。特にファイルアップロード時には、許可する拡張子のタイプを検証し、ファイルの「マジックバイト」を検証して、ユーザーが主張するファイルタイプが本物かを確認してください。このための [記事](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [や](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [ライブラリ](https://github.com/RikudouSage/MimeTypeDetector) が利用可能です。 +> **セキュリティ注意:** ユーザー入力の検証とサニタイズを常に実行してください。特にファイルアップロード時には、許可する拡張子の種類を検証し、ファイルの「マジックバイト」を検証して、ユーザーが主張するファイルの種類が本物であることを確認してください。このために [記事](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [や](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [ライブラリ](https://github.com/RikudouSage/MimeTypeDetector) が利用可能です。 ### リクエスト本文 -POST/PUT リクエストなどの生の HTTP リクエスト本文を取得するには、以下を実行できます: +POST/PUT リクエストなどで生の HTTP リクエスト本文を取得するには、以下のようにします: ```php Flight::route('POST /users/xml', function(){ $xmlBody = Flight::request()->getBody(); - // 送信された XML で何か処理。 + // 送信された XML で何らかの操作を行います。 }); ``` ### JSON 本文 -コンテンツタイプ `application/json` のリクエストを受け取り、例として `{"id": 123}` のデータの場合、`data` プロパティから利用可能です: +コンテンツタイプが `application/json` のリクエストで、例として `{"id": 123}` のデータを受け取った場合、`data` プロパティから利用可能です: ```php $id = Flight::request()->data->id; @@ -141,10 +141,10 @@ $id = Flight::request()->data->id; ### リクエストヘッダー -`getHeader()` または `getHeaders()` メソッドを使用してリクエストヘッダーにアクセスできます: +リクエストヘッダーは `getHeader()` または `getHeaders()` メソッドを使用してアクセスできます: ```php -// Authorization ヘッダーが必要な場合 +// Authorization ヘッダーが必要な場合など $host = Flight::request()->getHeader('Authorization'); // または $host = Flight::request()->header('Authorization'); @@ -157,26 +157,26 @@ $headers = Flight::request()->headers(); ### リクエストメソッド -`method` プロパティまたは `getMethod()` メソッドを使用してリクエストメソッドにアクセスできます: +リクエストメソッドは `method` プロパティまたは `getMethod()` メソッドを使用してアクセスできます: ```php -$method = Flight::request()->method; // 実際には getMethod() で設定 +$method = Flight::request()->method; // 実際には getMethod() で設定されます $method = Flight::request()->getMethod(); ``` -**注意:** `getMethod()` メソッドはまず `$_SERVER['REQUEST_METHOD']` からメソッドを取得し、存在する場合 `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` または `$_REQUEST['_method']` で上書きされます。 +**注意:** `getMethod()` メソッドは最初に `$_SERVER['REQUEST_METHOD']` からメソッドを取得し、存在する場合に `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` または `$_REQUEST['_method']` で上書きされます。 ## リクエストオブジェクトのプロパティ リクエストオブジェクトは以下のプロパティを提供します: - **body** - 生の HTTP リクエスト本文 -- **url** - リクエストされる URL +- **url** - リクエストされている URL - **base** - URL の親サブディレクトリ - **method** - リクエストメソッド (GET, POST, PUT, DELETE) - **referrer** - リファラー URL - **ip** - クライアントの IP アドレス -- **ajax** - リクエストが AJAX かどうかのフラグ +- **ajax** - リクエストが AJAX リクエストかどうか - **scheme** - サーバープロトコル (http, https) - **user_agent** - ブラウザ情報 - **type** - コンテンツタイプ @@ -185,19 +185,19 @@ $method = Flight::request()->getMethod(); - **data** - 投稿データまたは JSON データ - **cookies** - クッキーデータ - **files** - アップロードされたファイル -- **secure** - 接続がセキュアかどうかのフラグ -- **accept** - HTTP accept パラメータ +- **secure** - 接続がセキュアかどうか +- **accept** - HTTP アクセプトパラメータ - **proxy_ip** - クライアントのプロキシ IP アドレス。`$_SERVER` 配列を `HTTP_CLIENT_IP`、`HTTP_X_FORWARDED_FOR`、`HTTP_X_FORWARDED`、`HTTP_X_CLUSTER_CLIENT_IP`、`HTTP_FORWARDED_FOR`、`HTTP_FORWARDED` の順でスキャンします。 - **host** - リクエストホスト名 - **servername** - `$_SERVER` からの SERVER_NAME -## URL ヘルパーメソッド +## ヘルパーメソッド -URL の一部を便利に組み合わせるためのヘルパーメソッドがいくつかあります。 +URL の一部を組み合わせたり、特定のヘッダーを扱ったりするためのいくつかのヘルパーメソッドがあります。 -### 完全な URL +### フル URL -`getFullUrl()` メソッドを使用して完全なリクエスト URL にアクセスできます: +フルリクエスト URL は `getFullUrl()` メソッドを使用してアクセスできます: ```php $url = Flight::request()->getFullUrl(); @@ -206,13 +206,13 @@ $url = Flight::request()->getFullUrl(); ### ベース URL -`getBaseUrl()` メソッドを使用してベース URL にアクセスできます: +ベース URL は `getBaseUrl()` メソッドを使用してアクセスできます: ```php // http://example.com/path/to/something/cool?query=yes+thanks $url = Flight::request()->getBaseUrl(); // https://example.com -// 注意: 末尾のスラッシュなし。 +// 注意: 末尾のスラッシュはありません。 ``` ## クエリ解析 @@ -224,7 +224,29 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` -## 関連項目 +## コンテンツアクセプトタイプのネゴシエーション + +_v3.17.2_ + +`negotiateContentType()` メソッドを使用して、クライアントが送信した `Accept` ヘッダーに基づいて、最適なコンテンツタイプを決定できます。 + +```php +// 例: Accept ヘッダー: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// 以下でサポートするものを定義します。 +$availableTypes = ['application/json', 'application/xml']; +$typeToServe = Flight::request()->negotiateContentType($availableTypes); +if ($typeToServe === 'application/json') { + // JSON レスポンスを送信 +} elseif ($typeToServe === 'application/xml') { + // XML レスポンスを送信 +} else { + // デフォルトで他のものを送信するか、エラーをスロー +} +``` + +> **注意:** `Accept` ヘッダーに利用可能なタイプが見つからない場合、メソッドは `null` を返します。`Accept` ヘッダーが定義されていない場合、メソッドは `$availableTypes` 配列の最初のタイプを返します。 + +## 関連トピック - [Routing](/learn/routing) - ルートをコントローラーにマッピングし、ビューをレンダリングする方法。 - [Responses](/learn/responses) - HTTP レスポンスのカスタマイズ方法。 - [Why a Framework?](/learn/why-frameworks) - リクエストが全体像にどのように適合するか。 @@ -232,8 +254,9 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); - [Uploaded File Handler](/learn/uploaded-file) - ファイルアップロードの処理。 ## トラブルシューティング -- ウェブサーバーがプロキシ、ロードバランサーなどで後ろにある場合、`request()->ip` と `request()->proxy_ip` が異なる可能性があります。 +- `request()->ip` と `request()->proxy_ip` は、ウェブサーバーがプロキシ、ロードバランサーなどの背後にある場合に異なる可能性があります。 ## 変更履歴 -- v3.12.0 - リクエストオブジェクト経由でファイルアップロードを処理する機能を追加。 -- v1.0 - 初回リリース。 \ No newline at end of file +- v3.17.2 - negotiateContentType() を追加 +- v3.12.0 - リクエストオブジェクト経由でファイルアップロードを処理する機能を追加 +- v1.0 - 初回リリース \ No newline at end of file diff --git a/content/v3/ja/learn/responses.md b/content/v3/ja/learn/responses.md index ac056710..d9e73808 100644 --- a/content/v3/ja/learn/responses.md +++ b/content/v3/ja/learn/responses.md @@ -2,20 +2,20 @@ ## 概要 -Flight は、レスポンスヘッダーの一部を自動生成するのに役立ちますが、ユーザーに返す内容の大部分はあなたが制御します。ほとんどの場合、`response()` オブジェクトに直接アクセスしますが、Flight にはいくつかのヘルパーメソッドがあり、それらを使ってレスポンスヘッダーの一部を設定できます。 +Flight はレスポンスヘッダーの一部を生成するのを手伝いますが、ユーザーに返す内容のほとんどの制御はあなたが持ちます。通常は `response()` オブジェクトに直接アクセスしますが、Flight にはレスポンスヘッダーの一部を設定するためのヘルパーメソッドもあります。 ## 理解 -ユーザーが [request](/learn/requests) リクエストをアプリケーションに送信した後、それらに対して適切なレスポンスを生成する必要があります。彼らは、好みの言語、特定の種類の圧縮を扱えるかどうか、ユーザーエージェントなどを含む情報を送信しており、すべてを処理した後、適切なレスポンスを返します。これは、ヘッダーの設定、HTML や JSON のボディの出力、またはページへのリダイレクトを行うことです。 +ユーザーが [request](/learn/requests) リクエストをアプリケーションに送信した後、彼らに適切なレスポンスを生成する必要があります。彼らは好みの言語、特定の種類の圧縮を扱えるかどうか、ユーザーエージェントなどを含む情報を送信してきました。すべてを処理した後、適切なレスポンスを彼らに返します。これはヘッダーの設定、HTML や JSON のボディを出力、またはページへのリダイレクトです。 ## 基本的な使用方法 ### レスポンスボディの送信 -Flight は `ob_start()` を使用して出力をバッファリングします。これにより、`echo` や `print` を使用してユーザーにレスポンスを送信でき、Flight がそれをキャプチャして適切なヘッダーとともにユーザーに返します。 +Flight は出力のバッファリングに `ob_start()` を使用します。これにより、`echo` や `print` を使用してユーザーにレスポンスを送信でき、Flight がそれをキャプチャして適切なヘッダーと共にユーザーに返します。 ```php -// これは「Hello, World!」をユーザーのブラウザに送信します +// This will send "Hello, World!" to the user's browser Flight::route('/', function() { echo "Hello, World!"; }); @@ -29,34 +29,34 @@ Flight::route('/', function() { 代替として、`write()` メソッドを呼び出してボディに追加することもできます。 ```php -// これは「Hello, World!」をユーザーのブラウザに送信します +// This will send "Hello, World!" to the user's browser Flight::route('/', function() { - // 冗長ですが、必要なときに役立ちます + // verbose, but gets the job sometimes when you need it Flight::response()->write("Hello, World!"); - // この時点で設定したボディを取得したい場合 - // 以下のようにできます + // if you want to retrieve the body that you've set at this point + // you can do so like this $body = Flight::response()->getBody(); }); ``` ### JSON -Flight は JSON および JSONP レスポンスの送信をサポートします。JSON レスポンスを送信するには、JSON エンコードするデータを渡します: +Flight は JSON および JSONP レスポンスの送信をサポートします。JSON レスポンスを送信するには、JSON エンコードされるデータを渡します: ```php Flight::route('/@companyId/users', function(int $companyId) { - // 例としてデータベースからユーザーを取得する + // somehow pull out your users from a database for example $users = Flight::db()->fetchAll("SELECT id, first_name, last_name FROM users WHERE company_id = ?", [ $companyId ]); Flight::json($users); }); -// [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* 他のユーザー */ ] +// [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* more users */ ] ``` -> **注意:** デフォルトでは、Flight はレスポンスに `Content-Type: application/json` ヘッダーを送信します。また、JSON をエンコードする際に `JSON_THROW_ON_ERROR` および `JSON_UNESCAPED_SLASHES` フラグを使用します。 +> **Note:** By default, Flight will send a `Content-Type: application/json` header with the response. It will also use the flags `JSON_THROW_ON_ERROR` and `JSON_UNESCAPED_SLASHES` when encoding the JSON. -#### ステータスコード付きの JSON +#### ステータスコード付き JSON 2 番目の引数としてステータスコードを渡すこともできます: @@ -64,7 +64,7 @@ Flight::route('/@companyId/users', function(int $companyId) { Flight::json(['id' => 123], 201); ``` -#### プリティプリント付きの JSON +#### プリティプリント付き JSON 最後の位置に引数を渡してプリティプリントを有効にすることもできます: @@ -74,16 +74,16 @@ Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT); #### JSON 引数の順序変更 -`Flight::json()` は非常にレガシーメソッドですが、Flight の目標はプロジェクトの後方互換性を維持することです。引数の順序をよりシンプルな構文に変更したい場合、JSON メソッドを他の Flight メソッドと同様に [再マップ](/learn/extending) するだけで非常に簡単です: +`Flight::json()` は非常に古いメソッドですが、Flight の目標はプロジェクトの後方互換性を維持することです。引数の順序を変更してよりシンプルな構文を使用したい場合、JSON メソッドを他の Flight メソッドと同様に [remap](/learn/extending) するだけです: ```php Flight::map('json', function($data, $code = 200, $options = 0) { - // これで json() メソッドを使用する際に `true, 'utf-8'` を指定する必要がなくなります! + // now you don't have to `true, 'utf-8'` when using the json() method! Flight::_json($data, $code, true, 'utf-8', $options); } -// これで以下のように使用できます +// And now it can be used like this Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT); ``` @@ -91,18 +91,18 @@ Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT); _v3.10.0_ -JSON レスポンスを送信して実行を停止したい場合、`jsonHalt()` メソッドを使用できます。これは、承認の種類をチェックしており、ユーザーが承認されていない場合に JSON レスポンスを即座に送信し、既存のボディコンテンツをクリアして実行を停止するのに便利です。 +JSON レスポンスを送信して実行を停止したい場合、`jsonHalt()` メソッドを使用できます。これは、承認などのチェックを行い、ユーザーが承認されていない場合に JSON レスポンスを即座に送信し、既存のボディコンテンツをクリアして実行を停止するのに便利です。 ```php Flight::route('/users', function() { $authorized = someAuthorizationCheck(); - // ユーザーが承認されているかをチェック + // Check if the user is authorized if($authorized === false) { Flight::jsonHalt(['error' => 'Unauthorized'], 401); - // ここで exit; は必要ありません。 + // no exit; needed here. } - // ルートの残りを続行 + // Continue with the rest of the route }); ``` @@ -111,12 +111,12 @@ v3.10.0 以前では、以下のようにする必要がありました: ```php Flight::route('/users', function() { $authorized = someAuthorizationCheck(); - // ユーザーが承認されているかをチェック + // Check if the user is authorized if($authorized === false) { Flight::halt(401, json_encode(['error' => 'Unauthorized'])); } - // ルートの残りを続行 + // Continue with the rest of the route }); ``` @@ -134,7 +134,7 @@ Flight::route('/', function() { }); ``` -上記のユースケースは一般的ではありませんが、[middleware](/learn/middleware) で使用する場合により一般的になる可能性があります。 +上記の使用例は一般的ではないかもしれませんが、[middleware](/learn/middleware) で使用される場合に一般的になる可能性があります。 ### レスポンスボディに対するコールバックの実行 @@ -147,19 +147,19 @@ Flight::route('/users', function() { Flight::render('users_table', ['users' => $users]); }); -// これにより、すべてのルートのレスポンスを gzip します +// This will gzip all the responses for any route Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); ``` -複数のコールバックを追加でき、追加された順序で実行されます。これは任意の [callable](https://www.php.net/manual/en/language.types.callable.php) を受け入れるため、クラス配列 `[ $class, 'method' ]`、クロージャ `$strReplace = function($body) { str_replace('hi', 'there', $body); };`、または HTML コードを最小化する関数名 `'minify'` などを指定できます。 +複数のコールバックを追加でき、追加された順序で実行されます。これには任意の [callable](https://www.php.net/manual/en/language.types.callable.php) を受け入れるため、クラス配列 `[ $class, 'method' ]`、クロージャ `$strReplace = function($body) { str_replace('hi', 'there', $body); };`、または HTML コードを最小化するための関数名 `'minify'` などを渡せます。 -**注意:** `flight.v2.output_buffering` 設定オプションを使用している場合、ルートコールバックは動作しません。 +**Note:** Route callbacks will not work if you are using the `flight.v2.output_buffering` configuration option. #### 特定のルートコールバック -これを特定のルートにのみ適用したい場合、ルート自体でコールバックを追加できます: +これを特定のルートにのみ適用したい場合、ルート内でコールバックを追加できます: ```php Flight::route('/users', function() { @@ -167,7 +167,7 @@ Flight::route('/users', function() { $users = $db->fetchAll("SELECT * FROM users"); Flight::render('users_table', ['users' => $users]); - // これにより、このルートのレスポンスのみを gzip します + // This will gzip only the response for this route Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); @@ -176,20 +176,20 @@ Flight::route('/users', function() { #### ミドルウェアオプション -[middleware](/learn/middleware) を使用して、すべてのルートにコールバックを適用することもできます: +[middleware](/learn/middleware) を使用して、すべてのルートにコールバックをミドルウェア経由で適用することもできます: ```php // MinifyMiddleware.php class MinifyMiddleware { public function before() { - // ここで response() オブジェクトにコールバックを適用します。 + // Apply the callback here on the response() object. Flight::response()->addResponseBodyCallback(function($body) { return $this->minify($body); }); } protected function minify(string $body): string { - // ボディを最小化する + // minify the body somehow return $body; } } @@ -203,7 +203,7 @@ Flight::group('/users', function() { ### ステータスコード -`status` メソッドを使用してレスポンスのステータスコードを設定できます: +`status` メソッドを使用して、レスポンスのステータスコードを設定できます: ```php Flight::route('/@id', function($id) { @@ -228,10 +228,10 @@ Flight::response()->status(); // 200 `header` メソッドを使用して、レスポンスのコンテンツタイプなどのヘッダーを設定できます: ```php -// これは「Hello, World!」をプレーンテキストでユーザーのブラウザに送信します +// This will send "Hello, World!" to the user's browser in plain text Flight::route('/', function() { Flight::response()->header('Content-Type', 'text/plain'); - // または + // or Flight::response()->setHeader('Content-Type', 'text/plain'); echo "Hello, World!"; }); @@ -249,50 +249,52 @@ Flight::route('/login', function() { if($password !== $passwordConfirm) { Flight::redirect('/new/location'); - return; // 下記の機能が実行されないように必要です + return; // this is necessary so functionality below doesn't execute } - // 新しいユーザーを追加... + // add the new user... Flight::db()->runQuery("INSERT INTO users ...."); Flight::redirect('/admin/dashboard'); }); ``` -> **注意:** デフォルトでは、Flight は HTTP 303 ("See Other") ステータスコードを送信します。オプションでカスタムコードを設定できます: +> **Note:** By default Flight sends a HTTP 303 ("See Other") status code. You can optionally set a +custom code: ```php -Flight::redirect('/new/location', 301); // 永久 +Flight::redirect('/new/location', 301); // permanent ``` ### ルート実行の停止 -`halt` メソッドを呼び出して、フレームワークを停止し、任意の時点で即座に終了できます: +`halt` メソッドを呼び出して、任意の時点でフレームワークを停止して即座に終了できます: ```php Flight::halt(); ``` -オプションで `HTTP` ステータスコードとメッセージを指定することもできます: +オプションの `HTTP` ステータスコードとメッセージを指定することもできます: ```php Flight::halt(200, 'Be right back...'); ``` -`halt` を呼び出すと、その時点までのすべてのレスポンスコンテンツを破棄し、すべての実行を停止します。フレームワークを停止して現在のレスポンスを出力したい場合、`stop` メソッドを使用します: +`halt` を呼び出すと、その時点までのレスポンスコンテンツを破棄し、すべての実行を停止します。フレームワークを停止して現在のレスポンスを出力したい場合、`stop` メソッドを使用します: ```php Flight::stop($httpStatusCode = null); ``` -> **注意:** `Flight::stop()` には奇妙な動作があり、レスポンスを出力しますが、スクリプトの実行を続行します。これは望ましくない場合があります。`Flight::stop()` を呼び出した後に `exit` または `return` を使用してさらなる実行を防げますが、一般的に `Flight::halt()` を使用することを推奨します。 +> **Note:** `Flight::stop()` has some odd behavior such as it will output the response but continue executing your script which might not be what you are after. You can use `exit` or `return` after calling `Flight::stop()` to prevent further execution, but it is generally recommended to use `Flight::halt()`. -これにより、ヘッダーキーと値がレスポンスオブジェクトに保存されます。リクエストライフサイクルの終了時に、ヘッダーを構築してレスポンスを送信します。 +This will save the header key and value to the response object. At the end of the request lifecycle +it will build the headers and send a response. ## 高度な使用方法 ### ヘッダーの即時送信 -ヘッダーでカスタムなことを行い、作業中のそのコード行でヘッダーを送信する必要がある場合があります。[ストリーミングルート](/learn/routing) を設定する場合、これが必要です。これは `response()->setRealHeader()` で実現できます。 +ヘッダーでカスタムなことをする必要があり、作業中のそのコード行でヘッダーを送信する必要がある場合があります。[streamed route](/learn/routing) を設定する場合、これが必要です。これは `response()->setRealHeader()` で達成できます。 ```php Flight::route('/', function() { @@ -305,13 +307,13 @@ Flight::route('/', function() { ### JSONP -JSONP リクエストの場合、コールバック関数を定義するために使用するクエリパラメータ名をオプションで渡せます: +JSONP リクエストの場合、コールバック関数を定義するためのクエリパラメータ名をオプションで渡せます: ```php Flight::jsonp(['id' => 123], 'q'); ``` -したがって、`?q=my_func` を使用した GET リクエストを行うと、以下のような出力を受け取るはずです: +したがって、`?q=my_func` を使用した GET リクエストの場合、出力は以下のようになります: ```javascript my_func({"id":123}); @@ -319,11 +321,11 @@ my_func({"id":123}); クエリパラメータ名を渡さない場合、デフォルトで `jsonp` になります。 -> **注意:** 2025 年以降も JSONP リクエストを使用している場合、チャットに参加して理由を教えてください! 良い戦いやホラーストーリーを聞くのが好きです! +> **Note:** If you are still using JSONP requests in 2025 and beyond, hop in the chat and tell us why! We love hearing some good battle/horror stories! ### レスポンスデータのクリア -`clear()` メソッドを使用してレスポンスボディとヘッダーをクリアできます。これにより、レスポンスに割り当てられたすべてのヘッダーをクリアし、レスポンスボディをクリアし、ステータスコードを `200` に設定します。 +`clear()` メソッドを使用して、レスポンスボディとヘッダーをクリアできます。これはレスポンスに割り当てられたすべてのヘッダーをクリアし、レスポンスボディをクリアし、ステータスコードを `200` に設定します。 ```php Flight::response()->clear(); @@ -334,13 +336,13 @@ Flight::response()->clear(); レスポンスボディのみをクリアしたい場合、`clearBody()` メソッドを使用できます: ```php -// これにより、response() オブジェクトに設定されたヘッダーは保持されます。 +// This will still keep any headers set on the response() object. Flight::response()->clearBody(); ``` ### HTTP キャッシング -Flight は HTTP レベルのキャッシングの組み込みサポートを提供します。キャッシング条件が満たされた場合、Flight は HTTP `304 Not Modified` レスポンスを返します。次にクライアントが同じリソースをリクエストすると、ローカルにキャッシュされたバージョンを使用するよう促されます。 +Flight は HTTP レベルのキャッシングのビルトインサポートを提供します。キャッシング条件が満たされた場合、Flight は HTTP `304 Not Modified` レスポンスを返します。次にクライアントが同じリソースをリクエストすると、ローカルにキャッシュされたバージョンの使用が促されます。 #### ルートレベルのキャッシング @@ -348,13 +350,14 @@ Flight は HTTP レベルのキャッシングの組み込みサポートを提 ```php -// これはレスポンスを 5 分間キャッシュします +// This will cache the response for 5 minutes Flight::route('/news', function () { Flight::response()->cache(time() + 300); echo 'This content will be cached.'; }); -// 代替として、strtotime() メソッドに渡す文字列を使用できます +// Alternatively, you can use a string that you would pass +// to the strtotime() method Flight::route('/news', function () { Flight::response()->cache('+5 minutes'); echo 'This content will be cached.'; @@ -363,7 +366,7 @@ Flight::route('/news', function () { ### Last-Modified -`lastModified` メソッドを使用して、ページが最後に変更された日時を UNIX タイムスタンプで設定できます。クライアントは、最終変更値が変更されるまでキャッシュを使用し続けます。 +`lastModified` メソッドを使用して、ページが最後に変更された日時を UNIX タイムスタンプで設定できます。クライアントは最後に変更された値が変更されるまでキャッシュを使用し続けます。 ```php Flight::route('/news', function () { @@ -374,7 +377,7 @@ Flight::route('/news', function () { ### ETag -`ETag` キャッシングは `Last-Modified` に似ていますが、リソースに対して任意の ID を指定できます: +`ETag` キャッシングは `Last-Modified` に似ていますが、リソースに任意の ID を指定できます: ```php Flight::route('/news', function () { @@ -383,32 +386,35 @@ Flight::route('/news', function () { }); ``` -`lastModified` または `etag` のいずれかを呼び出すと、両方ともキャッシュ値を設定し、チェックします。リクエスト間でキャッシュ値が同じ場合、Flight は即座に `HTTP 304` レスポンスを送信し、処理を停止します。 +`lastModified` または `etag` のいずれかを呼び出すと、両方ともキャッシュ値を設定してチェックします。リクエスト間でキャッシュ値が同じ場合、Flight は即座に `HTTP 304` レスポンスを送信して処理を停止します。 ### ファイルのダウンロード _v3.12.0_ -エンドユーザーにファイルをストリーミングするヘルパーメソッドがあります。`download` メソッドを使用してパスを渡せます。 +エンドユーザーにファイルをストリーミングするためのヘルパーメソッドがあります。`download` メソッドを使用してパスを渡せます。 ```php Flight::route('/download', function () { Flight::download('/path/to/file.txt'); + // As of v3.17.1 you can specify a custom filename for the download + Flight::download('/path/to/file.txt', 'custom_name.txt'); }); ``` ## 関連項目 -- [Routing](/learn/routing) - ルートをコントローラーにマップし、ビューをレンダリングする方法。 -- [Requests](/learn/requests) - 受信リクエストの処理方法の理解。 -- [Middleware](/learn/middleware) - 認証、ロギングなどにルートでミドルウェアを使用。 -- [Why a Framework?](/learn/why-frameworks) - Flight のようなフレームワークを使用する利点の理解。 -- [Extending](/learn/extending) - Flight を独自の機能で拡張する方法。 +- [Routing](/learn/routing) - How to map routes to controllers and render views. +- [Requests](/learn/requests) - Understanding how to handle incoming requests. +- [Middleware](/learn/middleware) - Using middleware with routes for authentication, logging, etc. +- [Why a Framework?](/learn/why-frameworks) - Understanding the benefits of using a framework like Flight. +- [Extending](/learn/extending) - How to extend Flight with your own functionality. ## トラブルシューティング -- リダイレクトが動作しない場合、メソッドに `return;` を追加してください。 -- `stop()` と `halt()` は同じではありません。`halt()` は実行を即座に停止しますが、`stop()` は実行を続行します。 - -## 変更履歴 -- v3.12.0 - downloadFile ヘルパーメソッドを追加。 -- v3.10.0 - `jsonHalt` を追加。 -- v1.0 - 初回リリース。 \ No newline at end of file +- If you're having trouble with redirects not working, make sure you add a `return;` to the method. +- `stop()` and `halt()` are not the same thing. `halt()` will stop execution immediately, while `stop()` will allow execution to continue. + +## Changelog +- v3.17.1 - Added `$fileName` to `downloadFile()` method. +- v3.12.0 - Added downloadFile helper method. +- v3.10.0 - Added `jsonHalt`. +- v1.0 - Initial release. \ No newline at end of file diff --git a/content/v3/ja/learn/routing.md b/content/v3/ja/learn/routing.md index 9a360d5f..850993a2 100644 --- a/content/v3/ja/learn/routing.md +++ b/content/v3/ja/learn/routing.md @@ -1,12 +1,12 @@ # ルーティング ## 概要 -Flight PHP のルーティングは、URL パターンをコールバック関数やクラスメソッドにマッピングし、高速でシンプルなリクエスト処理を可能にします。最小限のオーバーヘッド、初心者向けの使用感、そして外部依存なしの拡張性を設計しています。 +Flight PHP のルーティングは、URL パターンをコールバック関数やクラスメソッドにマッピングし、高速でシンプルなリクエスト処理を可能にします。最小限のオーバーヘッド、初心者向けの使用しやすさ、そして外部依存なしの拡張性を設計の目標としています。 ## 理解 -ルーティングは、Flight アプリケーション内で HTTP リクエストをアプリケーションのロジックに接続するコアメカニズムです。ルートを定義することで、異なる URL が関数、クラスメソッド、またはコントローラーアクションを通じて特定のコードをトリガーする方法を指定します。Flight のルーティングシステムは柔軟で、基本パターン、名前付きパラメータ、正規表現、依存性注入やリソースフルルーティングなどの高度な機能に対応しています。このアプローチにより、コードを整理しやすくメンテナンスしやすく保ちつつ、初心者には高速でシンプルに、上級者には拡張可能に保てます。 +ルーティングは、Flight 内で HTTP リクエストをアプリケーションのロジックに接続するコアメカニズムです。ルートを定義することで、異なる URL が特定のコードをトリガーする方法を指定します。これは関数、クラスメソッド、またはコントローラーアクションを通じて行われます。Flight のルーティングシステムは柔軟で、基本パターン、名前付きパラメータ、正規表現、依存性注入やリソースフルルーティングなどの高度な機能をサポートします。このアプローチにより、コードを整理しやすくメンテナンスしやすく保ちつつ、初心者には高速でシンプルに、進んだユーザーには拡張可能に保てます。 -> **注意:** ルーティングについてさらに理解したいですか?["なぜフレームワークか?"](/learn/why-frameworks) ページで詳細な説明を確認してください。 +> **注意:** ルーティングについてさらに理解したいですか?より詳細な説明のために、["なぜフレームワーク?"](/learn/why-frameworks) ページを参照してください。 ## 基本的な使用方法 @@ -19,7 +19,7 @@ Flight::route('/', function(){ }); ``` -> ルートは定義された順序でマッチされます。リクエストに最初にマッチしたルートが呼び出されます。 +> ルートは定義された順序でマッチされます。リクエストに最初にマッチするルートが呼び出されます。 ### コールバックとしての関数の使用 コールバックは任意の呼び出し可能なオブジェクトを使用できます。したがって、通常の関数を使用できます: @@ -33,7 +33,7 @@ Flight::route('/', 'hello'); ``` ### コントローラーとしてのクラスとメソッドの使用 -クラス(静的または非静的)のメソッドも使用できます: +クラス(静的メソッドまたは非静的)のメソッドも使用できます: ```php class GreetingController { @@ -51,7 +51,7 @@ Flight::route('/', [ 'GreetingController::hello' ]); Flight::route('/', [ 'GreetingController->hello' ]); ``` -または、まずオブジェクトを作成してからメソッドを呼び出す方法: +または、最初にオブジェクトを作成してからメソッドを呼び出す: ```php use flight\Engine; @@ -77,11 +77,11 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **注意:** フレームワーク内でコントローラーが呼び出される場合、デフォルトで `flight\Engine` クラスが注入されます。[依存性注入コンテナ](/learn/dependency-injection-container) を通じて指定しない限りです。 +> **注意:** フレームワーク内でコントローラーが呼び出される場合、デフォルトで `flight\Engine` クラスが常に注入されます。[依存性注入コンテナ](/learn/dependency-injection-container) を通じて指定しない限りです。 ### メソッド固有のルーティング -デフォルトでは、ルートパターンはすべてのリクエストメソッドにマッチします。特定のメソッドに応答するには、URL の前に識別子を配置します。 +デフォルトでは、ルートパターンはすべてのリクエストメソッドに対してマッチします。特定のメソッドに応答するには、URL の前に識別子を置きます。 ```php Flight::route('GET /', function () { @@ -99,7 +99,7 @@ Flight::put('/', function() { /* code */ }); Flight::delete('/', function() { /* code */ }); ``` -複数のメソッドを単一のコールバックにマッピングするには、`|` 区切り文字を使用できます: +単一のコールバックに複数のメソッドをマップするには、`|` 区切り文字を使用できます: ```php Flight::route('GET|POST /', function () { @@ -107,15 +107,46 @@ Flight::route('GET|POST /', function () { }); ``` +### HEAD と OPTIONS リクエストの特別な処理 + +Flight は `HEAD` と `OPTIONS` HTTP リクエストの組み込み処理を提供します: + +#### HEAD リクエスト + +- **HEAD リクエスト** は `GET` リクエストと同様に扱われますが、Flight はクライアントに送信する前にレスポンスボディを自動的に削除します。 +- これにより、`GET` のルートを定義でき、同じ URL への HEAD リクエストはヘッダーのみ(コンテンツなし)を返し、HTTP 標準に従います。 + +```php +Flight::route('GET /info', function() { + echo 'This is some info!'; +}); +// /info への HEAD リクエストは同じヘッダーを返しますが、ボディはありません。 +``` + +#### OPTIONS リクエスト + +`OPTIONS` リクエストは、定義された任意のルートに対して Flight によって自動的に処理されます。 +- OPTIONS リクエストを受け取ると、Flight は `204 No Content` ステータスと、そのルートでサポートされるすべての HTTP メソッドをリストした `Allow` ヘッダーで応答します。 +- カスタム動作やレスポンスの変更を望まない限り、OPTIONS 用の別ルートを定義する必要はありません。 + +```php +// 以下のように定義されたルートの場合: +Flight::route('GET|POST /users', function() { /* ... */ }); + +// /users への OPTIONS リクエストは以下のように応答します: +// +// Status: 204 No Content +// Allow: GET, POST, HEAD, OPTIONS +``` + ### ルーターオブジェクトの使用 さらに、ヘルパーメソッドを持つルーターオブジェクトを取得できます: ```php - $router = Flight::router(); -// Flight::route() と同じくすべてのメソッドをマップします +// Flight::route() と同様にすべてのメソッドをマップ $router->map('/', function() { echo 'hello world!'; }); @@ -135,14 +166,14 @@ $router->patch('/users/@id', function() { /* code */}); ```php Flight::route('/user/[0-9]+', function () { - // これにより /user/1234 にマッチします + // /user/1234 にマッチします }); ``` -この方法は利用可能ですが、名前付きパラメータ、または正規表現付きの名前付きパラメータを使用することを推奨します。これらは読みやすく、メンテナンスしやすいためです。 +この方法は利用可能ですが、名前付きパラメータ、または正規表現付きの名前付きパラメータを使用することを推奨します。これらはより読みやすく、メンテナンスしやすいためです。 ### 名前付きパラメータ -ルートで名前付きパラメータを指定すると、コールバック関数に渡されます。**これはルートの可読性を高めるためのもので、それ以上のものではありません。重要な注意点については以下のセクションを参照してください。** +ルートで名前付きパラメータを指定でき、コールバック関数に渡されます。**これは主にルートの可読性のためです。重要な注意事項については以下のセクションを参照してください。** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -154,14 +185,14 @@ Flight::route('/@name/@id', function (string $name, string $id) { ```php Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { - // これにより /bob/123 にマッチします - // しかし /bob/12345 にはマッチしません + // /bob/123 にマッチします + // /bob/12345 にはマッチしません }); ``` -> **注意:** 位置パラメータ付きのマッチング regex グループ `()` はサポートされていません。例: `:'\(` +> **注意:** 位置パラメータとのマッチング regex グループ `()` はサポートされていません。例: `:'\(` -#### 重要な注意点 +#### 重要な注意事項 上記の例では、`@name` が直接 `$name` 変数に結びついているように見えますが、そうではありません。コールバック関数のパラメータの順序が何が渡されるかを決定します。コールバック関数のパラメータの順序を切り替えると、変数も切り替わります。例: @@ -172,7 +203,7 @@ Flight::route('/@name/@id', function (string $id, string $name) { ``` 以下の URL にアクセスした場合:`/bob/123`、出力は `hello, 123 (bob)!` になります。 -ルートとコールバック関数の設定時には _注意してください_! +ルートとコールバック関数の設定時に _注意してください_! ### オプションのパラメータ マッチングにオプションの名前付きパラメータを指定するには、セグメントを括弧で囲みます。 @@ -190,14 +221,14 @@ Flight::route( ); ``` -マッチしなかったオプションのパラメータは `NULL` として渡されます。 +マッチしないオプションのパラメータは `NULL` として渡されます。 ### ワイルドカードルーティング -マッチングは個別の URL セグメントでのみ行われます。複数のセグメントにマッチするには、`*` ワイルドカードを使用できます。 +マッチングは個別の URL セグメントでのみ行われます。複数のセグメントにマッチするには、` * ` ワイルドカードを使用します。 ```php Flight::route('/blog/*', function () { - // これにより /blog/2000/02/01 にマッチします + // /blog/2000/02/01 にマッチします }); ``` @@ -211,7 +242,7 @@ Flight::route('*', function () { ### 404 Not Found ハンドラー -デフォルトでは、URL が見つからない場合、Flight は非常にシンプルでプレーンな `HTTP 404 Not Found` レスポンスを送信します。よりカスタマイズされた 404 レスポンスを希望する場合は、独自の `notFound` メソッドを[マップ](/learn/extending)できます: +デフォルトでは、URL が見つからない場合、Flight は非常にシンプルでプレーンな `HTTP 404 Not Found` レスポンスを送信します。よりカスタマイズされた 404 レスポンスを望む場合、独自の `notFound` メソッドを [マップ](/learn/extending) できます: ```php Flight::map('notFound', function() { @@ -231,15 +262,43 @@ Flight::map('notFound', function() { }); ``` +### メソッドが見つからないハンドラー + +デフォルトでは、URL は見つかるがメソッドが許可されていない場合、Flight は非常にシンプルでプレーンな `HTTP 405 Method Not Allowed` レスポンスを送信します(例: Method Not Allowed. Allowed Methods are: GET, POST)。また、その URL で許可されたメソッドの `Allow` ヘッダーも含めます。 + +よりカスタマイズされた 405 レスポンスを望む場合、独自の `methodNotFound` メソッドを [マップ](/learn/extending) できます: + +```php +use flight\net\Route; + +Flight::map('methodNotFound', function(Route $route) { + $url = Flight::request()->url; + $methods = implode(', ', $route->methods); + + // カスタムテンプレートで Flight::render() を使用することもできます。 + $output = <<My Custom 405 Method Not Allowed +

The method you have requested for {$url} is not allowed.

+

Allowed Methods are: {$methods}

+ HTML; + + $this->response() + ->clearBody() + ->status(405) + ->setHeader('Allow', $methods) + ->write($output) + ->send(); +}); +``` + ## 高度な使用方法 ### ルートでの依存性注入 -コンテナ(PSR-11、PHP-DI、Dice など)経由で依存性注入を使用する場合、利用可能なルートのタイプは、自身でオブジェクトを作成しコンテナでオブジェクトを作成するか、クラスとメソッドを呼び出す文字列を使用するかのいずれかです。[依存性注入](/learn/dependency-injection-container) ページで詳細を確認してください。 +コンテナ(PSR-11、PHP-DI、Dice など)を介した依存性注入を使用する場合、利用可能なルートのタイプは、自身でオブジェクトを作成しコンテナでオブジェクトを作成するか、クラスとメソッドを呼び出す文字列を使用するかのいずれかです。詳細は [依存性注入](/learn/dependency-injection-container) ページを参照してください。 簡単な例: ```php - use flight\database\PdoWrapper; // Greeting.php @@ -263,7 +322,7 @@ class Greeting // PSR-11 に関する詳細は依存性注入ページを参照 $dice = new \Dice\Dice(); -// '$dice = ' で変数を再割り当てすることを忘れずに!!!!! +// 変数を '$dice = ' で再代入することを忘れずに!!!!! $dice = $dice->addRule('flight\database\PdoWrapper', [ 'shared' => true, 'constructParams' => [ @@ -288,9 +347,9 @@ Flight::route('/hello/@id', 'Greeting::hello'); Flight::start(); ``` -### 次のルートへの実行の引き渡し +### 実行を次のルートに渡す 非推奨 -コールバック関数から `true` を返すことで、次のマッチするルートに実行を引き渡せます。 +コールバック関数から `true` を返すことで、実行を次のマッチするルートに渡せます。 ```php Flight::route('/user/@name', function (string $name) { @@ -309,14 +368,14 @@ Flight::route('/user/*', function () { このような複雑なユースケースには、[ミドルウェア](/learn/middleware) を使用することを推奨します。 ### ルートエイリアス -ルートにエイリアスを割り当てることで、アプリケーション内で動的にそのエイリアスを呼び出し、後でコード内で生成できます(例: HTML テンプレート内のリンク、またはリダイレクト URL の生成)。 +ルートにエイリアスを割り当てることで、後でアプリ内でそのエイリアスを動的に呼び出し、コード内で後で生成できます(例: HTML テンプレート内のリンク、またはリダイレクト URL の生成)。 ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); // または Flight::route('/users/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view'); -// 後でコードのどこかで +// コードの後半で class UserController { public function update() { @@ -327,10 +386,10 @@ class UserController { Flight::redirect($redirectUrl); } } - ``` -URL が変更された場合に特に役立ちます。上記の例で、ユーザーが `/admin/users/@id` に移動したとします。ルートにエイリアスを設定していれば、コード内のすべての古い URL を探して変更する必要がなく、エイリアスは今や `/admin/users/5` を返します。 +URL が変更された場合に特に役立ちます。上記の例で、ユーザーが `/admin/users/@id` に移動されたとします。 +ルートにエイリアスを設定していれば、コード内の古い URL をすべて見つけて変更する必要がなく、エイリアスは上記の例のように `/admin/users/5` を返します。 グループ内でもルートエイリアスは動作します: @@ -343,10 +402,10 @@ Flight::group('/users', function() { ``` ### ルート情報の検査 -マッチしたルート情報を検査したい場合、2 つの方法があります: +マッチするルート情報を検査したい場合、2 つの方法があります: -1. `Flight::router()` オブジェクトの `executedRoute` プロパティを使用します。 -2. ルートメソッドの第 3 パラメータに `true` を渡すことで、ルートオブジェクトをコールバックに渡すようリクエストします。ルートオブジェクトはコールバックに渡される最後のパラメータになります。 +1. `Flight::router()` オブジェクトの `executedRoute` プロパティを使用できます。 +2. ルートメソッドの 3 番目のパラメータに `true` を渡すことで、ルートオブジェクトをコールバックに渡すようリクエストできます。ルートオブジェクトは常にコールバックに渡される最後のパラメータです。 #### `executedRoute` ```php @@ -376,7 +435,7 @@ Flight::route('/', function() { }); ``` -> **注意:** `executedRoute` プロパティは、ルートが実行された後にのみ設定されます。ルートが実行される前にアクセスしようとすると `NULL` になります。[ミドルウェア](/learn/middleware) でも executedRoute を使用できます! +> **注意:** `executedRoute` プロパティはルートが実行された後にのみ設定されます。ルートが実行される前にアクセスしようとすると `NULL` です。[ミドルウェア](/learn/middleware) でも executedRoute を使用できます! #### ルート定義に `true` を渡す ```php @@ -404,7 +463,7 @@ Flight::route('/', function(\flight\net\Route $route) { }, true);// <-- この true パラメータがそれを実現します ``` -### ルートグループとミドルウェア +### ルートグループ化とミドルウェア 関連するルートをグループ化したい場合(例: `/api/v1`)があります。`group` メソッドを使用してこれを行えます: ```php @@ -419,12 +478,12 @@ Flight::group('/api/v1', function () { }); ``` -グループのグループをネストすることもできます: +グループのネストも可能です: ```php Flight::group('/api', function () { Flight::group('/v1', function () { - // Flight::get() は変数を取得します。ルートを設定しません!オブジェクトコンテキストを以下で参照 + // Flight::get() は変数を取得します。ルートを設定しません!オブジェクトコンテキストを以下参照 Flight::route('GET /users', function () { // GET /api/v1/users にマッチ }); @@ -439,7 +498,7 @@ Flight::group('/api', function () { }); Flight::group('/v2', function () { - // Flight::get() は変数を取得します。ルートを設定しません!オブジェクトコンテキストを以下で参照 + // Flight::get() は変数を取得します。ルートを設定しません!オブジェクトコンテキストを以下参照 Flight::route('GET /users', function () { // GET /api/v2/users にマッチ }); @@ -471,20 +530,20 @@ $app->group('/api/v1', function (Router $router) { #### ミドルウェア付きのグループ化 -ルートのグループにミドルウェアを割り当てすることもできます: +ルートグループにミドルウェアを割り当てられます: ```php Flight::group('/api/v1', function () { Flight::route('/users', function () { // /api/v1/users にマッチ }); -}, [ MyAuthMiddleware::class ]); // インスタンスを使用したい場合は [ new MyAuthMiddleware() ] +}, [ MyAuthMiddleware::class ]); // インスタンスを使用したい場合 [ new MyAuthMiddleware() ] ``` -[group middleware](/learn/middleware#grouping-middleware) ページで詳細を確認してください。 +詳細は [グループミドルウェア](/learn/middleware#grouping-middleware) ページを参照してください。 ### リソースルーティング -`resource` メソッドを使用して、リソースのためのルートのセットを作成できます。これは RESTful 規約に従ったルートのセットを作成します。 +`resource` メソッドを使用して、リソース用のルートセットを作成できます。これは RESTful 規約に従うリソース用のルートセットを作成します。 リソースを作成するには: @@ -492,7 +551,7 @@ Flight::group('/api/v1', function () { Flight::resource('/users', UsersController::class); ``` -バックグラウンドで以下のルートが作成されます: +バックグラウンドでは、以下のルートが作成されます: ```php [ @@ -541,16 +600,16 @@ class UsersController } ``` -> **注意**: 新しく追加されたルートは `php runway routes` を実行して `runway` で確認できます。 +> **注意**: 新しく追加されたルートは `php runway routes` を実行することで `runway` で表示できます。 #### リソースルートのカスタマイズ -リソースルートを構成するためのオプションがいくつかあります。 +リソースルートを構成するためのいくつかのオプションがあります。 ##### エイリアスベース `aliasBase` を構成できます。デフォルトでは、エイリアスは指定された URL の最後の部分です。 -例: `/users/` は `aliasBase` を `users` にします。これらのルートが作成されると、エイリアスは `users.index`、`users.create` などになります。エイリアスを変更したい場合は、`aliasBase` を希望の値に設定します。 +例: `/users/` は `aliasBase` を `users` にします。これらのルートが作成されると、エイリアスは `users.index`、`users.create` などになります。エイリアスを変更したい場合、`aliasBase` を望む値に設定します。 ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); @@ -570,7 +629,7 @@ Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` -これらは基本的にホワイトリストとブラックリストのオプションで、作成するルートを指定できます。 +これらは基本的にホワイトリストとブラックリストオプションで、作成するルートを指定できます。 ##### ミドルウェア @@ -582,15 +641,15 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid ### ストリーミングレスポンス -`stream()` または `streamWithHeaders()` を使用して、クライアントにレスポンスをストリーミングできます。 -これは大きなファイル、長時間実行のプロセス、または大きなレスポンスを生成する場合に役立ちます。 +`stream()` または `streamWithHeaders()` を使用してクライアントにレスポンスをストリーミングできます。 +これは大きなファイル、長時間実行プロセス、または大きなレスポンスの生成に役立ちます。 ルートのストリーミングは通常のルートとは少し異なります。 -> **注意:** ストリーミングレスポンスは、[`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) を `false` に設定した場合にのみ利用可能です。 +> **注意:** ストリーミングレスポンスは、`flight.v2.output_buffering` を `false` に設定した場合にのみ利用可能です。 #### 手動ヘッダーでのストリーム -ルートで `stream()` メソッドを使用してクライアントにレスポンスをストリーミングできます。これを行う場合、クライアントに出力する前にすべてのヘッダーを手動で設定する必要があります。 +ルートで `stream()` メソッドを使用してクライアントにレスポンスをストリーミングできます。これを行う場合、クライアントに何かを出力する前にすべてのヘッダーを手動で設定する必要があります。 これは `header()` PHP 関数または `Flight::response()->setRealHeader()` メソッドで行います。 ```php @@ -598,13 +657,13 @@ Flight::route('/@filename', function($filename) { $response = Flight::response(); - // 明らかにパスをサニタイズするなどします。 + // 明らかにパスをサニタイズするなど。 $fileNameSafe = basename($filename); - // ルートが実行された後に追加のヘッダーを設定する場合 - // クライアントにエコーする前に定義する必要があります。 + // ルート実行後に追加のヘッダーを設定する場合 + // 何かをエコーする前に定義する必要があります。 // すべて header() 関数の生の呼び出しまたは - // Flight::response()->setRealHeader() の呼び出しである必要があります + // Flight::response()->setRealHeader() の呼び出しでなければなりません header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); // または $response->setRealHeader('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); @@ -620,10 +679,10 @@ Flight::route('/@filename', function($filename) { // または $response->setRealHeader('Content-Length: '.filesize($filePath)); - // ファイルが読み込まれるにつれてクライアントにストリーミング + // ファイルを読みながらクライアントにストリーミング readfile($filePath); -// これが魔法の行です +// ここが魔法の行です })->stream(); ``` @@ -634,8 +693,8 @@ Flight::route('/@filename', function($filename) { ```php Flight::route('/stream-users', function() { - // ここに追加のヘッダーを追加できます - // header() または Flight::response()->setRealHeader() を使用するだけです + // ここに追加のヘッダーを追加可能 + // header() または Flight::response()->setRealHeader() を使用する必要があります // データの取得方法の例として... $users_stmt = Flight::db()->query("SELECT id, first_name, last_name FROM users"); @@ -657,45 +716,43 @@ Flight::route('/stream-users', function() { })->streamWithHeaders([ 'Content-Type' => 'application/json', 'Content-Disposition' => 'attachment; filename="users.json"', - // オプションのステータスコード、デフォルトは 200 + // オプションのステータスコード、デフォルト 200 'status' => 200 ]); ``` -## 関連トピック -- [Middleware](/learn/middleware) - ルートで認証、ロギングなどにミドルウェアを使用。 -- [Dependency Injection](/learn/dependency-injection-container) - ルートでのオブジェクト作成と管理の簡素化。 -- [Why a Framework?](/learn/why-frameworks) - Flight のようなフレームワークを使用する利点の理解。 -- [Extending](/learn/extending) - `notFound` メソッドを含む独自機能で Flight を拡張する方法。 +## 関連項目 +- [ミドルウェア](/learn/middleware) - 認証、ロギングなどにルートでミドルウェアを使用。 +- [依存性注入](/learn/dependency-injection-container) - ルートでのオブジェクト作成と管理の簡素化。 +- [なぜフレームワーク?](/learn/why-frameworks) - Flight のようなフレームワークを使用する利点の理解。 +- [拡張](/learn/extending) - `notFound` メソッドを含む独自機能で Flight を拡張する方法。 - [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - 正規表現マッチングのための PHP 関数。 ## トラブルシューティング -- ルートパラメータは名前ではなく順序でマッチされます。コールバックパラメータの順序がルート定義と一致することを確認してください。 -- `Flight::get()` はルートを定義しません。ルーティングには `Flight::route('GET /...')` またはグループ内のルーターオブジェクトコンテキスト(例: `$router->get(...)`)を使用してください。 +- ルートパラメータは名前ではなく順序でマッチされます。コールバックパラメータの順序がルート定義に一致することを確認。 +- `Flight::get()` はルートを定義しません。ルーティングには `Flight::route('GET /...')` を使用するか、グループ内のルーターオブジェクトコンテキスト(例: `$router->get(...)`)を使用。 - executedRoute プロパティはルート実行後にのみ設定されます。実行前は NULL です。 - ストリーミングにはレガシー Flight 出力バッファリング機能の無効化(`flight.v2.output_buffering = false`)が必要です。 -- 依存性注入の場合、コンテナベースのインスタンス化をサポートするのは特定のルート定義のみです。 +- 依存性注入の場合、特定のルート定義のみコンテナベースのインスタンス化をサポート。 ### 404 Not Found または予期しないルート動作 -404 Not Found エラー(しかし命に誓ってそこにあり、タイポではないと確信している場合)が表示される場合、これはルートエンドポイントで値を返す代わりにエコーするだけであることが原因の可能性があります。この理由は意図的ですが、一部の開発者を驚かせる可能性があります。 +404 Not Found エラーが表示される場合(しかし、命に誓ってそこにあるしタイポではないと確信している場合)、これはルートエンドポイントで値を返す代わりに単にエコーしなかった問題かもしれません。この理由は意図的ですが、一部の開発者を驚かせる可能性があります。 ```php - Flight::route('/hello', function(){ - // これにより 404 Not Found エラーが発生する可能性があります + // これが 404 Not Found エラーを引き起こす可能性 return 'Hello World'; }); -// 恐らくこれが欲しいもの +// 恐らくこれが望ましい Flight::route('/hello', function(){ echo 'Hello World'; }); - ``` -この理由は、ルーターに組み込まれた特別なメカニズムのためで、戻り値を出力を「次のルートに進む」シグナルとして扱います。 -動作は [Routing](/learn/routing#passing) セクションで文書化されています。 +この理由は、ルーターに組み込まれた特別なメカニズムのためで、リターン出力を「次のルートに進む」シグナルとして扱います。 +動作は [ルーティング](/learn/routing#passing) セクションで文書化されています。 ## 変更履歴 - v3: リソースルーティング、ルートエイリアス、ストリーミングサポート、ルートグループ、ミドルウェアサポートを追加。 diff --git a/content/v3/ko/awesome-plugins/apm.md b/content/v3/ko/awesome-plugins/apm.md index b13d8feb..ca3fbf3b 100644 --- a/content/v3/ko/awesome-plugins/apm.md +++ b/content/v3/ko/awesome-plugins/apm.md @@ -1,69 +1,71 @@ # FlightPHP APM 문서 -FlightPHP APM에 오신 것을 환영합니다—당신의 앱을 위한 개인적인 성능 코치입니다! 이 가이드는 FlightPHP와 함께 Application Performance Monitoring (APM)을 설정하고, 사용하며, 마스터하는 로드맵입니다. 느린 요청을 추적하거나 지연 시간 차트를 살펴보고 싶으신지, 우리는 모든 것을 다루고 있습니다. 당신의 앱을 더 빠르게 만들고, 사용자들을 더 행복하게 하며, 디버깅 세션을 쉽게 만들어 보겠습니다! +FlightPHP APM에 오신 것을 환영합니다—앱의 개인 성능 코치입니다! 이 가이드는 FlightPHP와 함께 Application Performance Monitoring (APM)을 설정하고, 사용하며, 마스터하는 로드맵입니다. 느린 요청을 추적하든 지연 차트에 열중하든, 우리는 모든 것을 다루고 있습니다. 앱을 더 빠르게 만들고, 사용자를 더 행복하게 하며, 디버깅 세션을 쉽게 만들어 보겠습니다! + +Flight Docs 사이트의 대시보드 [데모](https://flightphp-docs-apm.sky-9.com/apm/dashboard)를 확인하세요. ![FlightPHP APM](/images/apm.png) -## APM의 중요성 +## APM이 중요한 이유 -이것을 상상해 보세요: 당신의 앱이 바쁜 레스토랑입니다. 주문이 얼마나 걸리는지 또는 주방이 어디서 지연되는지 추적할 방법 없이, 고객들이 왜 불만족스럽게 떠나는지 추측만 하게 됩니다. APM은 당신의 수석 셰프와 같습니다—들어오는 요청부터 데이터베이스 쿼리까지 모든 단계를 감시하고, 지연을 일으키는 것을 플래그로 표시합니다. 느린 페이지는 사용자를 잃게 합니다 (연구에 따르면 사이트가 3초 이상 걸리면 53%가 이탈한다고 합니다!), 그리고 APM은 이러한 문제를 *발생하기 전에* 포착해줍니다. 이는 사전적인 평화로운 마음—더 적은 "이게 왜 고장 났지?" 순간, 더 많은 "이게 얼마나 멋지게 작동하나?" 승리입니다. +이 장면을 상상해 보세요: 앱이 바쁜 레스토랑입니다. 주문이 얼마나 걸리는지나 주방이 어디서 느려지는지 추적할 방법이 없으면, 고객이 왜 불만족스럽게 떠나는지 추측할 수밖에 없습니다. APM은 당신의 수석 셰프입니다—들어오는 요청부터 데이터베이스 쿼리까지 모든 단계를 감시하고, 느려지는 부분을 표시합니다. 느린 페이지는 사용자를 잃습니다 (연구에 따르면 사이트 로딩이 3초를 초과하면 53%가 이탈합니다!), 그리고 APM은 이러한 문제를 *미리* 포착하여 아프기 전에 도와줍니다. 이는 사전적 안심입니다—더 적은 “이게 왜 고장 났어?” 순간, 더 많은 “이게 얼마나 부드럽게 돌아가!” 승리. ## 설치 -Composer를 사용하여 시작하세요: +Composer로 시작하세요: ```bash composer require flightphp/apm ``` 필요한 것: -- **PHP 7.4+**: LTS Linux 배포판과 호환되면서 현대적인 PHP를 지원합니다. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: 우리가 강화하는 가벼운 프레임워크입니다. +- **PHP 7.4+**: LTS Linux 배포판과 호환성을 유지하면서 현대 PHP를 지원합니다. +- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: 우리가 강화하는 경량 프레임워크입니다. -## 지원되는 데이터베이스 +## 지원 데이터베이스 -FlightPHP APM은 현재 메트릭스 저장을 위해 다음 데이터베이스를 지원합니다: +FlightPHP APM은 현재 메트릭을 저장하기 위해 다음 데이터베이스를 지원합니다: -- **SQLite3**: 간단하고 파일 기반이며, 로컬 개발이나 작은 앱에 적합합니다. 대부분의 설정에서 기본 옵션입니다. -- **MySQL/MariaDB**: 더 큰 프로젝트나 프로덕션 환경에서 강력하고 확장 가능한 저장이 필요한 경우 이상적입니다. +- **SQLite3**: 간단하고 파일 기반이며, 로컬 개발이나 작은 앱에 훌륭합니다. 대부분의 설정에서 기본 옵션입니다. +- **MySQL/MariaDB**: 더 큰 프로젝트나 프로덕션 환경에서 강력하고 확장 가능한 저장소가 필요한 경우 이상적입니다. -구성 단계에서 데이터베이스 유형을 선택할 수 있습니다 (아래 참조). PHP 환경에 필요한 확장(예: `pdo_sqlite` 또는 `pdo_mysql`)이 설치되어 있는지 확인하세요. +구성 단계(아래 참조)에서 데이터베이스 유형을 선택할 수 있습니다. PHP 환경에 필요한 확장(예: `pdo_sqlite` 또는 `pdo_mysql`)이 설치되어 있는지 확인하세요. ## 시작하기 -APM의 멋진 기능을 단계별로 안내합니다: +APM의 멋진 단계별 가이드입니다: ### 1. APM 등록 -`index.php` 또는 `services.php` 파일에 다음을 추가하여 추적을 시작하세요: +추적을 시작하기 위해 `index.php` 또는 `services.php` 파일에 다음을 추가하세요: ```php use flight\apm\logger\LoggerFactory; use flight\Apm; -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // 구성 파일을 가져와 로거를 설정합니다. 기본적으로 SQLite입니다. +$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); $Apm = new Apm($ApmLogger); $Apm->bindEventsToFlightInstance($app); -// 추가로 데이터베이스 연결을 추가하는 경우 -// Tracy Extensions의 PdoWrapper 또는 PdoQueryCapture여야 합니다. -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True가 필요하여 APM에서 추적을 활성화합니다. +// 데이터베이스 연결을 추가하는 경우 +// Tracy Extensions의 PdoWrapper 또는 PdoQueryCapture여야 합니다 +$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- APM 추적을 활성화하려면 True가 필요합니다. $Apm->addPdoConnection($pdo); ``` **여기서 무슨 일이 일어나나요?** -- `LoggerFactory::create()`는 구성(곧 더 자세히 설명)을 가져와 로거를 설정합니다—기본적으로 SQLite입니다. -- `Apm`은 주인공입니다—Flight의 이벤트(요청, 라우트, 오류 등)를 듣고 메트릭스를 수집합니다. +- `LoggerFactory::create()`는 구성(곧 더 자세히)을 가져와 로거를 설정합니다—기본적으로 SQLite입니다. +- `Apm`은 스타입니다—Flight의 이벤트(요청, 라우트, 오류 등)를 듣고 메트릭을 수집합니다. - `bindEventsToFlightInstance($app)`은 이를 Flight 앱에 연결합니다. **프로 팁: 샘플링** -앱이 바쁘면 모든 요청을 로그하면 과부하가 발생할 수 있습니다. 샘플 속도(0.0에서 1.0)를 사용하세요: +앱이 바쁘면 *모든* 요청을 로깅하면 과부하가 될 수 있습니다. 샘플 레이트(0.0에서 1.0)를 사용하세요: ```php -$Apm = new Apm($ApmLogger, 0.1); // 요청의 10%를 로그합니다. +$Apm = new Apm($ApmLogger, 0.1); // 10% 요청 로깅 ``` -이렇게 하면 성능을 유지하면서도 안정적인 데이터를 제공합니다. +이렇게 하면 성능을 유지하면서도 견고한 데이터를 제공합니다. ### 2. 구성 @@ -73,9 +75,9 @@ $Apm = new Apm($ApmLogger, 0.1); // 요청의 10%를 로그합니다. php vendor/bin/runway apm:init ``` -**이게 뭐하는 건가요?** -- 원시 메트릭스가 어디서 오는지(소스)와 처리된 데이터가 어디로 가는지(목적지)를 묻는 마법사를 시작합니다. -- 기본은 SQLite—예: `sqlite:/tmp/apm_metrics.sqlite` 소스, 다른 하나는 목적지입니다. +**이게 무슨 일이에요?** +- 원시 메트릭의 출처(소스)와 처리된 데이터의 목적지(대상)에 대한 마법사를 실행합니다. +- 기본은 SQLite—예: 소스에 `sqlite:/tmp/apm_metrics.sqlite`, 대상에 다른 하나. - 다음과 같은 구성으로 끝납니다: ```json { @@ -88,123 +90,123 @@ php vendor/bin/runway apm:init } ``` -> 이 과정에서 이 설정에 대한 마이그레이션을 실행할지 묻습니다. 처음 설정하는 경우, 대답은 예입니다. +> 이 과정에서 이 설정에 대한 마이그레이션을 실행할지 묻습니다. 처음 설정하는 경우 답은 yes입니다. **왜 두 위치인가요?** -원시 메트릭스는 빠르게 쌓입니다(필터링되지 않은 로그를 생각하세요). 워커가 이를 처리된 목적지로 구조화합니다. 깔끔하게 유지하기 위해! +원시 메트릭은 빠르게 쌓입니다(필터링되지 않은 로그 생각). 워커가 이를 구조화된 대상으로 처리하여 대시보드를 유지합니다. 깔끔하게 유지합니다! -### 3. 워커로 메트릭스 처리 +### 3. 워커로 메트릭 처리 -워커는 원시 메트릭스를 대시보드 준비 데이터로 변환합니다. 한 번 실행하세요: +워커는 원시 메트릭을 대시보드 준비 데이터로 변환합니다. 한 번 실행하세요: ```bash php vendor/bin/runway apm:worker ``` -**이게 뭐하는 건가요?** +**무슨 일을 하나요?** - 소스(예: `apm_metrics.sqlite`)에서 읽습니다. -- 최대 100개의 메트릭스(기본 배치 크기)를 처리된 목적지로 처리합니다. -- 완료되거나 메트릭스가 없을 때 중지합니다. +- 최대 100 메트릭(기본 배치 크기)을 대상으로 처리합니다. +- 완료되거나 메트릭이 없으면 중지합니다. -**계속 실행하기** -라이브 앱의 경우, 지속적인 처리가 필요합니다. 옵션: +**실행 유지** +라이브 앱의 경우 지속적인 처리가 필요합니다. 옵션은 다음과 같습니다: - **데몬 모드**: ```bash php vendor/bin/runway apm:worker --daemon ``` - 영원히 실행되며, 메트릭스가 들어오면 처리합니다. 개발이나 작은 설정에 적합합니다. + 영원히 실행되며, 메트릭이 오면 처리합니다. 개발이나 작은 설정에 좋습니다. - **Crontab**: - crontab에 추가하세요(`crontab -e`): + crontab(`crontab -e`)에 추가하세요: ```bash * * * * * php /path/to/project/vendor/bin/runway apm:worker ``` - 매 분 실행—프로덕션에 완벽합니다. + 매분 실행—프로덕션에 완벽합니다. - **Tmux/Screen**: 분리 가능한 세션을 시작하세요: ```bash tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon - # Ctrl+B, then D로 분리; `tmux attach -t apm-worker`로 재연결 + # Ctrl+B, 그 다음 D로 분리; `tmux attach -t apm-worker`로 재연결 ``` - 로그아웃해도 계속 실행됩니다. + 로그아웃해도 실행을 유지합니다. - **커스텀 조정**: ```bash php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 ``` - - `--batch_size 50`: 한 번에 50개의 메트릭스 처리. - - `--max_messages 1000`: 1000개 메트릭스 후 중지. + - `--batch_size 50`: 한 번에 50 메트릭 처리. + - `--max_messages 1000`: 1000 메트릭 후 중지. - `--timeout 300`: 5분 후 종료. **왜 신경 써야 하나요?** -워커 없이는 대시보드가 비어 있습니다. 이는 원시 로그와 실행 가능한 통찰 사이의 다리입니다. +워커 없이 대시보드는 비어 있습니다. 원시 로그와 실행 가능한 인사이트 사이의 다리입니다. ### 4. 대시보드 실행 -앱의 활력 상태를 보세요: +앱의 활력을 확인하세요: ```bash php vendor/bin/runway apm:dashboard ``` -**이게 뭐하는 건가요?** -- `http://localhost:8001/apm/dashboard`에서 PHP 서버를 시작합니다. +**이게 뭐예요?** +- `http://localhost:8001/apm/dashboard`에서 PHP 서버를 실행합니다. - 요청 로그, 느린 라우트, 오류 비율 등을 보여줍니다. -**커스터마이즈**: +**커스터마이징**: ```bash php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php ``` -- `--host 0.0.0.0`: 모든 IP에서 접근 가능(원격 보기 유용). -- `--port 8080`: 8001이 사용 중일 때 다른 포트 사용. -- `--php-path`: PATH에 없는 경우 PHP 위치 지정. +- `--host 0.0.0.0`: 모든 IP에서 접근 가능(원격 보기 편함). +- `--port 8080`: 8001이 사용 중이면 다른 포트 사용. +- `--php-path`: PATH에 없으면 PHP를 가리킵니다. 브라우저에서 URL을 열고 탐색하세요! #### 프로덕션 모드 -프로덕션에서 대시보드를 실행하려면 방화벽 및 기타 보안 조치로 인해 몇 가지 기술을 시도해야 할 수 있습니다. 몇 가지 옵션: +프로덕션에서 대시보드를 실행하려면 방화벽과 기타 보안 조치가 있으므로 몇 가지 기술을 시도해야 할 수 있습니다. 몇 가지 옵션: -- **리버스 프록시 사용**: Nginx 또는 Apache를 설정하여 요청을 대시보드로 전달합니다. -- **SSH 터널**: 서버에 SSH로 접속할 수 있으면 `ssh -L 8080:localhost:8001 youruser@yourserver`를 사용하여 로컬 머신으로 터널링합니다. -- **VPN**: 서버가 VPN 뒤에 있으면 연결하여 대시보드에 직접 접근합니다. -- **방화벽 구성**: 포트 8001을 IP나 서버 네트워크에 대해 열어줍니다. (또는 설정한 포트). -- **Apache/Nginx 구성**: 애플리케이션 앞에 웹 서버가 있으면 도메인이나 서브도메인에 구성합니다. 이렇게 하면 문서 루트를 `/path/to/your/project/vendor/flightphp/apm/dashboard`로 설정합니다. +- **리버스 프록시 사용**: Nginx 또는 Apache를 설정하여 대시보드로 요청을 전달합니다. +- **SSH 터널**: 서버에 SSH로 접근할 수 있으면 `ssh -L 8080:localhost:8001 youruser@yourserver`를 사용하여 대시보드를 로컬 머신으로 터널링합니다. +- **VPN**: 서버가 VPN 뒤에 있으면 연결하고 대시보드를 직접 접근합니다. +- **방화벽 구성**: IP나 서버 네트워크에 대해 포트 8001을 열습니다. (또는 설정한 포트). +- **Apache/Nginx 구성**: 애플리케이션 앞에 웹 서버가 있으면 도메인이나 서브도메인으로 구성할 수 있습니다. 이렇게 하면 문서 루트를 `/path/to/your/project/vendor/flightphp/apm/dashboard`로 설정합니다. -#### 다른 대시보드 원하세요? +#### 다른 대시보드를 원하나요? -원하는 대시보드를 직접 만들 수 있습니다! 데이터 표시 아이디어를 위해 vendor/flightphp/apm/src/apm/presenter 디렉터리를 확인하세요! +원하면 자신의 대시보드를 만들 수 있습니다! vendor/flightphp/apm/src/apm/presenter 디렉토리를 보고 자신의 대시보드에 데이터를 제시하는 아이디어를 얻으세요! ## 대시보드 기능 -대시보드는 APM 본부입니다—보실 내용: +대시보드는 APM 본부입니다—여기서 볼 수 있는 것: -- **요청 로그**: 타임스탬프, URL, 응답 코드, 총 시간과 함께 모든 요청. "세부사항" 클릭으로 미들웨어, 쿼리, 오류를 확인합니다. -- **가장 느린 요청**: 시간을 잡아먹는 상위 5개 요청(예: “/api/heavy” 2.5초). -- **가장 느린 라우트**: 평균 시간 기준 상위 5개 라우트—패턴 발견에 좋습니다. -- **오류 비율**: 실패하는 요청 비율(예: 2.3% 500s). -- **지연 백분위수**: 95번째(p95) 및 99번째(p99) 응답 시간—최악 시나리오를 알 수 있습니다. -- **응답 코드 차트**: 200s, 404s, 500s 등을 시간에 따라 시각화합니다. -- **긴 쿼리/미들웨어**: 상위 5개 느린 데이터베이스 호출 및 미들웨어 레이어. -- **캐시 적중/실패**: 캐시가 얼마나 자주 도움을 주는가. +- **요청 로그**: 타임스탬프, URL, 응답 코드, 총 시간과 함께 모든 요청. “상세”를 클릭하여 미들웨어, 쿼리, 오류 확인. +- **가장 느린 요청**: 시간 소모 상위 5개 요청(예: “/api/heavy” 2.5s). +- **가장 느린 라우트**: 평균 시간 기준 상위 5개 라우트—패턴 발견에 좋음. +- **오류 비율**: 실패한 요청 비율(예: 2.3% 500s). +- **지연 백분위**: 95번째(p95)와 99번째(p99) 응답 시간—최악 시나리오를 알기. +- **응답 코드 차트**: 시간에 따른 200s, 404s, 500s 시각화. +- **긴 쿼리/미들웨어**: 느린 데이터베이스 호출과 미들웨어 레이어 상위 5개. +- **캐시 히트/미스**: 캐시가 얼마나 자주 구하는지. **추가 기능**: -- "지난 1시간", "지난 1일", "지난 1주"로 필터링. -- 야간 세션을 위한 다크 모드 토글. +- “지난 시간,” “지난 날,” 또는 “지난 주”로 필터링. +- 늦은 밤 세션에 다크 모드 토글. **예시**: -`/users` 요청은 다음과 같이 보여질 수 있습니다: +`/users` 요청은 다음과 같이 표시될 수 있습니다: - 총 시간: 150ms - 미들웨어: `AuthMiddleware->handle` (50ms) - 쿼리: `SELECT * FROM users` (80ms) -- 캐시: `user_list` 적중 (5ms) +- 캐시: `user_list` 히트 (5ms) ## 커스텀 이벤트 추가 -API 호출이나 지불 처리와 같은 것을 추적하세요: +API 호출이나 결제 프로세스처럼 아무거나 추적하세요: ```php use flight\apm\CustomEvent; @@ -216,8 +218,8 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ])); ``` -**어디에 나타나나요?** -대시보드의 요청 세부사항 아래 "커스텀 이벤트"—확장 가능하며 예쁜 JSON 형식입니다. +**어디에 표시되나요?** +대시보드의 요청 상세에서 “커스텀 이벤트” 아래—예쁜 JSON 형식으로 확장 가능. **사용 사례**: ```php @@ -229,7 +231,7 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -이제 그 API가 앱을 지연시키는지 확인할 수 있습니다! +이제 그 API가 앱을 끌어내리는지 확인할 수 있습니다! ## 데이터베이스 모니터링 @@ -238,19 +240,19 @@ PDO 쿼리를 이렇게 추적하세요: ```php use flight\database\PdoWrapper; -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True가 필요하여 APM에서 추적을 활성화합니다. +$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- APM 추적을 활성화하려면 True가 필요합니다. $Apm->addPdoConnection($pdo); ``` -**얻을 수 있는 것**: +**얻는 것**: - 쿼리 텍스트(예: `SELECT * FROM users WHERE id = ?`) - 실행 시간(예: 0.015s) - 행 수(예: 42) **주의**: -- **선택적**: DB 추적이 필요하지 않으면 생략하세요. -- **PdoWrapper만**: 기본 PDO는 아직 연결되지 않았습니다—기다려 주세요! -- **성능 경고**: DB 중심 사이트에서 모든 쿼리를 로그하면 느려질 수 있습니다. 샘플링(`$Apm = new Apm($ApmLogger, 0.1)`)을 사용해 부하를 줄이세요. +- **선택적**: DB 추적이 필요 없으면 건너뛰기. +- **PdoWrapper만**: 코어 PDO는 아직 연결되지 않음—기대하세요! +- **성능 경고**: DB 중심 사이트에서 모든 쿼리를 로깅하면 느려질 수 있습니다. 샘플링(`$Apm = new Apm($ApmLogger, 0.1)`)으로 부하를 줄이세요. **예시 출력**: - 쿼리: `SELECT name FROM products WHERE price > 100` @@ -259,30 +261,30 @@ $Apm->addPdoConnection($pdo); ## 워커 옵션 -워커를 원하는 대로 조정하세요: +취향에 맞게 워커를 조정하세요: -- `--timeout 300`: 5분 후 중지—테스트에 좋습니다. -- `--max_messages 500`: 500개 메트릭스에서 중지. -- `--batch_size 200`: 한 번에 200개 처리—속도와 메모리 균형. -- `--daemon`: 영원히 실행—라이브 모니터링에 이상적. +- `--timeout 300`: 5분 후 중지—테스트에 좋음. +- `--max_messages 500`: 500 메트릭으로 제한—유한하게 유지. +- `--batch_size 200`: 한 번에 200 처리—속도와 메모리 균형. +- `--daemon`: 중단 없이 실행—라이브 모니터링에 이상적. **예시**: ```bash php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ``` -한 시간 동안 실행되며, 한 번에 100개 메트릭스 처리. +한 시간 동안 실행되며, 한 번에 100 메트릭 처리. ## 앱의 요청 ID -각 요청에 고유한 요청 ID가 있으며, 로그와 메트릭스를 상관짓는 데 사용할 수 있습니다. 예를 들어 오류 페이지에 요청 ID를 추가할 수 있습니다: +각 요청은 추적을 위한 고유 요청 ID를 가집니다. 앱에서 이 ID를 사용하여 로그와 메트릭을 상관관계지을 수 있습니다. 예를 들어 오류 페이지에 요청 ID를 추가할 수 있습니다: ```php Flight::map('error', function($message) { - // 응답 헤더 X-Flight-Request-Id에서 요청 ID를 가져옵니다. + // 응답 헤더 X-Flight-Request-Id에서 요청 ID 가져오기 $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - // 추가로 Flight 변수에서 가져올 수 있습니다. - // 이는 Swoole나 다른 비동기 플랫폼에서 잘 작동하지 않을 수 있습니다. + // 추가로 Flight 변수에서 가져올 수 있음 + // swoole나 다른 비동기 플랫폼에서는 이 방법이 잘 작동하지 않습니다. // $requestId = Flight::get('apm.request_id'); echo "Error: $message (Request ID: $requestId)"; @@ -291,55 +293,55 @@ Flight::map('error', function($message) { ## 업그레이드 -APM의 새 버전으로 업그레이드할 때, 데이터베이스 마이그레이션을 실행해야 할 수 있습니다. 다음 명령으로 실행하세요: +APM의 최신 버전으로 업그레이드할 때 데이터베이스 마이그레이션을 실행해야 할 수 있습니다. 다음 명령으로 이를 할 수 있습니다: ```bash php vendor/bin/runway apm:migrate ``` -이 명령은 데이터베이스 스키마를 최신 버전으로 업데이트합니다. +이것은 데이터베이스 스키마를 최신 버전으로 업데이트하는 데 필요한 모든 마이그레이션을 실행합니다. -**노트:** APM 데이터베이스가 크면 이 마이그레이션이 시간이 걸릴 수 있습니다. 피크 시간 외에 실행하세요. +**참고:** APM 데이터베이스가 크면 이러한 마이그레이션이 실행되는 데 시간이 걸릴 수 있습니다. 피크 시간 외에 이 명령을 실행하는 것이 좋습니다. -## 오래된 데이터 제거 +## 오래된 데이터 삭제 -데이터베이스를 깔끔하게 유지하려면 오래된 데이터를 제거하세요. 바쁜 앱을 운영할 때 데이터베이스 크기를 관리하는 데 유용합니다. -다음 명령으로 실행하세요: +데이터베이스를 깔끔하게 유지하려면 오래된 데이터를 삭제할 수 있습니다. 이는 바쁜 앱을 실행 중이고 데이터베이스 크기를 관리하려는 경우 특히 유용합니다. +다음 명령으로 이를 할 수 있습니다: ```bash php vendor/bin/runway apm:purge ``` -이 명령은 데이터베이스에서 30일 이상 된 모든 데이터를 제거합니다. `--days` 옵션으로 일수를 조정할 수 있습니다: +이것은 데이터베이스에서 30일 이상 된 모든 데이터를 제거합니다. `--days` 옵션에 다른 값을 전달하여 일 수를 조정할 수 있습니다: ```bash php vendor/bin/runway apm:purge --days 7 ``` -이 명령은 7일 이상 된 모든 데이터를 제거합니다. +이것은 데이터베이스에서 7일 이상 된 모든 데이터를 제거합니다. ## 문제 해결 -문제가 발생했다면, 다음을 시도하세요: +막혔나요? 다음을 시도하세요: -- **대시보드에 데이터가 없나요?** - - 워커가 실행 중인가요? `ps aux | grep apm:worker`로 확인하세요. - - 구성 경로가 맞나요? `.runway-config.json` DSNs가 실제 파일을 가리키는지 확인하세요. - - 수동으로 `php vendor/bin/runway apm:worker`를 실행하여 보류 중인 메트릭스를 처리하세요. +- **대시보드 데이터 없음?** + - 워커가 실행 중인가요? `ps aux | grep apm:worker` 확인. + - 구성 경로가 일치하나요? `.runway-config.json` DSN이 실제 파일을 가리키는지 확인. + - 보류 중인 메트릭을 처리하려면 `php vendor/bin/runway apm:worker`를 수동으로 실행. - **워커 오류?** - - SQLite 파일을 확인하세요(예: `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - PHP 로그에서 스택 추적을 확인하세요. + - SQLite 파일 확인(예: `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). + - PHP 로그에서 스택 트레이스 확인. -- **대시보드가 시작되지 않나요?** - - 포트 8001이 사용 중인가요? `--port 8080`을 사용하세요. - - PHP를 찾을 수 없나요? `--php-path /usr/bin/php`를 사용하세요. - - 방화벽이 차단하나요? 포트를 열거나 `--host localhost`을 사용하세요. +- **대시보드 시작 안 됨?** + - 포트 8001 사용 중? `--port 8080` 사용. + - PHP 없음? `--php-path /usr/bin/php` 사용. + - 방화벽 차단? 포트 열기 또는 `--host localhost` 사용. -- **너무 느린가요?** - - 샘플 속도를 낮추세요: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - 배치 크기를 줄이세요: `--batch_size 20`. +- **너무 느림?** + - 샘플 레이트 낮추기: `$Apm = new Apm($ApmLogger, 0.05)` (5%). + - 배치 크기 줄이기: `--batch_size 20`. -- **예외/오류를 추적하지 않나요?** - - [Tracy](https://tracy.nette.org/)가 프로젝트에 활성화되어 있으면 Flight의 오류 처리를 덮어씁니다. Tracy를 비활성화하고 `Flight::set('flight.handle_errors', true);`를 설정하세요. +- **예외/오류 추적 안 됨?** + - 프로젝트에 [Tracy](https://tracy.nette.org/)가 활성화되어 있으면 Flight의 오류 처리를 재정의합니다. Tracy를 비활성화하고 `Flight::set('flight.handle_errors', true);`가 설정되어 있는지 확인하세요. -- **데이터베이스 쿼리를 추적하지 않나요?** - - `PdoWrapper`를 데이터베이스 연결에 사용하고 있는지 확인하세요. - - 생성자에서 마지막 인수를 `true`로 설정했는지 확인하세요. \ No newline at end of file +- **데이터베이스 쿼리 추적 안 됨?** + - 데이터베이스 연결에 `PdoWrapper`를 사용 중인지 확인. + - 생성자에서 마지막 인수가 `true`인지 확인. \ No newline at end of file diff --git a/content/v3/ko/learn/ai.md b/content/v3/ko/learn/ai.md index 98cca069..753028d0 100644 --- a/content/v3/ko/learn/ai.md +++ b/content/v3/ko/learn/ai.md @@ -2,20 +2,20 @@ ## 개요 -Flight는 AI 기반 도구와 현대적인 개발자 워크플로를 통해 PHP 프로젝트를 쉽게 강화할 수 있게 합니다. LLM(Large Language Model) 제공자에 연결하는 내장 명령어와 프로젝트별 AI 코딩 지침 생성을 통해, Flight는 GitHub Copilot, Cursor, Windsurf와 같은 AI 어시스턴트로부터 최대한의 이점을 얻도록 도와줍니다. +Flight는 AI 기반 도구와 현대적인 개발자 워크플로우로 PHP 프로젝트를 쉽게 강화할 수 있게 해줍니다. LLM(대형 언어 모델) 제공자에 연결하는 내장 명령어와 프로젝트별 AI 코딩 지침을 생성하는 기능을 통해, Flight는 GitHub Copilot, Cursor, Windsurf와 같은 AI 어시스턴트에서 최대한의 이점을 얻도록 당신과 팀을 도와줍니다. -## 이해 +## 이해하기 AI 코딩 어시스턴트는 프로젝트의 맥락, 규칙, 목표를 이해할 때 가장 도움이 됩니다. Flight의 AI 도우미는 다음을 가능하게 합니다: - 프로젝트를 인기 있는 LLM 제공자(OpenAI, Grok, Claude 등)에 연결 -- AI 도구를 위한 프로젝트별 지침 생성 및 업데이트, 모든 사람이 일관되고 관련성 있는 도움을 받도록 함 -- 팀을 일치시키고 생산성을 유지하며, 맥락 설명에 소요되는 시간을 줄임 +- AI 도구를 위한 프로젝트별 지침을 생성하고 업데이트하여 모두가 일관되고 관련성 있는 도움을 받도록 함 +- 맥락 설명에 시간을 덜 들이고 팀을 일치시키며 생산성을 유지 -이러한 기능은 Flight 코어 CLI와 공식 [flightphp/skeleton](https://github.com/flightphp/skeleton) 스타터 프로젝트에 내장되어 있습니다. +이 기능들은 Flight 코어 CLI와 공식 [flightphp/skeleton](https://github.com/flightphp/skeleton) 시작 프로젝트에 내장되어 있습니다. ## 기본 사용법 -### 1. LLM 자격 증명 설정 +### LLM 자격 증명 설정 `ai:init` 명령어는 프로젝트를 LLM 제공자에 연결하는 과정을 안내합니다. @@ -23,24 +23,24 @@ AI 코딩 어시스턴트는 프로젝트의 맥락, 규칙, 목표를 이해할 php runway ai:init ``` -다음에 대한 프롬프트가 나타납니다: -- 제공자 선택(OpenAI, Grok, Claude 등) +다음으로 안내됩니다: +- 제공자 선택 (OpenAI, Grok, Claude 등) - API 키 입력 - 기본 URL 및 모델 이름 설정 -이것은 프로젝트 루트에 `.runway-creds.json` 파일을 생성합니다(그리고 `.gitignore`에 포함되도록 보장합니다). +이로 인해 프로젝트 루트에 `.runway-creds.json` 파일이 생성되며 (`.gitignore`에 포함되도록 보장합니다). **예시:** ``` -AI Init에 오신 것을 환영합니다! -어떤 LLM API를 사용하시겠습니까? [1] openai, [2] grok, [3] claude: 1 -LLM API의 기본 URL을 입력하세요 [https://api.openai.com]: -openai용 API 키를 입력하세요: sk-... -사용할 모델 이름을 입력하세요 (예: gpt-4, claude-3-opus 등) [gpt-4o]: -자격 증명이 .runway-creds.json에 저장되었습니다. +Welcome to AI Init! +Which LLM API do you want to use? [1] openai, [2] grok, [3] claude: 1 +Enter the base URL for the LLM API [https://api.openai.com]: +Enter your API key for openai: sk-... +Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: +Credentials saved to .runway-creds.json ``` -### 2. 프로젝트별 AI 지침 생성 +### 프로젝트별 AI 지침 생성 `ai:generate-instructions` 명령어는 프로젝트에 맞춤형 AI 코딩 어시스턴트 지침을 생성하거나 업데이트하는 데 도움을 줍니다. @@ -55,30 +55,30 @@ php runway ai:generate-instructions **예시:** ``` -프로젝트의 목적을 설명해 주세요? 내 멋진 API -어떤 데이터베이스를 사용할 계획인가요? MySQL -어떤 HTML 템플릿 엔진을 사용할 계획인가요 (없으면 none)? latte -이 프로젝트에서 보안이 중요한 요소인가요? (y/n) y +Please describe what your project is for? My awesome API +What database are you planning on using? MySQL +What HTML templating engine will you plan on using (if any)? latte +Is security an important element of this project? (y/n) y ... -AI 지침이 성공적으로 업데이트되었습니다. +AI instructions updated successfully. ``` 이제 AI 도구는 프로젝트의 실제 요구사항에 기반한 더 스마트하고 관련성 있는 제안을 제공합니다. ## 고급 사용법 -- 명령어 옵션을 사용하여 자격 증명 또는 지침 파일의 위치를 사용자 지정할 수 있습니다(각 명령어에 대해 `--help`를 참조하세요). -- AI 도우미는 OpenAI 호환 API를 지원하는 모든 LLM 제공자와 함께 작동하도록 설계되었습니다. -- 프로젝트가 진화함에 따라 지침을 업데이트하려면 `ai:generate-instructions`를 다시 실행하고 프롬프트에 답변하세요. +- 자격 증명 또는 지침 파일의 위치를 명령어 옵션을 사용하여 사용자 지정할 수 있습니다 (각 명령어의 `--help` 참조). +- AI 도우미는 OpenAI 호환 API를 지원하는 모든 LLM 제공자와 작동하도록 설계되었습니다. +- 프로젝트가 발전함에 따라 지침을 업데이트하려면 `ai:generate-instructions`를 다시 실행하고 프롬프트에 답변하세요. ## 관련 자료 -- [Flight Skeleton](https://github.com/flightphp/skeleton) – AI 통합이 포함된 공식 스타터 +- [Flight Skeleton](https://github.com/flightphp/skeleton) – AI 통합이 포함된 공식 시작 프로젝트 - [Runway CLI](/awesome-plugins/runway) – 이러한 명령어를 구동하는 CLI 도구에 대한 자세한 내용 ## 문제 해결 -- "Missing .runway-creds.json"이 표시되면 먼저 `php runway ai:init`을 실행하세요. +- "Missing .runway-creds.json"이 보이면 먼저 `php runway ai:init`을 실행하세요. - API 키가 유효하고 선택된 모델에 액세스할 수 있는지 확인하세요. - 지침이 업데이트되지 않으면 프로젝트 디렉토리의 파일 권한을 확인하세요. diff --git a/content/v3/ko/learn/requests.md b/content/v3/ko/learn/requests.md index a7eba64f..0f6eda19 100644 --- a/content/v3/ko/learn/requests.md +++ b/content/v3/ko/learn/requests.md @@ -1,6 +1,6 @@ -# 요청 +# Requests -## 개요 +## Overview Flight는 HTTP 요청을 단일 객체로 캡슐화하며, 이를 다음과 같이 접근할 수 있습니다: @@ -8,17 +8,17 @@ Flight는 HTTP 요청을 단일 객체로 캡슐화하며, 이를 다음과 같 $request = Flight::request(); ``` -## 이해 +## Understanding -HTTP 요청은 HTTP 수명 주기를 이해하는 데 핵심적인 측면 중 하나입니다. 사용자가 웹 브라우저나 HTTP 클라이언트에서 작업을 수행하면, 헤더, 본문, URL 등의 시리즈를 프로젝트로 보냅니다. 이러한 헤더(브라우저 언어, 처리할 수 있는 압축 유형, 사용자 에이전트 등)를 캡처하고, Flight 애플리케이션으로 전송된 본문과 URL을 캡처할 수 있습니다. 이러한 요청은 앱이 다음에 무엇을 해야 할지 이해하는 데 필수적입니다. +HTTP 요청은 HTTP 라이프사이클에 대한 이해의 핵심 요소 중 하나입니다. 사용자가 웹 브라우저나 HTTP 클라이언트에서 작업을 수행하면, 헤더, 본문, URL 등을 프로젝트로 보냅니다. 이러한 헤더(브라우저 언어, 처리 가능한 압축 유형, 사용자 에이전트 등)를 캡처하고, Flight 애플리케이션으로 전송된 본문과 URL을 캡처할 수 있습니다. 이러한 요청은 앱이 다음에 무엇을 할지 이해하는 데 필수적입니다. -## 기본 사용법 +## Basic Usage PHP에는 `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES`, `$_COOKIE`와 같은 여러 슈퍼 글로벌이 있습니다. Flight는 이를 편리한 [Collections](/learn/collections)로 추상화합니다. `query`, `data`, `cookies`, `files` 속성을 배열 또는 객체로 접근할 수 있습니다. -> **참고:** 프로젝트에서 이러한 슈퍼 글로벌을 사용하는 것은 **매우** 권장되지 않으며, `request()` 객체를 통해 참조해야 합니다. +> **Note:** 프로젝트에서 이러한 슈퍼 글로벌을 사용하는 것은 **강력히** 권장되지 않으며, `request()` 객체를 통해 참조해야 합니다. -> **참고:** `$_ENV`에 대한 추상화는 제공되지 않습니다. +> **Note:** `$_ENV`에 대한 추상화는 제공되지 않습니다. ### `$_GET` @@ -28,10 +28,10 @@ PHP에는 `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES`, `$_COOKIE`와 // GET /search?keyword=something Flight::route('/search', function(){ $keyword = Flight::request()->query['keyword']; - // 또는 + // or $keyword = Flight::request()->query->keyword; echo "You are searching for: $keyword"; - // $keyword를 사용하여 데이터베이스를 쿼리하거나 다른 작업 수행 + // query a database or something else with the $keyword }); ``` @@ -43,11 +43,11 @@ Flight::route('/search', function(){ Flight::route('POST /submit', function(){ $name = Flight::request()->data['name']; $email = Flight::request()->data['email']; - // 또는 + // or $name = Flight::request()->data->name; $email = Flight::request()->data->email; echo "You submitted: $name, $email"; - // $name과 $email을 사용하여 데이터베이스에 저장하거나 다른 작업 수행 + // save to a database or something else with the $name and $email }); ``` @@ -58,9 +58,9 @@ Flight::route('POST /submit', function(){ ```php Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; - // 또는 + // or $savedLogin = Flight::request()->cookies->myLoginCookie; - // 실제로 저장되었는지 확인하고, 저장되었다면 자동으로 로그인 처리 + // check if it's really saved or not and if it is auto log them in if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -68,11 +68,11 @@ Flight::route('GET /login', function(){ }); ``` -새 쿠키 값을 설정하는 방법에 대한 도움말은 [overclokk/cookie](/awesome-plugins/php-cookie)를 참조하세요. +새 쿠키 값 설정에 대한 도움말은 [overclokk/cookie](/awesome-plugins/php-cookie)를 참조하세요. ### `$_SERVER` -`$_SERVER` 배열은 `getVar()` 메서드를 통해 접근할 수 있는 단축키가 있습니다: +`$_SERVER` 배열에 접근하기 위해 `getVar()` 메서드를 사용할 수 있는 단축키가 있습니다: ```php @@ -84,23 +84,23 @@ $host = Flight::request()->getVar('HTTP_HOST'); 업로드된 파일은 `files` 속성을 통해 접근할 수 있습니다: ```php -// $_FILES 속성에 대한 원시 접근. 아래 권장 접근 방법을 참조하세요 +// raw access to $_FILES property. See below for recommended approach $uploadedFile = Flight::request()->files['myFile']; -// 또는 +// or $uploadedFile = Flight::request()->files->myFile; ``` -자세한 내용은 [Uploaded File Handler](/learn/uploaded-file)를 참조하세요. +더 자세한 정보는 [Uploaded File Handler](/learn/uploaded-file)를 참조하세요. -#### 파일 업로드 처리 +#### Processing File Uploads _v3.12.0_ -프레임워크의 도우미 메서드를 사용하여 파일 업로드를 처리할 수 있습니다. 기본적으로 요청에서 파일 데이터를 가져와 새로운 위치로 이동하는 것입니다. +프레임워크의 도우미 메서드를 사용하여 파일 업로드를 처리할 수 있습니다. 기본적으로 요청에서 파일 데이터를 가져와 새 위치로 이동하는 것입니다. ```php Flight::route('POST /upload', function(){ - // 와 같은 입력 필드가 있는 경우 + // If you had an input field like $uploadedFileData = Flight::request()->getUploadedFiles(); $uploadedFile = $uploadedFileData['myFile']; $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); @@ -111,7 +111,7 @@ Flight::route('POST /upload', function(){ ```php Flight::route('POST /upload', function(){ - // 와 같은 입력 필드가 있는 경우 + // If you had an input field like $uploadedFiles = Flight::request()->getUploadedFiles()['myFiles']; foreach ($uploadedFiles as $uploadedFile) { $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); @@ -119,20 +119,20 @@ Flight::route('POST /upload', function(){ }); ``` -> **보안 참고:** 파일 업로드를 다룰 때 사용자 입력을 항상 검증하고 정제하세요. 업로드할 허용 확장자 유형을 검증하는 것뿐만 아니라, 파일의 "매직 바이트"를 검증하여 사용자가 주장하는 파일 유형이 실제로 맞는지 확인해야 합니다. 이에 대한 [기사](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe), [기사](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/), [라이브러리](https://github.com/RikudouSage/MimeTypeDetector)가 도움이 됩니다. +> **Security Note:** 사용자 입력을 항상 검증하고 정제하세요, 특히 파일 업로드 시에는 더욱 그렇습니다. 업로드할 허용 확장자 유형을 검증해야 하며, 파일의 "매직 바이트"를 검증하여 사용자가 주장하는 파일 유형이 실제로 맞는지 확인해야 합니다. 이에 대한 [articles](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [and](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [libraries](https://github.com/RikudouSage/MimeTypeDetector)가 있습니다. -### 요청 본문 +### Request Body -POST/PUT 요청을 다룰 때와 같이 원시 HTTP 요청 본문을 가져오려면 다음을 수행할 수 있습니다: +POST/PUT 요청을 처리할 때 예를 들어, 원시 HTTP 요청 본문을 가져오려면 다음과 같이 할 수 있습니다: ```php Flight::route('POST /users/xml', function(){ $xmlBody = Flight::request()->getBody(); - // 전송된 XML로 작업 수행. + // do something with the XML that was sent. }); ``` -### JSON 본문 +### JSON Body 콘텐츠 유형이 `application/json`인 요청을 받고 예시 데이터가 `{"id": 123}`인 경우, `data` 속성에서 사용할 수 있습니다: @@ -140,35 +140,35 @@ Flight::route('POST /users/xml', function(){ $id = Flight::request()->data->id; ``` -### 요청 헤더 +### Request Headers -`getHeader()` 또는 `getHeaders()` 메서드를 사용하여 요청 헤더에 접근할 수 있습니다: +요청 헤더는 `getHeader()` 또는 `getHeaders()` 메서드를 사용하여 접근할 수 있습니다: ```php -// Authorization 헤더가 필요한 경우 +// Maybe you need Authorization header $host = Flight::request()->getHeader('Authorization'); -// 또는 +// or $host = Flight::request()->header('Authorization'); -// 모든 헤더를 가져와야 하는 경우 +// If you need to grab all headers $headers = Flight::request()->getHeaders(); -// 또는 +// or $headers = Flight::request()->headers(); ``` -### 요청 메서드 +### Request Method -`method` 속성 또는 `getMethod()` 메서드를 사용하여 요청 메서드에 접근할 수 있습니다: +요청 메서드는 `method` 속성 또는 `getMethod()` 메서드를 사용하여 접근할 수 있습니다: ```php -$method = Flight::request()->method; // 실제로 getMethod()에 의해 채워짐 +$method = Flight::request()->method; // actually populated by getMethod() $method = Flight::request()->getMethod(); ``` -**참고:** `getMethod()` 메서드는 먼저 `$_SERVER['REQUEST_METHOD']`에서 메서드를 가져온 다음, `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']`가 존재하면 이를 덮어쓰거나 `$_REQUEST['_method']`가 존재하면 이를 사용합니다. +**Note:** `getMethod()` 메서드는 먼저 `$_SERVER['REQUEST_METHOD']`에서 메서드를 가져오며, 존재할 경우 `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` 또는 `$_REQUEST['_method']`로 덮어쓸 수 있습니다. -## 요청 객체 속성 +## Request Object Properties 요청 객체는 다음 속성을 제공합니다: @@ -189,34 +189,34 @@ $method = Flight::request()->getMethod(); - **files** - 업로드된 파일 - **secure** - 연결이 보안인지 여부 - **accept** - HTTP accept 매개변수 -- **proxy_ip** - 클라이언트의 프록시 IP 주소. `$_SERVER` 배열을 `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` 순서로 스캔합니다. +- **proxy_ip** - 클라이언트의 프록시 IP 주소. `$_SERVER` 배열에서 `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED`를 순서대로 스캔합니다. - **host** - 요청 호스트 이름 - **servername** - `$_SERVER`의 SERVER_NAME -## URL 도우미 메서드 +## Helper Methods -URL의 부분을 조합하는 데 편리한 몇 가지 도우미 메서드가 있습니다. +URL의 일부를 조합하거나 특정 헤더를 처리하기 위한 몇 가지 도우미 메서드가 있습니다. -### 전체 URL +### Full URL -`getFullUrl()` 메서드를 사용하여 전체 요청 URL에 접근할 수 있습니다: +전체 요청 URL은 `getFullUrl()` 메서드를 사용하여 접근할 수 있습니다: ```php $url = Flight::request()->getFullUrl(); // https://example.com/some/path?foo=bar ``` -### 기본 URL +### Base URL -`getBaseUrl()` 메서드를 사용하여 기본 URL에 접근할 수 있습니다: +기본 URL은 `getBaseUrl()` 메서드를 사용하여 접근할 수 있습니다: ```php // http://example.com/path/to/something/cool?query=yes+thanks $url = Flight::request()->getBaseUrl(); // https://example.com -// 주의: 후행 슬래시 없음. +// Notice, no trailing slash. ``` -## 쿼리 파싱 +## Query Parsing `parseQuery()` 메서드에 URL을 전달하여 쿼리 문자열을 연관 배열로 파싱할 수 있습니다: @@ -225,16 +225,40 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` -## 관련 자료 +## Negotiate Content Accept Types + +_v3.17.2_ + +클라이언트가 보낸 `Accept` 헤더를 기반으로 응답할 최적의 콘텐츠 유형을 결정하기 위해 `negotiateContentType()` 메서드를 사용할 수 있습니다. + +```php + +// Example Accept header: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// The below defines what you support. +$availableTypes = ['application/json', 'application/xml']; +$typeToServe = Flight::request()->negotiateContentType($availableTypes); +if ($typeToServe === 'application/json') { + // Serve JSON response +} elseif ($typeToServe === 'application/xml') { + // Serve XML response +} else { + // Default to something else or throw an error +} +``` + +> **Note:** `Accept` 헤더에 사용 가능한 유형 중 하나가 발견되지 않으면 메서드는 `null`을 반환합니다. `Accept` 헤더가 정의되지 않은 경우, 메서드는 `$availableTypes` 배열의 첫 번째 유형을 반환합니다. + +## See Also - [Routing](/learn/routing) - 라우트를 컨트롤러에 매핑하고 뷰를 렌더링하는 방법. - [Responses](/learn/responses) - HTTP 응답을 사용자 지정하는 방법. - [Why a Framework?](/learn/why-frameworks) - 요청이 큰 그림에 어떻게 맞는지. - [Collections](/learn/collections) - 데이터 컬렉션 작업. - [Uploaded File Handler](/learn/uploaded-file) - 파일 업로드 처리. -## 문제 해결 +## Troubleshooting - `request()->ip`와 `request()->proxy_ip`는 웹 서버가 프록시, 로드 밸런서 등 뒤에 있는 경우 다를 수 있습니다. -## 변경 로그 -- v3.12.0 - 요청 객체를 통해 파일 업로드를 처리할 수 있는 기능 추가. +## Changelog +- v3.17.2 - negotiateContentType() 추가 +- v3.12.0 - 요청 객체를 통해 파일 업로드 처리 기능 추가. - v1.0 - 초기 릴리스. \ No newline at end of file diff --git a/content/v3/ko/learn/responses.md b/content/v3/ko/learn/responses.md index e0301d2d..1f66c3ff 100644 --- a/content/v3/ko/learn/responses.md +++ b/content/v3/ko/learn/responses.md @@ -2,17 +2,17 @@ ## 개요 -Flight는 응답 헤더의 일부를 생성하는 데 도움을 주지만, 사용자에게 다시 보내는 내용에 대한 대부분의 제어를 사용자가 가집니다. 대부분의 경우 `response()` 객체에 직접 접근하지만, Flight는 일부 응답 헤더를 설정하는 데 도움을 주는 헬퍼 메서드를 제공합니다. +Flight는 응답 헤더의 일부를 생성하는 데 도움을 주지만, 사용자에게 보낼 내용에 대한 대부분의 제어를 유지합니다. 대부분의 경우 `response()` 객체에 직접 접근하지만, Flight는 일부 응답 헤더를 설정하는 데 도움을 주는 헬퍼 메서드를 제공합니다. -## 이해 +## 이해하기 -사용자가 [요청](/learn/requests) 요청을 애플리케이션에 보낸 후, 사용자에게 적절한 응답을 생성해야 합니다. 그들은 선호하는 언어, 특정 유형의 압축 처리 가능 여부, 사용자 에이전트 등과 같은 정보를 보냈으며, 모든 것을 처리한 후 적절한 응답을 다시 보내는 시간입니다. 이는 헤더 설정, HTML 또는 JSON 본문 출력, 또는 페이지로 리디렉션하는 것을 포함할 수 있습니다. +사용자가 [요청](/learn/requests) 요청을 애플리케이션에 보낸 후, 적절한 응답을 생성해야 합니다. 그들은 선호하는 언어, 특정 유형의 압축을 처리할 수 있는지, 사용자 에이전트 등과 같은 정보를 보냈으며, 모든 것을 처리한 후 적절한 응답을 보내는 시간입니다. 이는 헤더 설정, HTML 또는 JSON 본문 출력, 또는 페이지로 리디렉션하는 등의 작업일 수 있습니다. ## 기본 사용법 ### 응답 본문 보내기 -Flight는 출력을 버퍼링하기 위해 `ob_start()`를 사용합니다. 이는 `echo` 또는 `print`를 사용하여 사용자에게 응답을 보낼 수 있으며, Flight가 이를 캡처하여 적절한 헤더와 함께 사용자에게 다시 보내는 것을 의미합니다. +Flight는 출력을 버퍼링하기 위해 `ob_start()`를 사용합니다. 이는 `echo` 또는 `print`를 사용하여 사용자에게 응답을 보낼 수 있으며, Flight가 이를 캡처하여 적절한 헤더와 함께 사용자에게 보낸다는 의미입니다. ```php // 이는 "Hello, World!"를 사용자의 브라우저로 보냅니다 @@ -26,27 +26,27 @@ Flight::route('/', function() { // Hello, World! ``` -대안으로, 본문에 추가하기 위해 `write()` 메서드를 호출할 수도 있습니다. +대안으로, `write()` 메서드를 호출하여 본문에 추가할 수도 있습니다. ```php // 이는 "Hello, World!"를 사용자의 브라우저로 보냅니다 Flight::route('/', function() { - // 때때로 필요할 때 작업을 수행하지만, 장황합니다 + // 때때로 필요할 때 작업을 수행하지만 장황합니다 Flight::response()->write("Hello, World!"); // 이 시점에서 설정한 본문을 검색하려면 - // 다음과 같이 할 수 있습니다 + // 이렇게 할 수 있습니다 $body = Flight::response()->getBody(); }); ``` ### JSON -Flight는 JSON 및 JSONP 응답을 보내는 지원을 제공합니다. JSON 응답을 보내기 위해 JSON으로 인코딩할 데이터를 전달합니다: +Flight는 JSON 및 JSONP 응답을 보내는 지원을 제공합니다. JSON 응답을 보내기 위해 JSON 인코딩할 데이터를 전달합니다: ```php Flight::route('/@companyId/users', function(int $companyId) { - // 예를 들어 데이터베이스에서 사용자를 가져오는 방식으로 + // 예를 들어 데이터베이스에서 사용자를 가져오는 등의 작업 $users = Flight::db()->fetchAll("SELECT id, first_name, last_name FROM users WHERE company_id = ?", [ $companyId ]); Flight::json($users); @@ -64,9 +64,9 @@ Flight::route('/@companyId/users', function(int $companyId) { Flight::json(['id' => 123], 201); ``` -#### 예쁘게 출력된 JSON +#### 예쁘게 출력하는 JSON -마지막 위치에 인수를 전달하여 예쁘게 출력(pretty printing)을 활성화할 수도 있습니다: +마지막 위치에 인수를 전달하여 예쁘게 출력할 수도 있습니다: ```php Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT); @@ -74,7 +74,7 @@ Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT); #### JSON 인수 순서 변경 -`Flight::json()`은 매우 레거시 메서드이지만, Flight의 목표는 프로젝트의 하위 호환성을 유지하는 것입니다. 인수의 순서를 다시 하고 더 간단한 구문을 사용하려면, 다른 Flight 메서드처럼 JSON 메서드를 재매핑하면 됩니다 [/learn/extending]: +`Flight::json()`은 매우 오래된 메서드이지만, Flight의 목표는 프로젝트의 이전 호환성을 유지하는 것입니다. 인수의 순서를 다시 설정하여 더 간단한 구문을 사용하려면, [다른 Flight 메서드처럼](/learn/extending) JSON 메서드를 재매핑할 수 있습니다: ```php Flight::map('json', function($data, $code = 200, $options = 0) { @@ -83,7 +83,7 @@ Flight::map('json', function($data, $code = 200, $options = 0) { Flight::_json($data, $code, true, 'utf-8', $options); } -// 이제 다음과 같이 사용할 수 있습니다 +// 이제 이렇게 사용할 수 있습니다 Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT); ``` @@ -91,8 +91,7 @@ Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT); _v3.10.0_ -JSON 응답을 보내고 실행을 중지하려면 `jsonHalt()` 메서드를 사용할 수 있습니다. -이는 권한 부여 유형을 확인하는 경우에 유용하며, 사용자가 권한이 없으면 즉시 JSON 응답을 보내고 기존 본문 내용을 지우고 실행을 중지할 수 있습니다. +JSON 응답을 보내고 실행을 중지하려면 `jsonHalt()` 메서드를 사용할 수 있습니다. 이는 권한 부여를 확인하는 등의 경우에 유용하며, 사용자가 권한이 없으면 JSON 응답을 즉시 보내고 기존 본문 내용을 지우고 실행을 중지할 수 있습니다. ```php Flight::route('/users', function() { @@ -100,10 +99,10 @@ Flight::route('/users', function() { // 사용자가 권한이 있는지 확인 if($authorized === false) { Flight::jsonHalt(['error' => 'Unauthorized'], 401); - // 여기에 exit;가 필요 없습니다. + // 여기서는 exit;가 필요 없습니다. } - // 나머지 라우트와 계속 + // 나머지 라우트로 계속 진행 }); ``` @@ -117,7 +116,7 @@ Flight::route('/users', function() { Flight::halt(401, json_encode(['error' => 'Unauthorized'])); } - // 나머지 라우트와 계속 + // 나머지 라우트로 계속 진행 }); ``` @@ -135,7 +134,7 @@ Flight::route('/', function() { }); ``` -위 사용 사례는 흔하지 않을 수 있지만, [미들웨어](/learn/middleware)에서 사용되면 더 흔할 수 있습니다. +위 사용 사례는 흔하지 않지만, [미들웨어](/learn/middleware)에서 사용된다면 더 흔할 수 있습니다. ### 응답 본문에 콜백 실행 @@ -154,13 +153,13 @@ Flight::response()->addResponseBodyCallback(function($body) { }); ``` -여러 콜백을 추가할 수 있으며, 추가된 순서대로 실행됩니다. 이는 [callable](https://www.php.net/manual/en/language.types.callable.php)을 허용하므로 클래스 배열 `[ $class, 'method' ]`, 클로저 `$strReplace = function($body) { str_replace('hi', 'there', $body); };`, 또는 HTML 코드를 압축하는 함수가 있다면 `'minify'`와 같은 함수 이름을 허용할 수 있습니다. +여러 콜백을 추가할 수 있으며, 추가된 순서대로 실행됩니다. 이는 [callable](https://www.php.net/manual/en/language.types.callable.php)을 허용하므로 클래스 배열 `[ $class, 'method' ]`, 클로저 `$strReplace = function($body) { str_replace('hi', 'there', $body); };`, 또는 HTML 코드를 압축하는 함수 이름 `'minify'` 등을 허용합니다. **참고:** `flight.v2.output_buffering` 구성 옵션을 사용 중이라면 라우트 콜백이 작동하지 않습니다. #### 특정 라우트 콜백 -이것이 특정 라우트에만 적용되도록 하려면 라우트 자체에 콜백을 추가할 수 있습니다: +이것을 특정 라우트에만 적용하려면 라우트 자체에 콜백을 추가할 수 있습니다: ```php Flight::route('/users', function() { @@ -177,20 +176,20 @@ Flight::route('/users', function() { #### 미들웨어 옵션 -[미들웨어](/learn/middleware)를 사용하여 모든 라우트에 콜백을 미들웨어를 통해 적용할 수도 있습니다: +[미들웨어](/learn/middleware)를 사용하여 모든 라우트에 콜백을 적용할 수도 있습니다: ```php // MinifyMiddleware.php class MinifyMiddleware { public function before() { - // 여기에 response() 객체에 콜백을 적용합니다. + // response() 객체에 여기서 콜백을 적용합니다. Flight::response()->addResponseBodyCallback(function($body) { return $this->minify($body); }); } protected function minify(string $body): string { - // 본문을 압축하는 방식으로 + // 본문을 압축하는 등의 작업 return $body; } } @@ -204,7 +203,7 @@ Flight::group('/users', function() { ### 상태 코드 -응답의 상태 코드를 설정하려면 `status` 메서드를 사용합니다: +`status` 메서드를 사용하여 응답의 상태 코드를 설정할 수 있습니다: ```php Flight::route('/@id', function($id) { @@ -226,7 +225,7 @@ Flight::response()->status(); // 200 ### 응답 헤더 설정 -`header` 메서드를 사용하여 응답의 콘텐츠 유형과 같은 헤더를 설정할 수 있습니다: +`header` 메서드를 사용하여 응답의 콘텐츠 유형 등의 헤더를 설정할 수 있습니다: ```php // 이는 "Hello, World!"를 사용자의 브라우저에 일반 텍스트로 보냅니다 @@ -240,7 +239,7 @@ Flight::route('/', function() { ### 리디렉션 -현재 요청을 `redirect()` 메서드를 사용하여 새 URL로 리디렉션할 수 있습니다: +`redirect()` 메서드를 사용하여 현재 요청을 리디렉션할 수 있으며, 새로운 URL을 전달합니다: ```php Flight::route('/login', function() { @@ -262,39 +261,38 @@ Flight::route('/login', function() { > **참고:** 기본적으로 Flight는 HTTP 303 ("See Other") 상태 코드를 보냅니다. 선택적으로 사용자 지정 코드를 설정할 수 있습니다: ```php -Flight::redirect('/new/location', 301); // 영구적 +Flight::redirect('/new/location', 301); // 영구 ``` ### 라우트 실행 중지 -프레임워크를 중지하고 즉시 종료하려면 `halt` 메서드를 호출할 수 있습니다: +`halt` 메서드를 호출하여 프레임워크를 중지하고 즉시 종료할 수 있습니다: ```php Flight::halt(); ``` -선택적 `HTTP` 상태 코드와 메시지를 지정할 수도 있습니다: +선택적으로 `HTTP` 상태 코드와 메시지를 지정할 수도 있습니다: ```php Flight::halt(200, 'Be right back...'); ``` -`halt`를 호출하면 그 시점까지의 모든 응답 내용을 버리고 모든 실행을 중지합니다. -프레임워크를 중지하고 현재 응답을 출력하려면 `stop` 메서드를 사용합니다: +`halt`를 호출하면 그 시점까지의 응답 내용을 버리고 모든 실행을 중지합니다. 프레임워크를 중지하고 현재 응답을 출력하려면 `stop` 메서드를 사용합니다: ```php Flight::stop($httpStatusCode = null); ``` -> **참고:** `Flight::stop()`은 응답을 출력하지만 스크립트 실행을 계속하는 이상한 동작이 있습니다. 이는 원하는 바가 아닐 수 있습니다. `Flight::stop()` 호출 후 `exit` 또는 `return`을 사용하여 추가 실행을 방지할 수 있지만, 일반적으로 `Flight::halt()`를 사용하는 것이 권장됩니다. +> **참고:** `Flight::stop()`은 응답을 출력하지만 스크립트 실행을 계속하므로 원하는 결과가 아닐 수 있습니다. 추가 실행을 방지하기 위해 `Flight::stop()` 호출 후 `exit` 또는 `return`을 사용할 수 있지만, 일반적으로 `Flight::halt()`를 사용하는 것이 권장됩니다. 이는 헤더 키와 값을 응답 객체에 저장합니다. 요청 수명 주기 끝에서 헤더를 빌드하고 응답을 보냅니다. ## 고급 사용법 -### 헤더 즉시 보내기 +### 즉시 헤더 보내기 -헤더에 사용자 지정 작업을 수행해야 하고 작업 중인 코드 라인에서 헤더를 보내야 하는 경우가 있을 수 있습니다. [스트리밍 라우트](/learn/routing)를 설정 중이라면 이것이 필요합니다. 이는 `response()->setRealHeader()`를 통해 달성할 수 있습니다. +헤더에 사용자 지정 작업을 수행해야 하며 작업 중인 코드 라인에서 헤더를 보내야 하는 경우가 있을 수 있습니다. [스트리밍 라우트](/learn/routing)를 설정 중이라면 이것이 필요합니다. 이는 `response()->setRealHeader()`를 통해 달성할 수 있습니다. ```php Flight::route('/', function() { @@ -313,15 +311,15 @@ JSONP 요청의 경우, 콜백 함수를 정의하는 데 사용하는 쿼리 Flight::jsonp(['id' => 123], 'q'); ``` -따라서 `?q=my_func`를 사용한 GET 요청을 하면 다음과 같은 출력을 받아야 합니다: +따라서 `?q=my_func`를 사용한 GET 요청을 하면 다음과 같은 출력을 받을 수 있습니다: ```javascript my_func({"id":123}); ``` -쿼리 매개변수 이름을 전달하지 않으면 기본값으로 `jsonp`를 사용합니다. +쿼리 매개변수 이름을 전달하지 않으면 기본적으로 `jsonp`가 됩니다. -> **참고:** 2025년 이후에도 JSONP 요청을 계속 사용 중이라면 채팅에 참여하여 이유를 알려주세요! 우리는 좋은 전투/공포 이야기를 듣는 것을 좋아합니다! +> **참고:** 2025년 이후에도 JSONP 요청을 사용 중이라면 채팅에 참여하여 이유를 알려주세요! 좋은 전투/공포 이야기를 듣는 것을 좋아합니다! ### 응답 데이터 지우기 @@ -342,11 +340,11 @@ Flight::response()->clearBody(); ### HTTP 캐싱 -Flight는 HTTP 수준 캐싱에 대한 내장 지원을 제공합니다. 캐싱 조건이 충족되면 Flight는 HTTP `304 Not Modified` 응답을 반환합니다. 클라이언트가 동일한 리소스를 다시 요청할 때 로컬에 캐시된 버전을 사용하도록 안내됩니다. +Flight는 HTTP 수준 캐싱에 대한 내장 지원을 제공합니다. 캐싱 조건이 충족되면 Flight는 HTTP `304 Not Modified` 응답을 반환합니다. 클라이언트가 동일한 리소스를 다음에 요청할 때 로컬 캐시된 버전을 사용하도록 안내됩니다. #### 라우트 수준 캐싱 -전체 응답을 캐싱하려면 `cache()` 메서드를 사용하고 캐싱할 시간을 전달할 수 있습니다. +전체 응답을 캐싱하려면 `cache()` 메서드를 사용하고 캐싱 시간을 전달할 수 있습니다. ```php // 이는 응답을 5분 동안 캐싱합니다 @@ -384,21 +382,23 @@ Flight::route('/news', function () { }); ``` -`lastModified` 또는 `etag`를 호출하면 둘 다 캐시 값을 설정하고 확인합니다. 요청 간에 캐시 값이 동일하면 Flight는 즉시 `HTTP 304` 응답을 보내고 처리를 중지합니다. +`lastModified` 또는 `etag`을 호출하면 캐시 값을 설정하고 확인합니다. 요청 간 캐시 값이 동일하면 Flight는 즉시 `HTTP 304` 응답을 보내고 처리를 중지합니다. ### 파일 다운로드 _v3.12.0_ -최종 사용자에게 파일을 스트리밍하는 헬퍼 메서드가 있습니다. `download` 메서드를 사용하고 경로를 전달할 수 있습니다. +사용자에게 파일을 스트리밍하는 헬퍼 메서드가 있습니다. `download` 메서드를 사용하고 경로를 전달할 수 있습니다. ```php Flight::route('/download', function () { Flight::download('/path/to/file.txt'); + // v3.17.1부터 다운로드에 사용자 지정 파일 이름을 지정할 수 있습니다 + Flight::download('/path/to/file.txt', 'custom_name.txt'); }); ``` -## 관련 항목 +## 관련 자료 - [라우팅](/learn/routing) - 라우트를 컨트롤러에 매핑하고 뷰를 렌더링하는 방법. - [요청](/learn/requests) - 들어오는 요청을 처리하는 방법 이해. - [미들웨어](/learn/middleware) - 인증, 로깅 등에 라우트와 함께 미들웨어 사용. @@ -406,10 +406,11 @@ Flight::route('/download', function () { - [확장](/learn/extending) - Flight를 자체 기능으로 확장하는 방법. ## 문제 해결 -- 리디렉션이 작동하지 않는 문제라면 메서드에 `return;`을 추가했는지 확인하세요. -- `stop()`과 `halt()`는 동일한 것이 아닙니다. `halt()`는 실행을 즉시 중지하지만, `stop()`은 실행을 계속할 수 있습니다. +- 리디렉션이 작동하지 않는 문제가 있다면 메서드에 `return;`을 추가했는지 확인하세요. +- `stop()`과 `halt()`는 동일하지 않습니다. `halt()`는 실행을 즉시 중지하지만, `stop()`은 실행을 계속할 수 있습니다. ## 변경 로그 +- v3.17.1 - `downloadFile()` 메서드에 `$fileName` 추가. - v3.12.0 - downloadFile 헬퍼 메서드 추가. - v3.10.0 - `jsonHalt` 추가. - v1.0 - 초기 릴리스. \ No newline at end of file diff --git a/content/v3/ko/learn/routing.md b/content/v3/ko/learn/routing.md index 2b23d06a..1d5ef114 100644 --- a/content/v3/ko/learn/routing.md +++ b/content/v3/ko/learn/routing.md @@ -1,17 +1,17 @@ # 라우팅 ## 개요 -Flight PHP의 라우팅은 URL 패턴을 콜백 함수나 클래스 메서드에 매핑하여 빠르고 간단한 요청 처리를 가능하게 합니다. 이는 최소한의 오버헤드, 초보자 친화적인 사용법, 그리고 외부 종속성 없이 확장성을 위해 설계되었습니다. +Flight PHP의 라우팅은 URL 패턴을 콜백 함수나 클래스 메서드에 매핑하여 빠르고 간단한 요청 처리를 가능하게 합니다. 이는 최소한의 오버헤드, 초보자 친화적인 사용, 그리고 외부 종속성 없이 확장성을 위해 설계되었습니다. -## 이해하기 -라우팅은 Flight에서 HTTP 요청을 애플리케이션 로직에 연결하는 핵심 메커니즘입니다. 라우트를 정의함으로써 다양한 URL이 함수, 클래스 메서드, 또는 컨트롤러 액션을 통해 특정 코드를 트리거하는 방식을 지정합니다. Flight의 라우팅 시스템은 유연하며, 기본 패턴, 명명된 매개변수, 정규 표현식, 그리고 의존성 주입 및 리소스 라우팅과 같은 고급 기능을 지원합니다. 이 접근 방식은 코드를 체계적으로 유지하고 유지보수를 쉽게 하며, 초보자에게는 빠르고 간단하며 고급 사용자에게는 확장 가능합니다. +## 이해 +라우팅은 Flight에서 HTTP 요청을 애플리케이션 로직에 연결하는 핵심 메커니즘입니다. 라우트를 정의함으로써 다양한 URL이 함수, 클래스 메서드, 또는 컨트롤러 액션을 통해 특정 코드를 트리거하는 방식을 지정할 수 있습니다. Flight의 라우팅 시스템은 유연하며, 기본 패턴, 명명된 매개변수, 정규 표현식, 그리고 의존성 주입 및 리소스 라우팅과 같은 고급 기능을 지원합니다. 이 접근 방식은 코드를 체계적으로 유지하고 유지보수를 쉽게 하며, 초보자에게는 빠르고 간단하며 고급 사용자에게는 확장 가능합니다. -> **참고:** 라우팅에 대해 더 이해하고 싶으신가요? ["왜 프레임워크인가?](/learn/why-frameworks)" 페이지를 확인하여 더 자세한 설명을 보세요. +> **참고:** 라우팅에 대해 더 이해하고 싶으신가요? ["프레임워크를 사용하는 이유?](/learn/why-frameworks)" 페이지를 확인하여 더 자세한 설명을 보세요. ## 기본 사용법 ### 간단한 라우트 정의 -Flight의 기본 라우팅은 URL 패턴을 콜백 함수나 클래스와 메서드의 배열로 매칭하여 수행됩니다. +Flight의 기본 라우팅은 URL 패턴을 콜백 함수나 클래스와 메서드의 배열로 매칭합니다. ```php Flight::route('/', function(){ @@ -44,14 +44,14 @@ class GreetingController { Flight::route('/', [ 'GreetingController','hello' ]); // 또는 -Flight::route('/', [ GreetingController::class, 'hello' ]); // 권장 방법 +Flight::route('/', [ GreetingController::class, 'hello' ]); // 선호되는 방법 // 또는 Flight::route('/', [ 'GreetingController::hello' ]); // 또는 Flight::route('/', [ 'GreetingController->hello' ]); ``` -또는 먼저 객체를 생성한 후 메서드를 호출할 수 있습니다: +먼저 객체를 생성한 후 메서드를 호출하는 방식도 있습니다: ```php use flight\Engine; @@ -77,7 +77,7 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **참고:** 프레임워크 내에서 컨트롤러가 호출될 때 기본적으로 `flight\Engine` 클래스가 항상 주입됩니다. [의존성 주입 컨테이너](/learn/dependency-injection-container)를 통해 지정하지 않는 한. +> **참고:** 기본적으로 프레임워크 내에서 컨트롤러가 호출될 때 `flight\Engine` 클래스가 항상 주입됩니다. [의존성 주입 컨테이너](/learn/dependency-injection-container)를 통해 지정하지 않는 한 예외입니다. ### 메서드별 라우팅 @@ -92,14 +92,14 @@ Flight::route('POST /', function () { echo 'I received a POST request.'; }); -// Flight::get()은 라우트를 생성하는 메서드가 아니라 변수를 가져오는 메서드이므로 라우트에 사용할 수 없습니다. +// Flight::get()을 라우트에 사용할 수 없습니다. 이는 변수를 가져오는 메서드이지 라우트를 생성하는 것이 아닙니다. Flight::post('/', function() { /* code */ }); Flight::patch('/', function() { /* code */ }); Flight::put('/', function() { /* code */ }); Flight::delete('/', function() { /* code */ }); ``` -단일 콜백에 여러 메서드를 매핑하려면 `|` 구분 기호를 사용할 수 있습니다: +`|` 구분자를 사용하여 여러 메서드를 단일 콜백에 매핑할 수도 있습니다: ```php Flight::route('GET|POST /', function () { @@ -107,12 +107,43 @@ Flight::route('GET|POST /', function () { }); ``` -### 라우터 객체 사용 +### HEAD 및 OPTIONS 요청에 대한 특별 처리 + +Flight는 `HEAD` 및 `OPTIONS` HTTP 요청에 대한 내장 처리를 제공합니다: + +#### HEAD 요청 + +- **HEAD 요청**은 `GET` 요청과 동일하게 처리되지만, Flight는 클라이언트로 전송하기 전에 응답 본문을 자동으로 제거합니다. +- 이는 `GET`에 대한 라우트를 정의하면 동일한 URL에 대한 HEAD 요청이 헤더만 반환(콘텐츠 없음)하도록 하여 HTTP 표준을 준수합니다. + +```php +Flight::route('GET /info', function() { + echo 'This is some info!'; +}); +// /info에 대한 HEAD 요청은 동일한 헤더를 반환하지만 본문은 없습니다. +``` + +#### OPTIONS 요청 -또한 라우터 객체를 가져와서 헬퍼 메서드를 사용할 수 있습니다: +`OPTIONS` 요청은 정의된 모든 라우트에 대해 Flight가 자동으로 처리합니다. +- OPTIONS 요청이 수신되면 Flight는 `204 No Content` 상태와 해당 라우트에 지원되는 모든 HTTP 메서드를 나열하는 `Allow` 헤더로 응답합니다. +- 커스텀 동작이나 응답 수정을 원하지 않는 한 별도의 OPTIONS 라우트를 정의할 필요가 없습니다. ```php +// 다음과 같이 정의된 라우트의 경우: +Flight::route('GET|POST /users', function() { /* ... */ }); +// /users에 대한 OPTIONS 요청은 다음과 같이 응답합니다: +// +// Status: 204 No Content +// Allow: GET, POST, HEAD, OPTIONS +``` + +### 라우터 객체 사용 + +추가로 라우터 객체를 가져와서 도우미 메서드를 사용할 수 있습니다: + +```php $router = Flight::router(); // Flight::route()처럼 모든 메서드를 매핑합니다. @@ -131,18 +162,18 @@ $router->patch('/users/@id', function() { /* code */}); ``` ### 정규 표현식 (Regex) -라우트에서 정규 표현식을 사용할 수 있습니다: +라우트에 정규 표현식을 사용할 수 있습니다: ```php Flight::route('/user/[0-9]+', function () { - // 이는 /user/1234와 일치합니다. + // 이는 /user/1234와 매칭됩니다. }); ``` -이 방법이 사용 가능하지만, 명명된 매개변수 또는 정규 표현식을 포함한 명명된 매개변수를 사용하는 것이 더 읽기 쉽고 유지보수가 쉽기 때문에 권장됩니다. +이 방법은 사용 가능하지만, 명명된 매개변수 또는 정규 표현식이 포함된 명명된 매개변수를 사용하는 것이 더 읽기 쉽고 유지보수가 용이하므로 권장됩니다. ### 명명된 매개변수 -라우트에서 명명된 매개변수를 지정할 수 있으며, 이는 콜백 함수로 전달됩니다. **이는 라우트의 가독성을 위한 것이지 다른 것이 아닙니다. 아래의 중요한 주의사항 섹션을 참조하세요.** +라우트에 명명된 매개변수를 지정하면 콜백 함수로 전달됩니다. **이는 라우트의 가독성을 위한 것이며, 아래의 중요한 주의 사항 섹션을 참조하세요.** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -150,20 +181,20 @@ Flight::route('/@name/@id', function (string $name, string $id) { }); ``` -`:` 구분 기호를 사용하여 명명된 매개변수에 정규 표현식을 포함할 수도 있습니다: +`:` 구분자를 사용하여 명명된 매개변수에 정규 표현식을 포함할 수도 있습니다: ```php Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { - // 이는 /bob/123과 일치합니다. - // 하지만 /bob/12345와는 일치하지 않습니다. + // 이는 /bob/123과 매칭됩니다. + // 하지만 /bob/12345와는 매칭되지 않습니다. }); ``` -> **참고:** 위치 매개변수와 함께 regex 그룹 `()` 매칭은 지원되지 않습니다. 예: `:'\(` +> **참고:** 위치 매개변수와 함께 매칭되는 regex 그룹 `()`은 지원되지 않습니다. 예: `:'\(` -#### 중요한 주의사항 +#### 중요한 주의 사항 -위 예에서 `@name`이 변수 `$name`에 직접 연결된 것처럼 보이지만, 그렇지 않습니다. 콜백 함수의 매개변수 순서가 전달되는 것을 결정합니다. 콜백 함수의 매개변수 순서를 변경하면 변수도 변경됩니다. 다음은 예입니다: +위 예에서 `@name`이 `$name` 변수에 직접 연결된 것처럼 보이지만, 실제로는 아닙니다. 콜백 함수의 매개변수 순서가 전달되는 것을 결정합니다. 콜백 함수의 매개변수 순서를 변경하면 변수도 변경됩니다. 예시: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -171,17 +202,17 @@ Flight::route('/@name/@id', function (string $id, string $name) { }); ``` -다음 URL로 이동하면: `/bob/123`, 출력은 `hello, 123 (bob)!`가 됩니다. -라우트와 콜백 함수를 설정할 때 **주의하세요**! +다음 URL로 이동하면: `/bob/123`, 출력은 `hello, 123 (bob)!`이 됩니다. +라우트와 콜백 함수를 설정할 때 _주의하세요_! ### 선택적 매개변수 -세그먼트를 괄호로 감싸서 매칭에 선택적인 명명된 매개변수를 지정할 수 있습니다. +URL 세그먼트를 괄호로 감싸서 매칭에 선택적인 명명된 매개변수를 지정할 수 있습니다. ```php Flight::route( '/blog(/@year(/@month(/@day)))', function(?string $year, ?string $month, ?string $day) { - // 이는 다음 URL과 일치합니다: + // 이는 다음 URL과 매칭됩니다: // /blog/2012/12/10 // /blog/2012/12 // /blog/2012 @@ -193,15 +224,15 @@ Flight::route( 매칭되지 않은 선택적 매개변수는 `NULL`로 전달됩니다. ### 와일드카드 라우팅 -매칭은 개별 URL 세그먼트에만 수행됩니다. 여러 세그먼트를 매칭하려면 `*` 와일드카드를 사용할 수 있습니다. +매칭은 개별 URL 세그먼트에만 수행됩니다. 여러 세그먼트를 매칭하려면 `*` 와일드카드를 사용하세요. ```php Flight::route('/blog/*', function () { - // 이는 /blog/2000/02/01과 일치합니다. + // 이는 /blog/2000/02/01과 매칭됩니다. }); ``` -모든 요청을 단일 콜백으로 라우팅하려면 다음을 할 수 있습니다: +모든 요청을 단일 콜백으로 라우팅하려면: ```php Flight::route('*', function () { @@ -212,13 +243,13 @@ Flight::route('*', function () { ### 404 Not Found 핸들러 기본적으로 URL을 찾을 수 없으면 Flight는 매우 간단하고 평범한 `HTTP 404 Not Found` 응답을 보냅니다. -더 사용자 지정된 404 응답을 원한다면 [map](/learn/extending)으로 자신의 `notFound` 메서드를 매핑할 수 있습니다: +더 맞춤형 404 응답을 원하면 [map](/learn/extending)으로 자신의 `notFound` 메서드를 매핑할 수 있습니다: ```php Flight::map('notFound', function() { $url = Flight::request()->url; - // 사용자 지정 템플릿과 함께 Flight::render()를 사용할 수도 있습니다. + // 커스텀 템플릿으로 Flight::render()를 사용할 수도 있습니다. $output = <<My Custom 404 Not Found

The page you have requested {$url} could not be found.

@@ -232,15 +263,43 @@ Flight::map('notFound', function() { }); ``` +### Method Not Found 핸들러 + +기본적으로 URL은 발견되지만 메서드가 허용되지 않으면 Flight는 매우 간단하고 평범한 `HTTP 405 Method Not Allowed` 응답을 보냅니다 (예: Method Not Allowed. Allowed Methods are: GET, POST). 또한 해당 URL에 허용된 메서드와 함께 `Allow` 헤더를 포함합니다. + +더 맞춤형 405 응답을 원하면 [map](/learn/extending)으로 자신의 `methodNotFound` 메서드를 매핑할 수 있습니다: + +```php +use flight\net\Route; + +Flight::map('methodNotFound', function(Route $route) { + $url = Flight::request()->url; + $methods = implode(', ', $route->methods); + + // 커스텀 템플릿으로 Flight::render()를 사용할 수도 있습니다. + $output = <<My Custom 405 Method Not Allowed +

The method you have requested for {$url} is not allowed.

+

Allowed Methods are: {$methods}

+ HTML; + + $this->response() + ->clearBody() + ->status(405) + ->setHeader('Allow', $methods) + ->write($output) + ->send(); +}); +``` + ## 고급 사용법 ### 라우트의 의존성 주입 -컨테이너(PSR-11, PHP-DI, Dice 등)를 통해 의존성 주입을 사용하려면, 직접 객체를 생성하고 컨테이너를 사용하여 객체를 생성하거나 문자열로 클래스와 메서드를 정의하여 호출하는 라우트 유형만 사용할 수 있습니다. 더 많은 정보는 [의존성 주입](/learn/dependency-injection-container) 페이지를 참조하세요. +컨테이너(PSR-11, PHP-DI, Dice 등)를 통한 의존성 주입을 사용하려면, 직접 객체를 생성하고 컨테이너를 사용하여 객체를 생성하거나 문자열로 클래스와 메서드를 정의하는 라우트 유형만 사용할 수 있습니다. 자세한 내용은 [의존성 주입](/learn/dependency-injection-container) 페이지를 참조하세요. -다음은 간단한 예입니다: +간단한 예시: ```php - use flight\database\PdoWrapper; // Greeting.php @@ -261,7 +320,7 @@ class Greeting // index.php // 필요한 매개변수로 컨테이너 설정 -// PSR-11에 대한 자세한 정보는 의존성 주입 페이지를 참조하세요. +// PSR-11에 대한 자세한 내용은 의존성 주입 페이지를 참조하세요. $dice = new \Dice\Dice(); // '$dice = '로 변수를 재할당하는 것을 잊지 마세요!!!!! @@ -307,10 +366,10 @@ Flight::route('/user/*', function () { }); ``` -이제 [미들웨어](/learn/middleware)를 사용하여 이와 같은 복잡한 사용 사례를 처리하는 것이 권장됩니다. +이제 [미들웨어](/learn/middleware)를 사용하여 이러한 복잡한 사용 사례를 처리하는 것을 권장합니다. ### 라우트 별칭 -라우트에 별칭을 할당하면, 나중에 앱에서 동적으로 해당 별칭을 호출하여 코드에서 나중에 생성할 수 있습니다(예: HTML 템플릿의 링크 또는 리디렉션 URL 생성). +라우트에 별칭을 지정하면 나중에 코드에서 동적으로 호출하여 HTML 템플릿의 링크나 리다이렉트 URL 생성 등에 사용할 수 있습니다. ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); @@ -328,13 +387,12 @@ class UserController { Flight::redirect($redirectUrl); } } - ``` -URL이 변경될 경우 특히 유용합니다. 위 예에서 사용자가 `/admin/users/@id`로 이동했다고 가정해 보세요. -라우트에 별칭이 있으면 코드에서 모든 이전 URL을 찾고 변경할 필요가 없으며, 별칭은 이제 `/admin/users/5`를 반환합니다. +URL이 변경될 때 특히 유용합니다. 위 예에서 사용자가 `/admin/users/@id`로 이동했다고 가정하면. +라우트에 별칭이 있으면 코드의 모든 이전 URL을 찾고 변경할 필요가 없으며, 별칭이 이제 `/admin/users/5`를 반환합니다. -그룹에서도 라우트 별칭이 작동합니다: +그룹 내에서도 라우트 별칭이 작동합니다: ```php Flight::group('/users', function() { @@ -348,7 +406,7 @@ Flight::group('/users', function() { 매칭된 라우트 정보를 검사하려면 2가지 방법이 있습니다: 1. `Flight::router()` 객체의 `executedRoute` 속성을 사용할 수 있습니다. -2. 라우트 메서드의 세 번째 매개변수로 `true`를 전달하여 콜백으로 라우트 객체를 전달받을 수 있습니다. 라우트 객체는 항상 콜백 함수로 전달되는 마지막 매개변수가 됩니다. +2. 라우트 메서드의 세 번째 매개변수로 `true`를 전달하여 콜백으로 라우트 객체를 요청할 수 있습니다. 라우트 객체는 항상 콜백 함수의 마지막 매개변수로 전달됩니다. #### `executedRoute` ```php @@ -364,21 +422,21 @@ Flight::route('/', function() { // 매칭 정규 표현식 $route->regex; - // URL 패턴에서 사용된 '*'의 내용을 포함 + // URL 패턴의 '*' 내용 포함 $route->splat; - // URL 경로를 보여줍니다....정말 필요하다면 + // URL 경로 표시... 정말 필요하다면 $route->pattern; - // 이 라우트에 할당된 미들웨어를 보여줍니다 + // 이 라우트에 할당된 미들웨어 표시 $route->middleware; - // 이 라우트에 할당된 별칭을 보여줍니다 + // 이 라우트에 할당된 별칭 표시 $route->alias; }); ``` -> **참고:** `executedRoute` 속성은 라우트가 실행된 후에만 설정됩니다. 라우트가 실행되기 전에 접근하려 하면 `NULL`입니다. [미들웨어](/learn/middleware)에서도 executedRoute를 사용할 수 있습니다! +> **참고:** `executedRoute` 속성은 라우트가 실행된 후에만 설정됩니다. 라우트 실행 전에 접근하려 하면 `NULL`입니다. [미들웨어](/learn/middleware)에서도 executedRoute를 사용할 수 있습니다! #### 라우트 정의에 `true` 전달 ```php @@ -392,32 +450,32 @@ Flight::route('/', function(\flight\net\Route $route) { // 매칭 정규 표현식 $route->regex; - // URL 패턴에서 사용된 '*'의 내용을 포함 + // URL 패턴의 '*' 내용 포함 $route->splat; - // URL 경로를 보여줍니다....정말 필요하다면 + // URL 경로 표시... 정말 필요하다면 $route->pattern; - // 이 라우트에 할당된 미들웨어를 보여줍니다 + // 이 라우트에 할당된 미들웨어 표시 $route->middleware; - // 이 라우트에 할당된 별칭을 보여줍니다 + // 이 라우트에 할당된 별칭 표시 $route->alias; -}, true);// <-- 이 true 매개변수가 그 일을 합니다. +}, true);// <-- 이 true 매개변수가 이를 가능하게 합니다. ``` ### 라우트 그룹화 및 미들웨어 -관련 라우트를 함께 그룹화해야 할 때가 있을 수 있습니다(예: `/api/v1`). +관련 라우트를 함께 그룹화해야 할 때가 있습니다 (예: `/api/v1`). `group` 메서드를 사용하여 이를 수행할 수 있습니다: ```php Flight::group('/api/v1', function () { Flight::route('/users', function () { - // /api/v1/users와 일치 + // /api/v1/users와 매칭 }); Flight::route('/posts', function () { - // /api/v1/posts와 일치 + // /api/v1/posts와 매칭 }); }); ``` @@ -427,24 +485,24 @@ Flight::group('/api/v1', function () { ```php Flight::group('/api', function () { Flight::group('/v1', function () { - // Flight::get()은 변수를 가져옵니다. 라우트를 설정하지 않습니다! 아래 객체 컨텍스트 참조 + // Flight::get()은 변수를 가져오며 라우트를 설정하지 않습니다! 아래 객체 컨텍스트 참조 Flight::route('GET /users', function () { - // GET /api/v1/users와 일치 + // GET /api/v1/users와 매칭 }); Flight::post('/posts', function () { - // POST /api/v1/posts와 일치 + // POST /api/v1/posts와 매칭 }); Flight::put('/posts/1', function () { - // PUT /api/v1/posts와 일치 + // PUT /api/v1/posts와 매칭 }); }); Flight::group('/v2', function () { - // Flight::get()은 변수를 가져옵니다. 라우트를 설정하지 않습니다! 아래 객체 컨텍스트 참조 + // Flight::get()은 변수를 가져오며 라우트를 설정하지 않습니다! 아래 객체 컨텍스트 참조 Flight::route('GET /users', function () { - // GET /api/v2/users와 일치 + // GET /api/v2/users와 매칭 }); }); }); @@ -452,7 +510,7 @@ Flight::group('/api', function () { #### 객체 컨텍스트와 그룹화 -다음 방식으로 `Engine` 객체와 함께 라우트 그룹화를 여전히 사용할 수 있습니다: +다음 방식으로 `Engine` 객체와 함께 라우트 그룹화를 사용할 수 있습니다: ```php $app = Flight::app(); @@ -461,25 +519,25 @@ $app->group('/api/v1', function (Router $router) { // $router 변수를 사용 $router->get('/users', function () { - // GET /api/v1/users와 일치 + // GET /api/v1/users와 매칭 }); $router->post('/posts', function () { - // POST /api/v1/posts와 일치 + // POST /api/v1/posts와 매칭 }); }); ``` -> **참고:** `$router` 객체를 사용한 라우트 및 그룹 정의의 권장 방법입니다. +> **참고:** `$router` 객체를 사용한 라우트와 그룹 정의의 선호되는 방법입니다. #### 미들웨어와 그룹화 -라우트 그룹에 미들웨어를 할당할 수도 있습니다: +라우트 그룹에 미들웨어를 지정할 수도 있습니다: ```php Flight::group('/api/v1', function () { Flight::route('/users', function () { - // /api/v1/users와 일치 + // /api/v1/users와 매칭 }); }, [ MyAuthMiddleware::class ]); // 인스턴스를 사용하려면 [ new MyAuthMiddleware() ] ``` @@ -544,7 +602,7 @@ class UsersController } ``` -> **참고**: 새로 추가된 라우트를 확인하려면 `php runway routes`를 실행하세요. +> **참고**: 새로 추가된 라우트를 보려면 `php runway routes`를 실행하세요. #### 리소스 라우트 사용자 지정 @@ -553,7 +611,7 @@ class UsersController ##### 별칭 베이스 `aliasBase`를 구성할 수 있습니다. 기본적으로 별칭은 지정된 URL의 마지막 부분입니다. -예를 들어 `/users/`는 `aliasBase`가 `users`가 됩니다. 이러한 라우트가 생성될 때 별칭은 `users.index`, `users.create` 등이 됩니다. 별칭을 변경하려면 `aliasBase`를 원하는 값으로 설정하세요. +예를 들어 `/users/`는 `aliasBase`가 `users`가 됩니다. 이러한 라우트가 생성되면 별칭은 `users.index`, `users.create` 등이 됩니다. 별칭을 변경하려면 `aliasBase`를 원하는 값으로 설정하세요. ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); @@ -561,7 +619,7 @@ Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); ##### Only 및 Except -`only` 및 `except` 옵션을 사용하여 생성할 라우트를 지정할 수도 있습니다. +`only`와 `except` 옵션을 사용하여 생성할 라우트를 지정할 수 있습니다. ```php // 이 메서드만 화이트리스트하고 나머지는 블랙리스트 @@ -573,11 +631,11 @@ Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` -이것은 라우트를 생성할지 지정할 수 있는 화이트리스트 및 블랙리스트 옵션입니다. +이는 생성할 라우트를 지정할 수 있는 화이트리스트 및 블랙리스트 옵션입니다. ##### 미들웨어 -`resource` 메서드가 생성한 각 라우트에 실행될 미들웨어를 지정할 수도 있습니다. +`resource` 메서드로 생성된 각 라우트에 실행될 미들웨어를 지정할 수도 있습니다. ```php Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]); @@ -593,8 +651,7 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid #### 수동 헤더와 스트림 -라우트에서 `stream()` 메서드를 사용하여 클라이언트에 응답을 스트리밍할 수 있습니다. -이 경우 클라이언트에 아무것도 출력하기 전에 모든 헤더를 수동으로 설정해야 합니다. +라우트의 `stream()` 메서드를 사용하여 클라이언트에 응답을 스트리밍할 수 있습니다. 이렇게 하면 클라이언트에 아무것도 출력하기 전에 모든 헤더를 수동으로 설정해야 합니다. 이는 `header()` PHP 함수나 `Flight::response()->setRealHeader()` 메서드로 수행됩니다. ```php @@ -602,12 +659,12 @@ Flight::route('/@filename', function($filename) { $response = Flight::response(); - // 명백히 경로를 정화하고 그 밖의 것을 수행합니다. + // 명백히 경로를 정화하는 등의 작업을 수행합니다. $fileNameSafe = basename($filename); - // 라우트가 실행된 후 여기서 추가 헤더를 설정해야 한다면 - // 클라이언트에 에코되기 전에 정의해야 합니다. - // 모두 header() 함수의 원시 호출이거나 + // 라우트 실행 후 추가 헤더를 설정해야 하는 경우 + // 아무것도 에코되기 전에 정의해야 합니다. + // 모두 header() 함수의 raw 호출이거나 // Flight::response()->setRealHeader() 호출이어야 합니다. header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); // 또는 @@ -619,7 +676,7 @@ Flight::route('/@filename', function($filename) { Flight::halt(404, 'File not found'); } - // 원한다면 콘텐츠 길이를 수동으로 설정 + // 원하면 콘텐츠 길이를 수동으로 설정 header('Content-Length: '.filesize($filePath)); // 또는 $response->setRealHeader('Content-Length: '.filesize($filePath)); @@ -627,7 +684,7 @@ Flight::route('/@filename', function($filename) { // 파일을 읽으면서 클라이언트에 스트리밍 readfile($filePath); -// 여기서 마법의 줄입니다. +// 여기가 마법의 줄입니다. })->stream(); ``` @@ -638,10 +695,10 @@ Flight::route('/@filename', function($filename) { ```php Flight::route('/stream-users', function() { - // 여기서 원하는 추가 헤더를 추가할 수 있습니다. + // 여기에 원하는 추가 헤더를 추가할 수 있습니다. // header() 또는 Flight::response()->setRealHeader()를 사용해야 합니다. - // 데이터를 어떻게 가져오든, 예시로... + // 데이터 가져오는 방식 예시... $users_stmt = Flight::db()->query("SELECT id, first_name, last_name FROM users"); echo '{'; @@ -652,7 +709,7 @@ Flight::route('/stream-users', function() { echo ','; } - // 데이터를 클라이언트에 보내기 위해 필요합니다. + // 클라이언트에 데이터를 보내기 위해 필요 ob_flush(); } echo '}'; @@ -661,7 +718,7 @@ Flight::route('/stream-users', function() { })->streamWithHeaders([ 'Content-Type' => 'application/json', 'Content-Disposition' => 'attachment; filename="users.json"', - // 선택적 상태 코드, 기본값 200 + // 선택적 상태 코드, 기본 200 'status' => 200 ]); ``` @@ -669,33 +726,31 @@ Flight::route('/stream-users', function() { ## 관련 자료 - [미들웨어](/learn/middleware) - 인증, 로깅 등에 라우트와 함께 미들웨어 사용. - [의존성 주입](/learn/dependency-injection-container) - 라우트에서 객체 생성 및 관리를 단순화. -- [왜 프레임워크인가?](/learn/why-frameworks) - Flight와 같은 프레임워크 사용의 이점 이해. -- [확장](/learn/extending) - `notFound` 메서드를 포함한 Flight 확장 방법. +- [프레임워크를 사용하는 이유?](/learn/why-frameworks) - Flight와 같은 프레임워크의 이점 이해. +- [확장](/learn/extending) - `notFound` 메서드를 포함한 Flight의 사용자 지정 기능 확장 방법. - [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - 정규 표현식 매칭을 위한 PHP 함수. ## 문제 해결 -- 라우트 매개변수는 이름이 아닌 순서대로 매칭됩니다. 콜백 매개변수 순서가 라우트 정의와 일치하는지 확인하세요. +- 라우트 매개변수는 이름이 아닌 순서에 따라 매칭됩니다. 콜백 매개변수 순서가 라우트 정의와 일치하는지 확인하세요. - `Flight::get()`은 라우트를 정의하지 않습니다; 라우팅에는 `Flight::route('GET /...')` 또는 그룹의 Router 객체 컨텍스트(예: `$router->get(...)`)를 사용하세요. - executedRoute 속성은 라우트 실행 후에만 설정됩니다; 실행 전에 NULL입니다. - 스트리밍은 레거시 Flight 출력 버퍼링 기능이 비활성화되어야 합니다(`flight.v2.output_buffering = false`). -- 의존성 주입의 경우, 특정 라우트 정의만 컨테이너 기반 인스턴스화를 지원합니다. +- 의존성 주입의 경우, 컨테이너 기반 인스턴스화를 지원하는 특정 라우트 정의만 사용하세요. ### 404 Not Found 또는 예상치 못한 라우트 동작 -404 Not Found 오류를 보고 있지만(인생을 걸고 정말 거기 있고 오타가 아니라고 맹세하더라도) 이는 라우트 엔드포인트에서 값을 반환하는 대신 에코하는 문제일 수 있습니다. 이유는 의도적ですが 일부 개발자에게 숨어들 수 있습니다. +404 Not Found 오류를 보고 있지만 (생명이 걸려도 타이포가 아니라고 맹세함) 실제로 라우트 엔드포인트에서 값을 반환하는 대신 에코만 하는 문제일 수 있습니다. 이는 의도적이며 일부 개발자에게 은밀하게 다가올 수 있습니다. ```php - Flight::route('/hello', function(){ // 이는 404 Not Found 오류를 일으킬 수 있습니다. return 'Hello World'; }); -// 아마 원하는 것 +// 원하는 것 Flight::route('/hello', function(){ echo 'Hello World'; }); - ``` 이유는 라우터에 내장된 특수 메커니즘 때문으로, 반환 출력을 "다음 라우트로 이동" 신호로 처리합니다. diff --git a/content/v3/lv/awesome-plugins/apm.md b/content/v3/lv/awesome-plugins/apm.md index eff4a5e4..e4d7fb2f 100644 --- a/content/v3/lv/awesome-plugins/apm.md +++ b/content/v3/lv/awesome-plugins/apm.md @@ -1,12 +1,14 @@ # FlightPHP APM Dokumentācija -Laipni lūgti FlightPHP APM—jūsu aplikācijas personīgais veiktspējas treneris! Šis ceļvedis ir jūsu rokasgrāmata, lai iestatītu, izmantotu un apgūtu Application Performance Monitoring (APM) ar FlightPHP. Vai jūs meklējat lēnus pieprasumus vai vienkārši vēlaties izklaidēties ar latentuma diagrammām, mēs esam to pārklājuši. Padarīsim jūsu aplikāciju ātrāku, lietotājus laimīgākus un atkļūdošanas sesijas vieglākas! +Laipni lūdzam FlightPHP APM — jūsu lietojumprogrammas personīgais veiktspējas treneris! Šis ceļvedis ir jūsu ceļakarte, lai iestatītu, izmantotu un apgūtu Lietojumprogrammas veiktspējas uzraudzību (APM) ar FlightPHP. Vai nu jūs meklējat lēnus pieprasījumus, vai vienkārši vēlaties iedziļināties latentuma diagrammās, mēs jums palīdzēsim. Padarīsim jūsu lietojumprogrammu ātrāku, jūsu lietotājus laimīgākus un jūsu atkļūdošanas sesijas vieglas! + +Apskatiet [demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) Flight Docs vietnes panelim. ![FlightPHP APM](/images/apm.png) -## Kāpēc APM ir svarīgs +## Kāpēc APM ir svarīga -Iedomājieties: jūsu aplikācija ir aizņemts restorāns. Bez veida izsekot, cik ilgi ņem pasūtījumi vai kur virtuvē ir aizkavēšanās, jūs minat, kāpēc klienti aiziet neapmierināti. APM ir jūsu pavārs palīgs—tas vēro katru soli, no ienākošiem pieprasījumiem līdz datubāzes vaicājumiem, un atzīmē visu, kas palēnina jūs. Lēnas lapas zaudē lietotājus (pētījumi saka, ka 53% izlec, ja vietne ielādējas vairāk par 3 sekundēm!), un APM palīdz noķert šīs problēmas *pirms* tās sāp. Tas ir proaktīvs miers—mazāk “kāpēc tas ir salauzts?” momentu, vairāk “skatieties, cik gludi tas darbojas!” uzvaru. +Iedomājieties: jūsu lietojumprogramma ir aizņemta restorāns. Bez veida, kā izsekot, cik ilgi aizņem pasūtījumi vai kur virtuvē rodas aizkavēšanās, jūs minaties, kāpēc klienti aiziet neapmierināti. APM ir jūsu pavāra palīgs — tas uzrauga katru soli, no ienākošajiem pieprasījumiem līdz datubāzes vaicājumiem, un atzīmē visu, kas jūs palēnina. Lēnas lapas zaudē lietotājus (pētījumi saka, ka 53% aiziet, ja vietne ielādējas vairāk nekā 3 sekundes!), un APM palīdz jums noķert šīs problēmas *pirms* tās sadod. Tas ir proaktīvs mierinājums — mazāk “kāpēc tas ir salūzis?” brīžu, vairāk “paskatieties, cik gludi tas darbojas!” uzvaru. ## Instalācija @@ -17,66 +19,66 @@ composer require flightphp/apm ``` Jums būs nepieciešams: -- **PHP 7.4+**: Saglabā saderību ar LTS Linux izdali, vienlaikus atbalstot mūsdienīgu PHP. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Vieglais ietvars, ko mēs uzlabojam. +- **PHP 7.4+**: Nodrošina saderību ar LTS Linux izplatījumiem, vienlaikus atbalstot modernu PHP. +- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Vieglā ietvara, ko mēs uzlabojam. ## Atbalstītās datubāzes -FlightPHP APM pašlaik atbalsta šādas datubāzes metrikas glabāšanai: +FlightPHP APM pašlaik atbalsta šādas datubāzes metriku uzglabāšanai: -- **SQLite3**: Vienkārša, failā balstīta, un lieliska lokālai izstrādei vai mazām aplikācijām. Noklusētā opcija lielākajā daļā iestatījumu. -- **MySQL/MariaDB**: Ideāla lielākiem projektiem vai produkcijas vidēm, kur nepieciešama izturīga, mērogojama glabāšana. +- **SQLite3**: Vienkārša, failu balstīta, lieliska lokālai izstrādei vai mazām lietojumprogrammām. Noklusējuma opcija lielākajā daļā iestatījumu. +- **MySQL/MariaDB**: Ideāla lielākiem projektiem vai produkcijas vidēm, kur nepieciešama robusta, mērogojama uzglabāšana. -Jūs varat izvēlēties savu datubāzes tipu konfigurācijas solī (skatiet zemāk). Pārliecinieties, ka jūsu PHP vide ir instalējusi nepieciešamās paplašinājumus (piemēram, `pdo_sqlite` vai `pdo_mysql`). +Jūs varat izvēlēties datubāzes tipu konfigurācijas solī (skatiet zemāk). Pārliecinieties, ka jūsu PHP videi ir instalētas nepieciešamās paplašinājumi (piem., `pdo_sqlite` vai `pdo_mysql`). ## Sākšana -Šeit ir jūsu solis-pa-solim ceļš uz APM lieliskumu: +Šeit ir jūsu soli pa solim ceļš uz APM lieliskumu: ### 1. Reģistrējiet APM Ievietojiet to savā `index.php` vai `services.php` failā, lai sāktu izsekošanu: ```php -use flight\apm\logger\LoggerFactory; // Importē konfigurācijas izveides rīku +use flight\apm\logger\LoggerFactory; use flight\Apm; -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); // Izveido loggeri no konfigurācijas -$Apm = new Apm($ApmLogger); // Izveido APM objektu -$Apm->bindEventsToFlightInstance($app); // Saistiet ar Flight instanci +$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); +$Apm = new Apm($ApmLogger); +$Apm->bindEventsToFlightInstance($app); // Ja pievienojat datubāzes savienojumu -// Tas jābūt PdoWrapper vai PdoQueryCapture no Tracy Extensions +// Jābūt PdoWrapper vai PdoQueryCapture no Tracy Extensions $pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True nepieciešams, lai iespējotu izsekošanu APM. $Apm->addPdoConnection($pdo); ``` -**Kas notiek šeit?** -- `LoggerFactory::create()` paņem jūsu konfigurāciju (vairāk par to drīz) un iestata loggeri—pēc noklusējuma SQLite. -- `Apm` ir zvaigzne—tas klausās Flight notikumus (pieprasījumi, maršruti, kļūdas utt.) un savāc metrikas. -- `bindEventsToFlightInstance($app)` saista to visu ar jūsu Flight aplikāciju. +**Kas šeit notiek?** +- `LoggerFactory::create()` paņem jūsu konfigurāciju (vairāk par to drīz) un iestata žurnālu — pēc noklusējuma SQLite. +- `Apm` ir zvaigzne — tas klausās Flight notikumus (pieprasījumus, maršrutus, kļūdas utt.) un savāc metrikas. +- `bindEventsToFlightInstance($app)` saista visu ar jūsu Flight lietojumprogrammu. -**Profesionāls padoms: Paraugu ņemšana** -Ja jūsu aplikācija ir aizņemta, žurnālošana *katram* pieprasījumam var pārslogot lietas. Izmantojiet paraugu ņemšanas līmeni (0.0 līdz 1.0): +**Pro Padoms: Paraugšana** +Ja jūsu lietojumprogramma ir aizņemta, žurnālošana *katra* pieprasījuma var pārslodzes. Izmantojiet paraugu (0.0 līdz 1.0): ```php $Apm = new Apm($ApmLogger, 0.1); // Žurnālo 10% pieprasījumu ``` -Tas uztur veiktspēju asu, vienlaikus sniedzot stabilus datus. +Tas saglabā veiktspēju ātru, vienlaikus dodot jums stingrus datus. ### 2. Konfigurējiet to -Izpildiet to, lai izveidotu `.runway-config.json`: +Palaidiet šo, lai izveidotu jūsu `.runway-config.json`: ```bash php vendor/bin/runway apm:init ``` -**Kas tas dara?** -- Palaid maģistru, kas jautā, no kurienes nāk izejmateriāla metrikas (avots) un kur iet apstrādātie dati (mērķis). -- Noklusētā ir SQLite—piemēram, `sqlite:/tmp/apm_metrics.sqlite` avotam, cits mērķim. -- Jūs saņemsiet konfigurāciju, piemēram: +**Ko tas dara?** +- Palaida vedni, kas jautā, no kurienes nāk neapstrādātās metrikas (avots) un kur iet apstrādātie dati (mērķis). +- Noklusējums ir SQLite — piem., `sqlite:/tmp/apm_metrics.sqlite` avotam, cits mērķim. +- Jūs iegūsiet konfigurāciju kā: ```json { "apm": { @@ -88,70 +90,70 @@ php vendor/bin/runway apm:init } ``` -> Šis process arī jautās, vai vēlaties palaist migrācijas šim iestatījumam. Ja jūs to iestatāt pirmo reizi, atbilde ir jā. +> Šis process arī jautās, vai vēlaties palaist migrācijas šim iestatījumam. Ja iestatāt to pirmo reizi, atbilde ir jā. **Kāpēc divas vietas?** -Neapstrādātās metrikas sakrājas ātri (domājiet nefiltrētus žurnālus). Darbinieks tās apstrādā strukturētā mērķī priekš paneļa. Tas uztur lietas kārtīgas! +Neapstrādātās metrikas uzkrājas ātri (domājiet nefiltrētus žurnālus). Darbinieks tās apstrādā strukturētā mērķī panelim. Saglabā visu kārtīgu! ### 3. Apstrādājiet metrikas ar darbinieku -Darbinieks pārvērš neapstrādātās metrikas par paneļa gataviem datiem. Izpildiet to vienreiz: +Darbinieks pārvērš neapstrādātās metrikas datus, kas gatavi panelim. Palaidiet to vienreiz: ```bash php vendor/bin/runway apm:worker ``` -**Kas tas dara?** -- Lasīt no jūsu avota (piemēram, `apm_metrics.sqlite`). -- Apstrādā līdz 100 metriku (noklusētā partijas lielums) jūsu mērķī. -- Pārtrauc, kad pabeigts vai ja nav metrikas. +**Ko tas dara?** +- Lasīt no jūsu avota (piem., `apm_metrics.sqlite`). +- Apstrādā līdz 100 metriku (noklusējuma partijas lielums) jūsu mērķī. +- Apstājas, kad pabeigts vai ja nav metrikas. -**Uzturiet to darbināšanā** -Produkcijas aplikācijām jūs gribēsiet nepārtrauktu apstrādi. Šeit ir jūsu opcijas: +**Uzturiet to darbojošos** +Dzīvām lietojumprogrammām vēlaties nepārtrauktu apstrādi. Šeit ir jūsu opcijas: -- **Dēmona režīms**: +- **Daemon režīms**: ```bash php vendor/bin/runway apm:worker --daemon ``` - Darbojas mūžīgi, apstrādājot metrikas, kad tās nāk. Lieliski attīstībai vai maziem iestatījumiem. + Darbojas mūžīgi, apstrādājot metrikas, kad tās nāk. Lieliski izstrādei vai maziem iestatījumiem. - **Crontab**: Pievienojiet to savam crontab (`crontab -e`): ```bash * * * * * php /path/to/project/vendor/bin/runway apm:worker ``` - Palaid katru minūti—ideāli produkcijai. + Palaid katru minūti — ideāli produkcijai. - **Tmux/Screen**: - Sāciet atdalāmu sesiju: + Sāciet atvienojamu sesiju: ```bash tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon - # Ctrl+B, tad D, lai atdalītos; `tmux attach -t apm-worker`, lai pievienotos atpakaļ + # Ctrl+B, tad D, lai atvienotu; `tmux attach -t apm-worker` lai savienotu atkārtoti ``` - Uztur to darbināšanā pat, ja jūs izlogojaties. + Uztur to darbojošos pat ja izreģistrējaties. -- **Pielāgotas izmaiņas**: +- **Pielāgoti uzstādījumi**: ```bash php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 ``` - - `--batch_size 50`: Apstrādāj 50 metrikas vienlaikus. - - `--max_messages 1000`: Pārtrauc pēc 1000 metriku. + - `--batch_size 50`: Apstrādāt 50 metrikas uzreiz. + - `--max_messages 1000`: Apstāties pēc 1000 metriku. - `--timeout 300`: Iziet pēc 5 minūtēm. -**Kāpēc to darīt?** +**Kāpēc censties?** Bez darbinieka jūsu panelis ir tukšs. Tas ir tilts starp neapstrādātiem žurnāliem un izmantojamiem ieskatiem. ### 4. Palaidiet paneli -Skatiet jūsu aplikācijas vitālos rādītājus: +Redziet jūsu lietojumprogrammas vitālos rādītājus: ```bash php vendor/bin/runway apm:dashboard ``` **Kas tas ir?** -- Palaid PHP serveri uz `http://localhost:8001/apm/dashboard`. +- Palaid PHP serveri pie `http://localhost:8001/apm/dashboard`. - Rāda pieprasījumu žurnālus, lēnus maršrutus, kļūdu līmeņus un vairāk. **Pielāgojiet to**: @@ -162,52 +164,52 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l - `--port 8080`: Izmanto citu portu, ja 8001 ir aizņemts. - `--php-path`: Norāda uz PHP, ja tas nav jūsu PATH. -Atveriet URL pārlūkā un izpētiet! +Atveriet URL savā pārlūkprogrammā un izpētiet! #### Produkcijas režīms -Produkcijā jums var nākties izmēģināt dažas tehnikas, lai paneli palaistu, jo, iespējams, ir ugunsmūri un citas drošības mērvienības. Šeit ir dažas opcijas: +Produkcijā jums var nākties izmēģināt dažas tehnikas, lai panelis darbotos, jo droši vien ir ugunsmūri un citas drošības pasākumi. Šeit ir dažas opcijas: -- **Izmantojiet apgriezto starpniekserveri**: Iestatiet Nginx vai Apache, lai pārsūtītu pieprasījumus uz paneli. -- **SSH Tunelis**: Ja jūs varat SSH uz serveri, izmantojiet `ssh -L 8080:localhost:8001 youruser@yourserver`, lai tunelētu paneli uz jūsu lokālo mašīnu. -- **VPN**: Ja jūsu serveris ir aiz VPN, pievienojieties tam un piekļūstiet panelim tieši. -- **Konfigurējiet Ugunsmūri**: Atveriet portu 8001 jūsu IP vai servera tīklam. (vai kādu portu, ko esat iestatījis). -- **Konfigurējiet Apache/Nginx**: Ja jums ir tīmekļa serveris priekš aplikācijas, jūs varat konfigurēt to uz domēna vai apakšdomēna. Ja jūs to darāt, jūs iestatīsiet dokumenta sakni uz `/path/to/your/project/vendor/flightphp/apm/dashboard` +- **Izmantojiet reverso proxy**: Iestatiet Nginx vai Apache, lai pārsūtītu pieprasījumus panelim. +- **SSH tunelis**: Ja varat SSH uz serveri, izmantojiet `ssh -L 8080:localhost:8001 youruser@yourserver`, lai tunelētu paneli uz jūsu lokālo mašīnu. +- **VPN**: Ja jūsu serveris ir aiz VPN, savienojieties ar to un piekļūstiet panelim tieši. +- **Konfigurējiet ugunsmūri**: Atveriet portu 8001 jūsu IP vai servera tīklam. (vai kādu portu jūs iestatījāt). +- **Konfigurējiet Apache/Nginx**: Ja jums ir tīmekļa serveris jūsu lietojumprogrammas priekšā, jūs varat to konfigurēt domēnam vai apakšdomēnam. Ja to darāt, iestatīsiet dokumentu sakni uz `/path/to/your/project/vendor/flightphp/apm/dashboard` -#### Vēlaties citu paneli? +#### Vai vēlaties citu paneli? -Jūs varat izveidot savu paneli, ja vēlaties! Skatiet `vendor/flightphp/apm/src/apm/presenter` direktoriju idejām, kā prezentēt datus jūsu panelim! +Jūs varat izveidot savu paneli, ja vēlaties! Apskatiet vendor/flightphp/apm/src/apm/presenter direktoriju idejām, kā prezentēt datus savam panelim! -## Paneļa funkcijas +## Panaļa funkcijas -Panelis ir jūsu APM štābs—šeit ir, ko jūs redzēsiet: +Panels ir jūsu APM galvenā mītne — šeit ir, ko redzēsiet: -- **Pieprasījumu žurnāls**: Katrs pieprasījums ar laika zīmogu, URL, atbildes kodu un kopējo laiku. Nospiediet “Detaļas”, lai redzētu vidutēji, vaicājumus un kļūdas. -- **Lēnākie pieprasījumi**: Top 5 pieprasījumi, kas tērē laiku (piemēram, “/api/heavy” ar 2.5s). -- **Lēnākie maršruti**: Top 5 maršruti pēc vidējā laika—lieliski, lai pamanītu modeļus. -- **Kļūdu līmenis**: Procentuāli no neveiksmīgiem pieprasījumiem (piemēram, 2.3% 500s). -- **Latentuma procentiļi**: 95. (p95) un 99. (p99) atbildes laiki—ziniet jūsu sliktākos scenārijus. -- **Atbildes kodu diagramma**: Visualizēj 200s, 404s, 500s laika gaitā. -- **Ilgi vaicājumi/Vidutēji**: Top 5 lēni datubāzes zvani un vidutēji slāņi. -- **Kešs Hit/Miss**: Cik bieži jūsu kešs glābj dienu. +- **Pieprasījumu žurnāls**: Katrs pieprasījums ar laika zīmi, URL, atbildes kodu un kopējo laiku. Noklikšķiniet “Detalizēti”, lai redzētu starprogrammatūru, vaicājumus un kļūdas. +- **Lēnākie pieprasījumi**: Top 5 pieprasījumi, kas aizņem laiku (piem., “/api/heavy” 2.5s). +- **Lēnākie maršruti**: Top 5 maršruti pēc vidējā laika — lieliski, lai pamanītu modeļus. +- **Kļūdu līmenis**: Procentos no pieprasījumiem, kas neizdodas (piem., 2.3% 500s). +- **Latentuma percentīļi**: 95. (p95) un 99. (p99) atbilžu laiki — ziniet savus sliktākos scenārijus. +- **Atbildes koda diagramma**: Vizualizējiet 200s, 404s, 500s laika gaitā. +- **Gari vaicājumi/Starpprogrammatūra**: Top 5 lēni datubāzes zvani un starprogrammatūras slāņi. +- **Kešs trāpījums/Praids**: Cik bieži jūsu kešs glābj dienu. -**Papildu**: -- Filtrēj pēc “Pēdējā stunda,” “Pēdējā diena,” vai “Pēdējā nedēļa.” -- Pārslēdz tumšo režīmu priekš vēlu nakts sesijām. +**Ekstras**: +- Filtrēt pēc “Pēdējā stunda,” “Pēdējā diena,” vai “Pēdējā nedēļa.” +- Pārslēdziet tumšo režīmu tiem vēlošajiem seansiem. **Piemērs**: -Pieprasījums uz `/users` var parādīt: +Pieprasījums uz `/users` var rādīt: - Kopējais laiks: 150ms -- Vidutēji: `AuthMiddleware->handle` (50ms) +- Starpprogrammatūra: `AuthMiddleware->handle` (50ms) - Vaicājums: `SELECT * FROM users` (80ms) -- Kešs: Hit uz `user_list` (5ms) +- Kešs: Trāpījums uz `user_list` (5ms) ## Pievienošana pielāgotu notikumu -Izsekot jebko—piemēram, API zvanu vai maksājuma procesu: +Izsekot jebko — piemēram, API zvanu vai maksājumu procesu: ```php -use flight\apm\CustomEvent; // Importē pielāgotu notikumu klasi +use flight\apm\CustomEvent; $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ 'endpoint' => 'https://api.example.com/users', @@ -217,129 +219,129 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ``` **Kur tas parādās?** -Paneļa pieprasījumu detaļās zem “Pielāgotu notikumu”—paplašināms ar skaistu JSON formatēšanu. +Panelī pieprasījuma detaļās zem “Pielāgoti notikumi” — paplašināms ar skaistu JSON formatējumu. **Lietošanas gadījums**: ```php -$start = microtime(true); // Sāk laika mērīšanu +$start = microtime(true); $apiResponse = file_get_contents('https://api.example.com/data'); $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'url' => 'https://api.example.com/data', - 'time' => microtime(true) - $start, // Izrēķina laiku - 'success' => $apiResponse !== false // Pārbauda, vai veiksmīgs + 'time' => microtime(true) - $start, + 'success' => $apiResponse !== false ])); ``` -Tagad jūs redzēsiet, ja šis API velk jūsu aplikāciju lejā! +Tagad redzēsiet, vai tas API velk jūsu lietojumprogrammu lejup! ## Datubāzes uzraudzība Izsekot PDO vaicājumus šādi: ```php -use flight\database\PdoWrapper; // Importē PDO iesvētītāju +use flight\database\PdoWrapper; $pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True nepieciešams, lai iespējotu izsekošanu APM. $Apm->addPdoConnection($pdo); ``` -**Ko jūs saņemat**: -- Vaicājuma tekstu (piemēram, `SELECT * FROM users WHERE id = ?`) -- Izpildes laiku (piemēram, 0.015s) -- Rindu skaitu (piemēram, 42) +**Ko jūs iegūstat**: +- Vaicājuma tekstu (piem., `SELECT * FROM users WHERE id = ?`) +- Izpildes laiku (piem., 0.015s) +- Rindu skaitu (piem., 42) **Brīdinājums**: -- **Neobligāti**: Izlaidiet to, ja jums nav nepieciešama DB izsekošana. -- **Tikai PdoWrapper**: Kodola PDO vēl nav pieslēgts—gaidiet! -- **Veiktspējas brīdinājums**: Žurnālošana katra vaicājuma DB-smagā vietnē var palēnināt lietas. Izmantojiet paraugu ņemšanu (`$Apm = new Apm($ApmLogger, 0.1)`), lai samazinātu slodzi. +- **Opsionāli**: Izlaidiet to, ja nevajag DB izsekošanu. +- **Tikai PdoWrapper**: Kodols PDO vēl nav savienots — sekojiet līdzi! +- **Veiktspējas brīdinājums**: Žurnālošana katra vaicājuma uz DB smagas vietnes var palēnināt. Izmantojiet paraugu (`$Apm = new Apm($ApmLogger, 0.1)`), lai samazinātu slodzi. -**Piemērs izvade**: +**Piemēra izvade**: - Vaicājums: `SELECT name FROM products WHERE price > 100` - Laiks: 0.023s - Rindas: 15 ## Darbinieka opcijas -Pielāgojiet darbinieku pēc savas gaumes: +Pielāgojiet darbinieku savai gaumei: -- `--timeout 300`: Pārtrauc pēc 5 minūtēm—labi testēšanai. -- `--max_messages 500`: Ierobežo pie 500 metriku—padara to galīgu. -- `--batch_size 200`: Apstrādā 200 vienlaikus—balansē ātrumu un atmiņu. -- `--daemon`: Darbojas nepārtraukti—ideāli dzīvei uzraudzībai. +- `--timeout 300`: Apstājas pēc 5 minūtēm — labi testēšanai. +- `--max_messages 500`: Ierobežo līdz 500 metriku — saglabā to ierobežotu. +- `--batch_size 200`: Apstrādā 200 uzreiz — līdzsvaro ātrumu un atmiņu. +- `--daemon`: Darbojas bez apstājas — ideāli dzīvai uzraudzībai. **Piemērs**: ```bash php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ``` -Darbojas stundu, apstrādājot 100 metrikas vienlaikus. +Darbojas stundu, apstrādājot 100 metrikas uzreiz. -## Pieprasījuma ID aplikācijā +## Pieprasījuma ID lietojumprogrammā -Katram pieprasījumam ir unikāls pieprasījuma ID izsekošanai. Jūs varat izmantot šo ID savā aplikācijā, lai saistītu žurnālus un metrikas. Piemēram, jūs varat pievienot pieprasījuma ID kļūdas lapai: +Katram pieprasījumam ir unikāls pieprasījuma ID izsekošanai. Jūs varat izmantot šo ID savā lietojumprogrammā, lai korelētu žurnālus un metrikas. Piemēram, jūs varat pievienot pieprasījuma ID kļūdu lapai: ```php Flight::map('error', function($message) { - // Iegūstiet pieprasījuma ID no atbildes galvenes X-Flight-Request-Id + // Iegūt pieprasījuma ID no atbildes galvenes X-Flight-Request-Id $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - // Turklāt jūs varētu to iegūt no Flight mainīgā - // Šī metode nedarbosies labi swoole vai citās async platformās. + // Papildus jūs varētu to iegūt no Flight mainīgā + // Šī metode labi nedarbosies swoole vai citās async platformās. // $requestId = Flight::get('apm.request_id'); - echo "Error: $message (Request ID: $requestId)"; // Izdrukā kļūdu ar ID + echo "Kļūda: $message (Pieprasījuma ID: $requestId)"; }); ``` ## Atjaunināšana -Ja jūs atjauninat uz jaunāku APM versiju, var būt, ka ir datubāzes migrācijas, kas jāpalaiž. Jūs varat to izdarīt, izpildot šo komandu: +Ja atjaunināt uz jaunāku APM versiju, ir iespēja, ka ir datubāzes migrācijas, kas jāpalaid. Jūs varat to izdarīt, palaižot šādu komandu: ```bash php vendor/bin/runway apm:migrate ``` -Šī palaist visas nepieciešamās migrācijas, lai atjauninātu datubāzes shēmu uz jaunāko versiju. +Tas palaidīs visas nepieciešamās migrācijas, lai atjauninātu datubāzes shēmu uz jaunāko versiju. -**Piezīme:** Ja jūsu APM datubāze ir liela izmērā, šīs migrācijas var prasīt laiku. Jūs varētu vēlēties palaist šo komandu ārpus maksimālās slodzes laikiem. +**Piezīme:** Ja jūsu APM datubāze ir liela izmērā, šīs migrācijas var prasīt laiku. Jūs varat vēlēties palaidīt šo komandu ārpus maksimālās slodzes stundām. -## Veco datu iztīrīšana +## Veco datu dzēšana -Lai uzturētu datubāzi kārtīgu, jūs varat iztīrīt vecos datus. Tas ir īpaši noderīgi, ja jūs darbojat aizņemtu aplikāciju un vēlaties uzturēt datubāzes izmēru pārvaldāmu. -Jūs varat to izdarīt, izpildot šo komandu: +Lai saglabātu jūsu datubāzi kārtīgu, jūs varat dzēst vecus datus. Tas ir īpaši noderīgi, ja darbojaties aizņemtu lietojumprogrammu un vēlaties uzturēt datubāzes izmēru vadāmu. +Jūs varat to izdarīt, palaižot šādu komandu: ```bash php vendor/bin/runway apm:purge ``` -Šī noņems visus datus vecākus par 30 dienām no datubāzes. Jūs varat pielāgot dienu skaitu, nododot citu vērtību `--days` opcijai: +Tas noņems visus datus vecākus par 30 dienām no datubāzes. Jūs varat pielāgot dienu skaitu, nododot citu vērtību `--days` opcijai: ```bash php vendor/bin/runway apm:purge --days 7 ``` -Šī noņems visus datus vecākus par 7 dienām no datubāzes. +Tas noņems visus datus vecākus par 7 dienām no datubāzes. -## Problēmu novēršana +## Problēmu risināšana Iestrēdzis? Mēģiniet šos: -- **Nav datu panelī?** +- **Nav paneļa datu?** - Vai darbinieks darbojas? Pārbaudiet `ps aux | grep apm:worker`. - - Konfigurācijas ceļi atbilst? Pārbaudiet `.runway-config.json` DSN, kas norāda uz reāliem failiem. - - Izpildiet `php vendor/bin/runway apm:worker` manuāli, lai apstrādātu gaidāmās metrikas. + - Konfigurācijas ceļi sakrīt? Pārbaudiet `.runway-config.json` DSN norāda uz reāliem failiem. + - Palaidiet `php vendor/bin/runway apm:worker` manuāli, lai apstrādātu gaidošās metrikas. - **Darbinieka kļūdas?** - - Apskatiet jūsu SQLite failus (piemēram, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Pārbaudiet PHP žurnālus uz steka izsekojumiem. + - Apskatiet jūsu SQLite failus (piem., `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). + - Pārbaudiet PHP žurnālus uz steka pēdzīmēm. -- **Panelis nekurasies?** - - Ports 8001 ir aizņemts? Izmantojiet `--port 8080`. +- **Panels nesākas?** + - Ports 8001 aizņemts? Izmantojiet `--port 8080`. - PHP nav atrasts? Izmantojiet `--php-path /usr/bin/php`. - Ugunsmūris bloķē? Atveriet portu vai izmantojiet `--host localhost`. - **Pārāk lēns?** - - Samaziniet paraugu līmeni: `$Apm = new Apm($ApmLogger, 0.05)` (5%). + - Samaziniet parauga līmeni: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - Samaziniet partijas lielumu: `--batch_size 20`. -- **Netiek izsekotas izņēmumi/kļūdas?** - - Ja jums ir [Tracy](https://tracy.nette.org/) iespējots jūsu projektā, tas pārrakstīs Flight kļūdu apstrādi. Jums būs jādeaktivizē Tracy un jāpārliecinās, ka `Flight::set('flight.handle_errors', true);` ir iestatīts. +- **Netiek izsekotas izņēmumi/Kļūdas?** + - Ja jums ir [Tracy](https://tracy.nette.org/) iespējots projektam, tas pārņems Flight kļūdu apstrādi. Jums jāatspējo Tracy un tad jāpārliecinās, ka `Flight::set('flight.handle_errors', true);` ir iestatīts. - **Netiek izsekoti datubāzes vaicājumi?** - - Pārliecinieties, ka jūs izmantojat `PdoWrapper` priekš datubāzes savienojumiem. - - Pārliecinieties, ka pēdējais arguments konstruktorā ir `true`. \ No newline at end of file + - Pārliecinieties, ka izmantojat `PdoWrapper` savām datubāzes savienojumiem. + - Pārliecinieties, ka konstruktorā pēdējais arguments ir `true`. \ No newline at end of file diff --git a/content/v3/lv/learn/ai.md b/content/v3/lv/learn/ai.md index 27fb9522..c48063b5 100644 --- a/content/v3/lv/learn/ai.md +++ b/content/v3/lv/learn/ai.md @@ -1,21 +1,21 @@ -# AI & Izstrādātāju pieredze ar Flight +# AI un izstrādātāju pieredze ar Flight ## Pārskats -Flight padara viegli uzlabot jūsu PHP projektus ar AI vadītiem rīkiem un mūsdienīgām izstrādātāju darba plūsmām. Ar iebūvētiem komandām savienojumam ar LLM (Large Language Model) sniedzējiem un ģenerēšanai projektu specifiskām AI kodēšanas instrukcijām, Flight palīdz jums un jūsu komandai gūt maksimālu labumu no AI asistentiem, piemēram, GitHub Copilot, Cursor un Windsurf. +Flight padara viegli uzlabot jūsu PHP projektus ar AI vadītiem rīkiem un mūsdienīgiem izstrādātāju darba plūsmu. Ar iebūvētiem komandām savienojumiem ar LLM (Large Language Model) sniedzējiem un ģenerēšanu projektu specifiskām AI kodēšanas instrukcijām, Flight palīdz jums un jūsu komandai iegūt maksimālo labumu no AI asistentiem, piemēram, GitHub Copilot, Cursor un Windsurf. -## Saprašana +## Izpratne -AI kodēšanas asistenti ir visnoderīgākie, kad tie saprot jūsu projekta kontekstu, konvencijas un mērķus. Flight AI palīgi ļauj jums: +AI kodēšanas asistenti ir visnoderīgākie, kad viņi saprot jūsu projekta kontekstu, konvencijas un mērķus. Flight AI palīgi ļauj jums: - Savienot savu projektu ar populāriem LLM sniedzējiem (OpenAI, Grok, Claude utt.) -- Ģenerēt un atjaunināt projektu specifiskas instrukcijas AI rīkiem, lai visi saņemtu konsekventu, relevantu palīdzību -- Turēt savu komandu saskaņotu un produktīvu, ar mazāk laika iztērēts konteksta skaidrošanai +- Ģenerēt un atjaunināt projektu specifiskas instrukcijas AI rīkiem, lai visi saņemtu konsekventu, atbilstošu palīdzību +- Turēt jūsu komandu saskaņotu un produktīvu, ar mazāku laiku, kas pavadīts konteksta skaidrošanā -Šīs funkcijas ir iebūvētas Flight kodola CLI un oficiālajā [flightphp/skeleton](https://github.com/flightphp/skeleton) sākuma projektā. +Šīs funkcijas ir iebūvētas Flight kodolā CLI un oficiālajā [flightphp/skeleton](https://github.com/flightphp/skeleton) starter projektā. ## Pamata lietošana -### 1. LLM akreditīvu iestatīšana +### LLM akreditīvu iestatīšana `ai:init` komanda ved jūs cauri jūsu projekta savienojumam ar LLM sniedzēju. @@ -40,7 +40,7 @@ Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: Credentials saved to .runway-creds.json ``` -### 2. Projekta specifisko AI instrukciju ģenerēšana +### Ģenerēšana projektu specifiskām AI instrukcijām `ai:generate-instructions` komanda palīdz jums izveidot vai atjaunināt instrukcijas AI kodēšanas asistentiem, pielāgotas jūsu projektam. @@ -48,10 +48,10 @@ Credentials saved to .runway-creds.json php runway ai:generate-instructions ``` -Jūs atbildēsiet uz dažiem jautājumiem par savu projektu (apraksts, datubāze, veidnes, drošība, komandas lielums utt.). Flight izmanto jūsu LLM sniedzēju, lai ģenerētu instrukcijas, tad ieraksta tās: -- `.github/copilot-instructions.md` (GitHub Copilot) -- `.cursor/rules/project-overview.mdc` (Cursor) -- `.windsurfrules` (Windsurf) +Jūs atbildēsiet uz dažiem jautājumiem par jūsu projektu (apraksts, datubāze, veidnes, drošība, komandas lielums utt.). Flight izmanto jūsu LLM sniedzēju, lai ģenerētu instrukcijas, tad ieraksta tās: +- `.github/copilot-instructions.md` (for GitHub Copilot) +- `.cursor/rules/project-overview.mdc` (for Cursor) +- `.windsurfrules` (for Windsurf) **Piemērs:** ``` @@ -63,22 +63,22 @@ Is security an important element of this project? (y/n) y AI instructions updated successfully. ``` -Tagad jūsu AI rīki sniegs gudrākus, relevantākus ieteikumus, balstoties uz jūsu projekta reālajām vajadzībām. +Tagad jūsu AI rīki sniegs gudrākus, atbilstošākus ieteikumus, balstītus uz jūsu projekta reālajām vajadzībām. -## Uzlabota lietošana +## Padziļinātā lietošana -- Jūs varat pielāgot jūsu akreditīvu vai instrukciju failu atrašanās vietu, izmantojot komandas opcijas (skat. `--help` katrai komandai). +- Jūs varat pielāgot jūsu akreditīvu vai instrukciju failu atrašanās vietu, izmantojot komandas opcijas (skatiet `--help` katrai komandai). - AI palīgi ir paredzēti darbam ar jebkuru LLM sniedzēju, kas atbalsta OpenAI saderīgās API. -- Ja vēlaties atjaunināt savas instrukcijas, kad jūsu projekts attīstās, vienkārši palaidiet atkārtoti `ai:generate-instructions` un atbildiet uz uzvednēm vēlreiz. +- Ja vēlaties atjaunināt jūsu instrukcijas, kad jūsu projekts attīstās, tikai palaidiet atkārtoti `ai:generate-instructions` un atbildiet uz uzvednēm vēlreiz. ## Skatīt arī -- [Flight Skeleton](https://github.com/flightphp/skeleton) – Oficiālais sākuma projekts ar AI integrāciju +- [Flight Skeleton](https://github.com/flightphp/skeleton) – Oficiālais starter ar AI integrāciju - [Runway CLI](/awesome-plugins/runway) – Vairāk par CLI rīku, kas nodrošina šīs komandas ## Traucējummeklēšana -- Ja redzat "Missing .runway-creds.json", vispirms palaidiet `php runway ai:init`. +- Ja jūs redzat "Missing .runway-creds.json", palaidiet `php runway ai:init` vispirms. - Pārliecinieties, ka jūsu API atslēga ir derīga un tai ir piekļuve izvēlētajam modelim. - Ja instrukcijas neatjaunojas, pārbaudiet failu atļaujas jūsu projektu direktorijā. diff --git a/content/v3/lv/learn/requests.md b/content/v3/lv/learn/requests.md index 43089935..a0aaf871 100644 --- a/content/v3/lv/learn/requests.md +++ b/content/v3/lv/learn/requests.md @@ -2,7 +2,7 @@ ## Pārskats -Flight ietver HTTP pieprasījumu vienā objektā, ko var piekļūt, veicot: +Flight ietver HTTP pieprasījumu vienā objektā, ko var piekļūt, darot: ```php $request = Flight::request(); @@ -10,13 +10,13 @@ $request = Flight::request(); ## Saprašana -HTTP pieprasījumi ir viens no galvenajiem aspektiem, kas jāizprot par HTTP dzīves ciklu. Lietotājs veic darbību tīmekļa pārlūkprogrammā vai HTTP klientā, un viņi nosūta virkni galvenes, ķermeņa, URL utt. uz jūsu projektu. Jūs varat uztvert šīs galvenes (pārlūkprogrammas valodu, kādu kompresijas veidu viņi var apstrādāt, lietotāja aģentu utt.) un uztvert ķermeni un URL, kas nosūtīts uz jūsu Flight lietojumprogrammu. Šie pieprasījumi ir būtiski jūsu lietojumprogrammai, lai saprastu, ko darīt tālāk. +HTTP pieprasījumi ir viens no galvenajiem HTTP cikla aspektiem, ko saprast. Lietotājs veic darbību tīmekļa pārlūkprogrammā vai HTTP klientā, un viņi nosūta virkni galvenes, ķermeņa, URL utt. uz jūsu projektu. Jūs varat uztvert šīs galvenes (pārlūkprogrammas valoda, kādu veida kompresiju viņi var apstrādāt, lietotāja aģents utt.) un uztvert ķermeni un URL, kas nosūtīts uz jūsu Flight lietojumprogrammu. Šie pieprasījumi ir būtiski jūsu lietojumprogrammai, lai saprastu, ko darīt tālāk. -## Pamata izmantošana +## Pamata Izmantošana -PHP ir vairākas superglobālās mainīgās, tostarp `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` un `$_COOKIE`. Flight abstraktē šīs prom uz ērtām [Kolekcijām](/learn/collections). Jūs varat piekļūt `query`, `data`, `cookies` un `files` īpašībām kā masīviem vai objektiem. +PHP ir vairākas superglobālas, tostarp `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` un `$_COOKIE`. Flight abstraktē šīs prom praktiskos [Collections](/learn/collections). Jūs varat piekļūt `query`, `data`, `cookies` un `files` īpašībām kā masīviem vai objektiem. -> **Piezīme:** Ir **ĻOTI** atvairīts izmantot šīs superglobālās mainīgās savā projektā, un tām jāatsaucas caur `request()` objektu. +> **Piezīme:** Ir ** ĻOTI** atdissludināts izmantot šīs superglobālas savā projektā, un tās jāatsaucas caur `request()` objektu. > **Piezīme:** Nav pieejama abstrakcija `$_ENV`. @@ -60,7 +60,7 @@ Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; // or $savedLogin = Flight::request()->cookies->myLoginCookie; - // pārbaudīt, vai tas tiešām ir saglabāts vai nē, un ja tas ir, automātiski ielogoties + // pārbaudīt, vai tas tiešām ir saglabāts vai nē, un ja ir, automātiski pieteikties if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -68,7 +68,7 @@ Flight::route('GET /login', function(){ }); ``` -Lai iegūtu palīdzību ar jaunu sīkfailu vērtību iestatīšanu, skatiet [overclokk/cookie](/awesome-plugins/php-cookie) +Palīdzībai iestatīt jaunas cepumu vērtības skatiet [overclokk/cookie](/awesome-plugins/php-cookie) ### `$_SERVER` @@ -92,26 +92,26 @@ $uploadedFile = Flight::request()->files->myFile; Skatiet [Uploaded File Handler](/learn/uploaded-file) vairāk informācijas. -#### Failu augšupielādes apstrāde +#### Apstrāde Failu Augšupielādes _v3.12.0_ -Jūs varat apstrādāt failu augšupielādi, izmantojot ietvaru ar dažām palīgmēģīnēm. Tas būtībā samazinās līdz faila datu izvilkšanai no pieprasījuma un tā pārvietošanai uz jaunu atrašanās vietu. +Jūs varat apstrādāt failu augšupielādi, izmantojot ietvaru ar dažām palīglokalizācijām. Tas būtībā samazinās līdz failu datu izvilkšanai no pieprasījuma un pārvietošanai uz jaunu atrašanās vietu. ```php Flight::route('POST /upload', function(){ - // If you had an input field like + // Ja jums ir ievades lauks kā $uploadedFileData = Flight::request()->getUploadedFiles(); $uploadedFile = $uploadedFileData['myFile']; $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); }); ``` -Ja jums ir vairāki augšupielādēti faili, jūs varat tos iterēt: +Ja jums ir vairāki augšupielādēti faili, jūs varat iterēt caur tiem: ```php Flight::route('POST /upload', function(){ - // If you had an input field like + // Ja jums ir ievades lauks kā $uploadedFiles = Flight::request()->getUploadedFiles()['myFiles']; foreach ($uploadedFiles as $uploadedFile) { $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); @@ -119,21 +119,21 @@ Flight::route('POST /upload', function(){ }); ``` -> **Drošības piezīme:** Vienmēr validējiet un sanitizējiet lietotāja ievadi, īpaši, kad darbojaties ar failu augšupielādi. Vienmēr validējiet paplašinājumu tipus, kurus atļausit augšupielādēt, bet jums arī vajadzētu validēt faila "burvju baitus", lai nodrošinātu, ka tas tiešām ir tāds faila tips, kādu lietotājs apgalvo. Ir pieejami [raksti](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [un](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [bibliotēkas](https://github.com/RikudouSage/MimeTypeDetector), lai palīdzētu ar to. +> **Drošības Piezīme:** Vienmēr validējiet un sanitējiet lietotāja ievadi, īpaši, kad darbojaties ar failu augšupielādi. Vienmēr validējiet paplašinājumu tipus, kurus atļausiet augšupielādēt, bet jums arī jāvalidē faila "magic bytes", lai nodrošinātu, ka tas tiešām ir tāda tipa fails, kādu lietotājs apgalvo. Ir pieejami [raksti](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [un](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [bibliotēkas](https://github.com/RikudouSage/MimeTypeDetector), lai palīdzētu ar to. -### Pieprasījuma ķermenis +### Pieprasījuma Ķermenis Lai iegūtu neapstrādātu HTTP pieprasījuma ķermeni, piemēram, kad darbojaties ar POST/PUT pieprasījumiem, -jūs varat to darīt: +jūs varat darīt: ```php Flight::route('POST /users/xml', function(){ $xmlBody = Flight::request()->getBody(); - // do something with the XML that was sent. + // darīt kaut ko ar XML, kas tika nosūtīts. }); ``` -### JSON ķermenis +### JSON Ķermenis Ja jūs saņemat pieprasījumu ar satura tipu `application/json` un piemēra datiem `{"id": 123}` tas būs pieejams no `data` īpašības: @@ -142,24 +142,24 @@ tas būs pieejams no `data` īpašības: $id = Flight::request()->data->id; ``` -### Pieprasījuma galvenes +### Pieprasījuma Galvenes Jūs varat piekļūt pieprasījuma galvenēm, izmantojot `getHeader()` vai `getHeaders()` metodi: ```php -// Maybe you need Authorization header +// Varbūt jums vajag Autorizācijas galveni $host = Flight::request()->getHeader('Authorization'); // or $host = Flight::request()->header('Authorization'); -// If you need to grab all headers +// Ja jums vajag paņemt visas galvenes $headers = Flight::request()->getHeaders(); // or $headers = Flight::request()->headers(); ``` -### Pieprasījuma metode +### Pieprasījuma Metode Jūs varat piekļūt pieprasījuma metodei, izmantojot `method` īpašību vai `getMethod()` metodi: @@ -169,9 +169,9 @@ $method = Flight::request()->getMethod(); ``` **Piezīme:** `getMethod()` metode vispirms izvelk metodi no `$_SERVER['REQUEST_METHOD']`, tad to var pārrakstīt -`$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']`, ja tas pastāv, vai `$_REQUEST['_method']`, ja tas pastāv. +`$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']`, ja tā pastāv, vai `$_REQUEST['_method']`, ja tā pastāv. -## Pieprasījuma objekta īpašības +## Pieprasījuma Objekta Īpašības Pieprasījuma objekts nodrošina šādas īpašības: @@ -188,17 +188,17 @@ Pieprasījuma objekts nodrošina šādas īpašības: - **length** - Satura garums - **query** - Vaicājuma virknes parametri - **data** - POST dati vai JSON dati -- **cookies** - Sīkfailu dati -- **files** - Augšupielādētie faili +- **cookies** - Cepumu dati +- **files** - Augšupielādēti faili - **secure** - Vai savienojums ir drošs - **accept** - HTTP pieņemšanas parametri -- **proxy_ip** - Klienta proxy IP adrese. Skenē `$_SERVER` masīvu pēc `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` tajā secībā. -- **host** - Pieprasījuma resursa nosaukums +- **proxy_ip** - Proxy IP adrese klienta. Skenē `$_SERVER` masīvu pēc `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` tajā secībā. +- **host** - Pieprasījuma resursdatora nosaukums - **servername** - SERVER_NAME no `$_SERVER` -## URL palīgmēģinātājas +## Palīglokas -Ir dažas palīgmēģinātājas, lai saliktu URL daļas jūsu ērtībai. +Ir dažas palīglokas, lai saliktu URL daļas vai darbotos ar noteiktām galvenēm. ### Pilns URL @@ -208,7 +208,6 @@ Jūs varat piekļūt pilnam pieprasījuma URL, izmantojot `getFullUrl()` metodi: $url = Flight::request()->getFullUrl(); // https://example.com/some/path?foo=bar ``` - ### Bāzes URL Jūs varat piekļūt bāzes URL, izmantojot `getBaseUrl()` metodi: @@ -217,10 +216,10 @@ Jūs varat piekļūt bāzes URL, izmantojot `getBaseUrl()` metodi: // http://example.com/path/to/something/cool?query=yes+thanks $url = Flight::request()->getBaseUrl(); // https://example.com -// Notice, no trailing slash. +// Pievērsiet uzmanību, nav beigu slīpsvītras. ``` -## Vaicājuma parsēšana +## Vaicājuma Parsēšana Jūs varat nodot URL uz `parseQuery()` metodi, lai parsētu vaicājuma virkni asociatīvā masīvā: @@ -229,16 +228,40 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` -## Skatīt arī +## Sarunu Satura Pieņemšanas Tipi + +_v3.17.2_ + +Jūs varat izmantot `negotiateContentType()` metodi, lai noteiktu labāko satura tipu, ar kuru atbildēt, balstoties uz `Accept` galveni, ko nosūtīja klients. + +```php + +// Piemēra Accept galvene: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// Zemāk definē, ko jūs atbalstāt. +$availableTypes = ['application/json', 'application/xml']; +$typeToServe = Flight::request()->negotiateContentType($availableTypes); +if ($typeToServe === 'application/json') { + // Pasniegt JSON atbildi +} elseif ($typeToServe === 'application/xml') { + // Pasniegt XML atbildi +} else { + // Noklusējuma kaut ko citu vai mest kļūdu +} +``` + +> **Piezīme:** Ja neviens no pieejamajiem tipiem nav atrasts `Accept` galvenē, metode atgriezīs `null`. Ja nav definēta `Accept` galvene, metode atgriezīs pirmo tipu `$availableTypes` masīvā. + +## Skatīt Arī - [Routing](/learn/routing) - Skatiet, kā kartēt maršrutus uz kontrolieriem un renderēt skatus. - [Responses](/learn/responses) - Kā pielāgot HTTP atbildes. -- [Why a Framework?](/learn/why-frameworks) - Kā pieprasījumi iederas lielajā attēlā. +- [Why a Framework?](/learn/why-frameworks) - Kā pieprasījumi iekļaujas lielajā attēlā. - [Collections](/learn/collections) - Darbs ar datu kolekcijām. - [Uploaded File Handler](/learn/uploaded-file) - Failu augšupielādes apstrāde. ## Traucējummeklēšana - `request()->ip` un `request()->proxy_ip` var atšķirties, ja jūsu tīmekļa serveris ir aiz proxy, slodzes līdzsvara utt. -## Izmaiņu žurnāls -- v3.12.0 - Pievienota iespēja apstrādāt failu augšupielādi caur pieprasījuma objektu. +## Izmaiņu Žurnāls +- v3.17.2 - Pievienota negotiateContentType() +- v3.12.0 - Pievienota spēja apstrādāt failu augšupielādi caur pieprasījuma objektu. - v1.0 - Sākotnējā izlaišana. \ No newline at end of file diff --git a/content/v3/lv/learn/responses.md b/content/v3/lv/learn/responses.md index bcd30fb7..40060459 100644 --- a/content/v3/lv/learn/responses.md +++ b/content/v3/lv/learn/responses.md @@ -2,37 +2,37 @@ ## Pārskats -Flight palīdz ģenerēt daļu no atbildes galvenes jums, bet jūs kontrolējat lielāko daļu no tā, ko nosūtāt atpakaļ lietotājam. Lielāko daļu laika jūs tieši piekļūsiet `response()` objektam, bet Flight piedāvā dažas palīgmēģenes, lai iestatītu dažas no atbildes galvenēm jums. +Flight palīdz ģenerēt daļu no atbildes galvenes jums, bet jūs kontrolējat lielāko daļu no tā, ko nosūtāt atpakaļ lietotājam. Lielāko daļu laika jūs tieši piekļūsiet `response()` objektam, bet Flight piedāvā dažas palīgmēģinājumu metodes, lai iestatītu dažas atbildes galvenes jums. ## Izpratne -Pēc tam, kad lietotājs nosūta savu [pieprasījumu](/learn/requests) jūsu lietojumprogrammai, jums jāģenerē pareiza atbilde viņiem. Viņi ir nosūtījuši jums informāciju, piemēram, valodu, kuru viņi dod priekšroku, vai viņi var apstrādāt noteiktus kompresijas veidus, viņu lietotāja aģentu utt., un pēc visu apstrādes ir laiks nosūtīt viņiem atpakaļ pareizu atbildi. Tas var būt galvenes iestatīšana, HTML vai JSON ķermeņa izvade viņiem vai novirzīšana uz lapu. +Pēc tam, kad lietotājs nosūta savu [pieprasījumu](/learn/requests) uz jūsu lietojumprogrammu, jums jāģenerē pareiza atbilde viņiem. Viņi ir nosūtījuši jums informāciju, piemēram, valodu, kuru viņi dod priekšroku, vai viņi var apstrādāt noteiktus kompresijas veidus, viņu lietotāja aģentu utt., un pēc visu apstrādes ir pienācis laiks nosūtīt viņiem atpakaļ pareizu atbildi. Tas var būt galvenes iestatīšana, HTML vai JSON ķermeņa izvade viņiem vai novirzīšana uz lapu. ## Pamata lietošana ### Atbildes ķermeņa nosūtīšana -Flight izmanto `ob_start()` buferēšanai izvadi. Tas nozīmē, ka jūs varat izmantot `echo` vai `print`, lai nosūtītu atbildi lietotājam, un Flight to uztvers un nosūtīs atpakaļ lietotājam ar atbilstošajām galvenēm. +Flight izmanto `ob_start()`, lai buferētu izvadi. Tas nozīmē, ka jūs varat izmantot `echo` vai `print`, lai nosūtītu atbildi lietotājam, un Flight to uztvers un nosūtīs atpakaļ lietotājam ar atbilstošajām galvenēm. ```php -// Tas nosūtīs "Sveiki, Pasaule!" uz lietotāja pārlūku +// Tas nosūtīs "Hello, World!" uz lietotāja pārlūkprogrammu Flight::route('/', function() { - echo "Sveiki, Pasaule!"; + echo "Hello, World!"; }); // HTTP/1.1 200 OK // Content-Type: text/html // -// Sveiki, Pasaule! +// Hello, World! ``` Kā alternatīvu, jūs varat izsaukt `write()` metodi, lai pievienotu ķermenim. ```php -// Tas nosūtīs "Sveiki, Pasaule!" uz lietotāja pārlūku +// Tas nosūtīs "Hello, World!" uz lietotāja pārlūkprogrammu Flight::route('/', function() { - // verbose, bet dažreiz dara darbu, kad tas ir vajadzīgs - Flight::response()->write("Sveiki, Pasaule!"); + // verbose, bet dažreiz tas ir nepieciešams + Flight::response()->write("Hello, World!"); // ja vēlaties iegūt ķermeni, kuru esat iestatījis šajā brīdī // jūs varat to izdarīt šādi @@ -51,7 +51,7 @@ Flight::route('/@companyId/users', function(int $companyId) { Flight::json($users); }); -// [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* vairāk lietotāju */ ] +// [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* more users */ ] ``` > **Piezīme:** Pēc noklusējuma Flight nosūtīs `Content-Type: application/json` galveni ar atbildi. Tas arī izmantos karodziņus `JSON_THROW_ON_ERROR` un `JSON_UNESCAPED_SLASHES`, kodējot JSON. @@ -66,20 +66,20 @@ Flight::json(['id' => 123], 201); #### JSON ar skaistu izdruku -Jūs varat arī nodot argumentu pēdējā pozīcijā, lai iespējotu skaistu izdruku: +Jūs varat arī nodot argumentu pēdējā pozīcijā, lai iespējotu skaistu drukāšanu: ```php Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT); ``` -#### Mainot JSON argumentu secību +#### JSON argumentu secības maiņa -`Flight::json()` ir ļoti novecojis metode, bet Flight mērķis ir saglabāt atpakaļsaderību projektiem. Patiesībā tas ir ļoti vienkārši, ja vēlaties atkārtoti izveidot argumentu secību, lai izmantotu vienkāršāku sintaksi, jūs varat vienkārši pārkartēt JSON metodi [kā jebkuru citu Flight metodi](/learn/extending): +`Flight::json()` ir ļoti vecs metode, bet Flight mērķis ir saglabāt atpakaļsaderību projektiem. Tas ir ļoti vienkārši, ja vēlaties pārkārtot argumentu secību, lai izmantotu vienkāršāku sintaksi, jūs varat tikai pārkartēt JSON metodi [kā jebkuru citu Flight metodi](/learn/extending): ```php Flight::map('json', function($data, $code = 200, $options = 0) { - // tagad jums nav jāizmanto `true, 'utf-8'` , izmantojot json() metodi! + // tagad jums nav jāizmanto `true, 'utf-8'`, kad izmantojat json() metodi! Flight::_json($data, $code, true, 'utf-8', $options); } @@ -92,7 +92,7 @@ Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT); _v3.10.0_ Ja vēlaties nosūtīt JSON atbildi un apturēt izpildi, jūs varat izmantot `jsonHalt()` metodi. -Tas ir noderīgi gadījumos, kad jūs pārbaudāt varbūt kādu autorizācijas veidu un, ja lietotājs nav autorizēts, jūs varat nekavējoties nosūtīt JSON atbildi, notīrīt esošo ķermeņa saturu un apturēt izpildi. +Tas ir noderīgi gadījumos, kad jūs pārbaudāt, iespējams, kādu autorizācijas veidu, un ja lietotājs nav autorizēts, jūs varat nekavējoties nosūtīt JSON atbildi, notīrīt esošo ķermeņa saturu un apturēt izpildi. ```php Flight::route('/users', function() { @@ -100,14 +100,14 @@ Flight::route('/users', function() { // Pārbaudiet, vai lietotājs ir autorizēts if($authorized === false) { Flight::jsonHalt(['error' => 'Unauthorized'], 401); - // nav izejas; vajadzīgs šeit. + // nav izvades; nepieciešams šeit. } - // Turpiniet ar pārējo maršruta daļu + // Turpiniet ar pārējo maršrutu }); ``` -Pirms v3.10.0 jums būtu jādarītu kaut kas šāds: +Pirms v3.10.0, jums būtu jādara kaut kas šāds: ```php Flight::route('/users', function() { @@ -117,18 +117,18 @@ Flight::route('/users', function() { Flight::halt(401, json_encode(['error' => 'Unauthorized'])); } - // Turpiniet ar pārējo maršruta daļu + // Turpiniet ar pārējo maršrutu }); ``` -### Ķermeņa atbildes notīrīšana +### Atbildes ķermeņa notīrīšana Ja vēlaties notīrīt atbildes ķermeni, jūs varat izmantot `clearBody` metodi: ```php Flight::route('/', function() { if($someCondition) { - Flight::response()->write("Sveiki, Pasaule!"); + Flight::response()->write("Hello, World!"); } else { Flight::response()->clearBody(); } @@ -137,9 +137,9 @@ Flight::route('/', function() { Iepriekš minētais lietošanas gadījums, iespējams, nav izplatīts, tomēr tas varētu būt izplatītāks, ja tas tiktu izmantots [starpprogrammatūrā](/learn/middleware). -### Izpildes atbilde uz atbildes ķermeni +### Izpildes palaišana uz atbildes ķermeņa -Jūs varat izpildīt atbildi uz atbildes ķermeni, izmantojot `addResponseBodyCallback` metodi: +Jūs varat palaist izpildes funkciju uz atbildes ķermeņa, izmantojot `addResponseBodyCallback` metodi: ```php Flight::route('/users', function() { @@ -148,19 +148,19 @@ Flight::route('/users', function() { Flight::render('users_table', ['users' => $users]); }); -// Tas sasniegs visas atbildes ar gzip jebkuram maršrutam +// Tas sasniegs visas atbildes visiem maršrutiem Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); ``` -Jūs varat pievienot vairākas atbildes, un tās tiks izpildītas secībā, kādā tās tika pievienotas. Tā kā tas var pieņemt jebkuru [izsaucamu](https://www.php.net/manual/en/language.types.callable.php), tas var pieņemt klases masīvu `[ $class, 'method' ]`, aizvēršanu `$strReplace = function($body) { str_replace('hi', 'there', $body); };` vai funkcijas nosaukumu `'minify'`, ja jums ir funkcija, lai samazinātu jūsu html kodu, piemēram. +Jūs varat pievienot vairākas izpildes funkcijas, un tās tiks palaistas secībā, kādā tās tika pievienotas. Tā kā tas var pieņemt jebkuru [izsaucamu](https://www.php.net/manual/en/language.types.callable.php), tas var pieņemt klases masīvu `[ $class, 'method' ]`, aizvēršanu `$strReplace = function($body) { str_replace('hi', 'there', $body); };`, vai funkcijas nosaukumu `'minify'`, ja jums ir funkcija, lai samazinātu jūsu html kodu, piemēram. -**Piezīme:** Maršruta atbildes nedarbosies, ja izmantojat `flight.v2.output_buffering` konfigurācijas opciju. +**Piezīme:** Maršruta izpildes funkcijas nedarbosies, ja izmantojat `flight.v2.output_buffering` konfigurācijas opciju. -#### Īpašs maršruta atbilde +#### Īpašs maršruta izpildes funkcija -Ja vēlaties, lai tas attiektos tikai uz noteiktu maršrutu, jūs varat pievienot atbildi pašā maršrutā: +Ja vēlaties, lai tas attiektos tikai uz specifisku maršrutu, jūs varat pievienot izpildes funkciju pašā maršrutā: ```php Flight::route('/users', function() { @@ -168,7 +168,7 @@ Flight::route('/users', function() { $users = $db->fetchAll("SELECT * FROM users"); Flight::render('users_table', ['users' => $users]); - // Tas sasniegs ar gzip tikai šo maršrutu atbildi + // Tas sasniegs tikai šo maršrutu atbildi Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); @@ -177,13 +177,13 @@ Flight::route('/users', function() { #### Starpprogrammatūras opcija -Jūs varat arī izmantot [starpprogrammatūru](/learn/middleware), lai piemērotu atbildi visiem maršrutiem, izmantojot starpprogrammatūru: +Jūs varat arī izmantot [starpprogrammatūru](/learn/middleware), lai piemērotu izpildes funkciju visiem maršrutiem caur starpprogrammatūru: ```php // MinifyMiddleware.php class MinifyMiddleware { public function before() { - // Šeit piemērojiet atbildi uz response() objektu. + // Šeit piemērojiet izpildes funkciju uz response() objektu. Flight::response()->addResponseBodyCallback(function($body) { return $this->minify($body); }); @@ -210,10 +210,10 @@ Jūs varat iestatīt atbildes statusa kodu, izmantojot `status` metodi: Flight::route('/@id', function($id) { if($id == 123) { Flight::response()->status(200); - echo "Sveiki, Pasaule!"; + echo "Hello, World!"; } else { Flight::response()->status(403); - echo "Aizliegts"; + echo "Forbidden"; } }); ``` @@ -229,12 +229,12 @@ Flight::response()->status(); // 200 Jūs varat iestatīt galveni, piemēram, atbildes satura veidu, izmantojot `header` metodi: ```php -// Tas nosūtīs "Sveiki, Pasaule!" uz lietotāja pārlūku kā vienkāršu tekstu +// Tas nosūtīs "Hello, World!" uz lietotāja pārlūkprogrammu kā vienkāršu tekstu Flight::route('/', function() { Flight::response()->header('Content-Type', 'text/plain'); // vai Flight::response()->setHeader('Content-Type', 'text/plain'); - echo "Sveiki, Pasaule!"; + echo "Hello, World!"; }); ``` @@ -250,7 +250,7 @@ Flight::route('/login', function() { if($password !== $passwordConfirm) { Flight::redirect('/new/location'); - return; // tas ir nepieciešams, lai funkcija zemāk neizpildītos + return; // tas ir nepieciešams, lai zemāk esošā funkcionalitāte neizpildītos } // pievienojiet jauno lietotāju... @@ -276,17 +276,17 @@ Flight::halt(); Jūs varat arī norādīt izvēles `HTTP` statusa kodu un ziņojumu: ```php -Flight::halt(200, 'Drīz atgriezīšos...'); +Flight::halt(200, 'Be right back...'); ``` -Izsaucot `halt`, tas atmetos jebkuru atbildes saturu līdz tam punktam un aptur visus izpildi. +Izsaucot `halt`, tas atmestīs jebkuru atbildes saturu līdz tam punktam un apturēs visu izpildi. Ja vēlaties apturēt ietvaru un izvadīt pašreizējo atbildi, izmantojiet `stop` metodi: ```php Flight::stop($httpStatusCode = null); ``` -> **Piezīme:** `Flight::stop()` ir dažas dīvainas uzvedības, piemēram, tas izvadīs atbildi, bet turpinās izpildīt jūsu skriptu, kas var nebūt tas, ko jūs vēlaties. Jūs varat izmantot `exit` vai `return` pēc `Flight::stop()` izsaukšanas, lai novērstu turpmāku izpildi, bet parasti iesaka izmantot `Flight::halt()`. +> **Piezīme:** `Flight::stop()` ir dažas dīvainas uzvedības, piemēram, tas izvadīs atbildi, bet turpinās izpildīt jūsu skriptu, kas var nebūt tas, ko vēlaties. Jūs varat izmantot `exit` vai `return` pēc `Flight::stop()` izsaukšanas, lai novērstu turpmāku izpildi, bet parasti iesaka izmantot `Flight::halt()`. Tas saglabās galvenes atslēgu un vērtību atbildes objektā. Pieprasījuma dzīves cikla beigās tas izveidos galvenes un nosūtīs atbildi. @@ -294,20 +294,20 @@ Tas saglabās galvenes atslēgu un vērtību atbildes objektā. Pieprasījuma dz ### Galvenes nosūtīšana nekavējoties -Var būt gadījumi, kad jums jāizdara kaut kas pielāgots ar galveni, un jums jānosūta galvene tajā pašā koda rindā, ar kuru jūs strādājat. Ja jūs iestatāt [straumētu maršrutu](/learn/routing), tas ir tas, kas jums būtu vajadzīgs. To var sasniegt, izmantojot `response()->setRealHeader()`. +Var būt gadījumi, kad jums jāizdara kaut kas pielāgots ar galveni, un jums jānosūta galvene tajā pašā koda rindā, ar kuru strādājat. Ja jūs iestatāt [straumētu maršrutu](/learn/routing), tas ir tas, kas jums būtu nepieciešams. To var sasniegt caur `response()->setRealHeader()`. ```php Flight::route('/', function() { Flight::response()->setRealHeader('Content-Type: text/plain'); - echo 'Straumēta atbilde...'; + echo 'Streaming response...'; sleep(5); - echo 'Gatavs!'; + echo 'Done!'; })->stream(); ``` ### JSONP -JSONP pieprasījumiem jūs varat izvēles kārtā nodot vaicājuma parametra nosaukumu, ko izmantojat, lai definētu savu atbilde funkciju: +JSONP pieprasījumiem jūs varat izvēles kārtā nodot vaicājuma parametra nosaukumu, ko izmantojat, lai definētu savu atgriezeniskās saites funkciju: ```php Flight::jsonp(['id' => 123], 'q'); @@ -321,7 +321,7 @@ my_func({"id":123}); Ja nenododat vaicājuma parametra nosaukumu, tas pēc noklusējuma būs `jsonp`. -> **Piezīme:** Ja jūs joprojām izmantojat JSONP pieprasījumus 2025. gadā un vēlāk, ielēkiet čatā un pastāstiet mums, kāpēc! Mēs mīlam dzirdēt dažus labus kaujas/briesmu stāstus! +> **Piezīme:** Ja joprojām izmantojat JSONP pieprasījumus 2025. gadā un vēlāk, ielēkiet čatā un pastāstiet mums, kāpēc! Mēs mīlam dzirdēt dažus labus kaujas/briesmu stāstus! ### Atbildes datu notīrīšana @@ -346,21 +346,21 @@ Flight nodrošina iebūvētu atbalstu HTTP līmeņa kešošanai. Ja kešošanas #### Maršruta līmeņa kešošana -Ja vēlaties kešot visu savu atbildi, jūs varat izmantot `cache()` metodi un nodot laiku kešošanai. +Ja vēlaties kešot visu savu atbildi, jūs varat izmantot `cache()` metodi un nodot kešošanas laiku. ```php // Tas kešos atbildi uz 5 minūtēm Flight::route('/news', function () { Flight::response()->cache(time() + 300); - echo 'Šis saturs tiks kešots.'; + echo 'This content will be cached.'; }); // Alternatīvi, jūs varat izmantot virkni, ko nodotu // strtotime() metodei Flight::route('/news', function () { Flight::response()->cache('+5 minutes'); - echo 'Šis saturs tiks kešots.'; + echo 'This content will be cached.'; }); ``` @@ -371,7 +371,7 @@ Jūs varat izmantot `lastModified` metodi un nodot UNIX laika zīmogu, lai iesta ```php Flight::route('/news', function () { Flight::lastModified(1234567890); - echo 'Šis saturs tiks kešots.'; + echo 'This content will be cached.'; }); ``` @@ -382,36 +382,39 @@ Flight::route('/news', function () { ```php Flight::route('/news', function () { Flight::etag('my-unique-id'); - echo 'Šis saturs tiks kešots.'; + echo 'This content will be cached.'; }); ``` -Ņemiet vērā, ka gan `lastModified`, gan `etag` izsaukums gan iestatīs, gan pārbaudīs keša vērtību. Ja keša vērtība ir tāda pati starp pieprasījumiem, Flight nekavējoties nosūtīs `HTTP 304` atbildi un apturēs apstrādi. +Ņemiet vērā, ka izsaucot vai nu `lastModified`, vai `etag`, tas abus iestatīs un pārbaudīs keša vērtību. Ja keša vērtība ir tāda pati starp pieprasījumiem, Flight nekavējoties nosūtīs `HTTP 304` atbildi un apturēs apstrādi. ### Faila lejupielāde _v3.12.0_ -Ir palīgmēģene, lai straumētu failu galapunktam lietotājam. Jūs varat izmantot `download` metodi un nodot ceļu. +Ir palīgmēģinājuma metode, lai straumētu failu galapunktam. Jūs varat izmantot `download` metodi un nodot ceļu. ```php Flight::route('/download', function () { Flight::download('/path/to/file.txt'); + // No v3.17.1 jūs varat norādīt pielāgotu faila nosaukumu lejupielādei + Flight::download('/path/to/file.txt', 'custom_name.txt'); }); ``` ## Skatīt arī - [Maršrutēšana](/learn/routing) - Kā kartēt maršrutus uz kontrolieriem un renderēt skatus. - [Pieprasījumi](/learn/requests) - Izpratne par to, kā apstrādāt ienākošos pieprasījumus. -- [Starpprogrammatūra](/learn/middleware) - Izmantojot starpprogrammatūru ar maršrutiem autentifikācijai, žurnālošanai utt. -- [Kāpēc ietvars?](/learn/why-frameworks) - Izpratne par ieguvumiem, izmantojot ietvaru kā Flight. +- [Starpprogrammatūra](/learn/middleware) - Starpprogrammatūras izmantošana ar maršrutiem autentifikācijai, žurnālošanai utt. +- [Kāpēc ietvars?](/learn/why-frameworks) - Izpratne par ietvara, piemēram, Flight, izmantošanas priekšrocībām. - [Paplašināšana](/learn/extending) - Kā paplašināt Flight ar savu funkcionalitāti. ## Traucējummeklēšana - Ja jums ir problēmas ar novirzīšanām, kas nedarbojas, pārliecinieties, ka pievienojat `return;` metodē. -- `stop()` un `halt()` nav tas pats. `halt()` apturēs izpildi nekavējoties, bet `stop()` ļaus izpildei turpināties. +- `stop()` un `halt()` nav tas pats. `halt()` nekavējoties apturēs izpildi, savukārt `stop()` ļaus izpildei turpināties. ## Izmaiņu žurnāls -- v3.12.0 - Pievienota downloadFile palīgmēģene. +- v3.17.1 - Pievienots `$fileName` `downloadFile()` metodei. +- v3.12.0 - Pievienota downloadFile palīgmēģinājuma metode. - v3.10.0 - Pievienots `jsonHalt`. - v1.0 - Sākotnējais izdevums. \ No newline at end of file diff --git a/content/v3/lv/learn/routing.md b/content/v3/lv/learn/routing.md index a8a98f00..3f52953e 100644 --- a/content/v3/lv/learn/routing.md +++ b/content/v3/lv/learn/routing.md @@ -1,17 +1,17 @@ -# Maršrutēšana +# Maršrutizēšana ## Pārskats -Maršrutēšana Flight PHP kartē URL modeļus uz atsauces funkcijām vai klases metodēm, ļaujot ātri un vienkārši apstrādāt pieprasījumus. Tā ir izstrādāta ar minimālu slodzi, iesācējam draudzīgu lietošanu un paplašināmību bez ārējām atkarībām. +Maršrutizēšana Flight PHP kartē URL modeļus uz atgriezeniskās saites funkcijām vai klases metodēm, ļaujot ātri un vienkārši apstrādāt pieprasījumus. Tā ir paredzēta minimālam overhead, iesācējam draudzīgai lietošanai un paplašināmībai bez ārējām atkarībām. ## Saprašana -Maršrutēšana ir galvenais mehānisms, kas savieno HTTP pieprasījumus ar jūsu lietojumprogrammas loģiku Flight. Definējot maršrutus, jūs norīdat, kā dažādi URL izraisa specifisku kodu, vai nu caur funkcijām, klases metodēm vai kontrolera darbībām. Flight maršrutēšanas sistēma ir elastīga, atbalstot pamata modeļus, nosauktus parametrus, regulārās izteiksmes un papildu funkcijas, piemēram, atkarību injekciju un resursu maršrutēšanu. Šī pieeja uztur jūsu kodu organizētu un viegli uzturamu, vienlaikus paliekot ātri un vienkāršai iesācējiem un paplašināmai pieredzējušiem lietotājiem. +Maršrutizēšana ir kodola mehānisms, kas savieno HTTP pieprasījumus ar jūsu lietojumprogrammas loģiku Flight. Definējot maršrutus, jūs norādāt, kā dažādi URL aktivizē specifisku kodu, vai nu caur funkcijām, klases metodēm vai kontroliera darbībām. Flight maršrutizēšanas sistēma ir elastīga, atbalstot pamata modeļus, nosauktos parametrus, regulārās izteiksmes un papildu funkcijas, piemēram, atkarību injekciju un resursu maršrutizēšanu. Šī pieeja uztur jūsu kodu organizētu un viegli uzturamu, vienlaikus paliekot ātrai un vienkāršai iesācējiem un paplašināmai pieredzējušiem lietotājiem. -> **Piezīme:** Vēlaties saprast vairāk par maršrutēšanu? Apskatiet ["kāpēc ietvars?"](/learn/why-frameworks) lapu plašākam skaidrojumam. +> **Piezīme:** Vēlaties saprast vairāk par maršrutizēšanu? Apskatiet ["kāpēc ietvars?"](/learn/why-frameworks) lapu plašākam skaidrojumam. ## Pamata lietošana ### Vienkārša maršruta definēšana -Pamata maršrutēšana Flight tiek veikta, saskaņojot URL modeli ar atsauces funkciju vai klases un metodes masīvu. +Pamata maršrutizēšana Flight tiek veikta, saskaņojot URL modeli ar atgriezeniskās saites funkciju vai klases un metodes masīvu. ```php Flight::route('/', function(){ @@ -21,8 +21,8 @@ Flight::route('/', function(){ > Maršruti tiek saskaņoti tajā secībā, kādā tie ir definēti. Pirmais maršruts, kas atbilst pieprasījumam, tiks izsaukts. -### Funkciju lietošana kā atsauces -Atsauce var būt jebkurš aizmirsts objekts. Tātad jūs varat izmantot regulāru funkciju: +### Funkciju lietošana kā atgriezeniskās saites +Atgriezeniskā saite var būt jebkurš aizmirsts objekts. Tātad jūs varat izmantot parastu funkciju: ```php function hello() { @@ -33,7 +33,7 @@ Flight::route('/', 'hello'); ``` ### Klases un metodes lietošana kā kontrolieris -Jūs varat izmantot klases metodi (statisku vai nē): +Jūs varat izmantot klases metodi (statisku vai nē) kā kontrolieris: ```php class GreetingController { @@ -51,7 +51,7 @@ Flight::route('/', [ 'GreetingController::hello' ]); Flight::route('/', [ 'GreetingController->hello' ]); ``` -Vai arī, vispirms izveidojot objektu un tad izsaucot metodi: +Vai arī izveidojot objektu vispirms un pēc tam izsaucot metodi: ```php use flight\Engine; @@ -77,11 +77,11 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **Piezīme:** Pēc noklusējuma, kad kontrolieris tiek izsaukts ietvarā, `flight\Engine` klase vienmēr tiek injicēta, ja vien jūs neprecizējat caur [atkarību injekcijas konteineru](/learn/dependency-injection-container) +> **Piezīme:** Pēc noklusējuma, kad kontrolieris tiek izsaukts ietvarā, `flight\Engine` klase vienmēr tiek injicēta, ja vien jūs nenorādāt caur [atkarību injekcijas konteineru](/learn/dependency-injection-container) -### Metodes specifiska maršrutēšana +### Metodes specifiska maršrutizēšana -Pēc noklusējuma maršrutu modeļi tiek saskaņoti pret visām pieprasījuma metodēm. Jūs varat reaģēt uz specifiskām metodēm, novietojot identifikatoru pirms URL. +Pēc noklusējuma maršrutu modeļi tiek saskaņoti pret visām pieprasījuma metodēm. Jūs varat atbildēt uz specifiskām metodēm, novietojot identifikatoru pirms URL. ```php Flight::route('GET /', function () { @@ -100,7 +100,7 @@ Flight::put('/', function() { /* code */ }); Flight::delete('/', function() { /* code */ }); ``` -Jūs varat arī kartēt vairākas metodes uz vienu atsauces funkciju, izmantojot `|` atdalītāju: +Jūs varat arī kartēt vairākas metodes uz vienu atgriezenisko saiti, izmantojot `|` atdalītāju: ```php Flight::route('GET|POST /', function () { @@ -108,9 +108,41 @@ Flight::route('GET|POST /', function () { }); ``` +### Īpaša apstrāde HEAD un OPTIONS pieprasījumiem + +Flight nodrošina iebūvētu apstrādi `HEAD` un `OPTIONS` HTTP pieprasījumiem: + +#### HEAD pieprasījumi + +- **HEAD pieprasījumi** tiek apstrādāti tāpat kā `GET` pieprasījumi, bet Flight automātiski noņem atbildes ķermeni pirms nosūtīšanas klientam. +- Tas nozīmē, ka jūs varat definēt maršrutu `GET`, un HEAD pieprasījumi uz to pašu URL atgriezīs tikai galvenes (bez satura), kā paredzēts HTTP standartos. + +```php +Flight::route('GET /info', function() { + echo 'This is some info!'; +}); +// A HEAD request to /info will return the same headers, but no body. +``` + +#### OPTIONS pieprasījumi + +`OPTIONS` pieprasījumi tiek automātiski apstrādāti Flight jebkuram definētam maršrutam. +- Kad OPTIONS pieprasījums tiek saņemts, Flight atbild ar `204 No Content` statusu un `Allow` galveni, kas uzskaita visas atbalstītās HTTP metodes tam maršrutam. +- Jums nav jādefinē atsevišķs maršruts OPTIONS, ja vien jūs nevēlaties pielāgotu uzvedību vai modificēt atbildi. + +```php +// For a route defined as: +Flight::route('GET|POST /users', function() { /* ... */ }); + +// An OPTIONS request to /users will respond with: +// +// Status: 204 No Content +// Allow: GET, POST, HEAD, OPTIONS +``` + ### Maršrutētāja objekta lietošana -Papildus jūs varat iegūt Maršrutētāja objektu, kuram ir daži palīginstrumenti jums: +Papildus jūs varat iegūt Maršrutētāja objektu, kuram ir dažas palīgfunkcijas jums: ```php @@ -140,10 +172,10 @@ Flight::route('/user/[0-9]+', function () { }); ``` -Lai gan šī metode ir pieejama, ieteicams izmantot nosauktus parametrus vai nosauktus parametrus ar regulārajām izteiksmēm, jo tie ir lasāmāki un vieglāk uzturami. +Lai gan šī metode ir pieejama, ieteicams izmantot nosauktos parametrus vai nosauktos parametrus ar regulārajām izteiksmēm, jo tie ir lasāmāki un vieglāk uzturami. -### Nosaukti parametri -Jūs varat norādīt nosauktus parametrus savos maršrutos, kas tiks nodoti jūsu atsauces funkcijai. **Tas ir vairāk maršruta lasāmībai nekā jebkas cits. Lūdzu, skatiet sadaļu zemāk par svarīgu brīdinājumu.** +### Nosauktie parametri +Jūs varat norādīt nosauktos parametrus savos maršrutos, kuri tiks nodoti jūsu atgriezeniskajai funkcijai. **Tas ir vairāk maršruta lasāmībai nekā jebkas cits. Lūdzu, skatiet sadaļu zemāk par svarīgu brīdinājumu.** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -160,11 +192,11 @@ Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { }); ``` -> **Piezīme:** Saskaņošana regex grupām `()` ar pozīciju parametriem netiek atbalstīta. Piem.: `:'\(` +> **Piezīme:** Saskaņošana regex grupām `()` ar pozīciju parametriem nav atbalstīta. Piem.: `:'\(` #### Svarīgs brīdinājums -Lai gan iepriekšējā piemērā šķiet, ka `@name` ir tieši saistīts ar mainīgo `$name`, tas nav. Parametru secība atsauces funkcijā nosaka, kas tam tiek nodots. Ja jūs mainītu parametru secību atsauces funkcijā, mainīgie tiktu mainīti arī. Šeit ir piemērs: +Lai gan iepriekšējā piemērā šķiet, ka `@name` ir tieši saistīts ar mainīgo `$name`, tas nav. Parametru secība atgriezeniskajā funkcijā nosaka, kas tam tiek nodots. Ja jūs mainītu parametru secību atgriezeniskajā funkcijā, mainīgie tiktu mainīti arī. Šeit ir piemērs: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -173,10 +205,10 @@ Flight::route('/@name/@id', function (string $id, string $name) { ``` Un ja jūs apmeklētu šādu URL: `/bob/123`, izvade būtu `hello, 123 (bob)!`. -_Lūdzu, esiet uzmanīgi_, kad iestatāt savus maršrutus un atsauces funkcijas! +_Lūdzu, esiet uzmanīgi_, kad iestatāt savus maršrutus un atgriezeniskās saites funkcijas! -### Neobligāti parametri -Jūs varat norādīt nosauktus parametrus, kas ir neobligāti saskaņošanai, iekļaujot segmentus iekavās. +### Neobligātie parametri +Jūs varat norādīt nosauktos parametrus, kas ir neobligāti saskaņošanai, iekļaujot segmentus iekavās. ```php Flight::route( @@ -191,10 +223,10 @@ Flight::route( ); ``` -Jei neobligāti parametri, kas netiek saskaņoti, tiks nodoti kā `NULL`. +Jei neobligātie parametri, kas nav saskaņoti, tiks nodoti kā `NULL`. -### Aizstājējzīmes maršrutēšana -Saskaņošana tiek veikta tikai uz atsevišķiem URL segmentiem. Ja vēlaties saskaņot vairākus segmentus, varat izmantot `*` aizstājējzīmi. +### Mežģa maršrutizēšana +Saskaņošana tiek veikta tikai uz atsevišķiem URL segmentiem. Ja vēlaties saskaņot vairākus segmentus, varat izmantot `*` mežģi. ```php Flight::route('/blog/*', function () { @@ -202,7 +234,7 @@ Flight::route('/blog/*', function () { }); ``` -Lai maršrutētu visus pieprasījumus uz vienu atsauces funkciju, varat darīt: +Lai maršrutētu visus pieprasījumus uz vienu atgriezenisko saiti, varat izdarīt: ```php Flight::route('*', function () { @@ -212,7 +244,7 @@ Flight::route('*', function () { ### 404 Nav atrasts apstrādātājs -Pēc noklusējuma, ja URL nevar tikt atrasts, Flight nosūtīs `HTTP 404 Nav atrasts` atbildi, kas ir ļoti vienkārša un vienkārša. +Pēc noklusējuma, ja URL nevar atrast, Flight nosūtīs `HTTP 404 Not Found` atbildi, kas ir ļoti vienkārša un vienkārša. Ja vēlaties pielāgotu 404 atbildi, varat [kartēt](/learn/extending) savu `notFound` metodi: ```php @@ -233,10 +265,39 @@ Flight::map('notFound', function() { }); ``` +### Metodes nav atrasts apstrādātājs + +Pēc noklusējuma, ja URL ir atrasts, bet metode nav atļauta, Flight nosūtīs `HTTP 405 Method Not Allowed` atbildi, kas ir ļoti vienkārša un vienkārša (Pi.: Method Not Allowed. Allowed Methods are: GET, POST). Tā arī iekļaus `Allow` galveni ar atļautajām metodēm tam URL. + +Ja vēlaties pielāgotu 405 atbildi, varat [kartēt](/learn/extending) savu `methodNotFound` metodi: + +```php +use flight\net\Route; + +Flight::map('methodNotFound', function(Route $route) { + $url = Flight::request()->url; + $methods = implode(', ', $route->methods); + + // You could also use Flight::render() with a custom template. + $output = <<My Custom 405 Method Not Allowed +

The method you have requested for {$url} is not allowed.

+

Allowed Methods are: {$methods}

+ HTML; + + $this->response() + ->clearBody() + ->status(405) + ->setHeader('Allow', $methods) + ->write($output) + ->send(); +}); +``` + ## Papildu lietošana ### Atkarību injekcija maršrutos -Ja vēlaties izmantot atkarību injekciju caur konteineru (PSR-11, PHP-DI, Dice utt.), vienīgais maršrutu veids, kur tas ir pieejams, ir vai nu tieši izveidojot objektu pats un izmantojot konteineru, lai izveidotu savu objektu, vai arī izmantojot virknes, lai definētu klasi un metodi, ko izsaukt. Jūs varat apmeklēt [Atkarību injekcijas](/learn/dependency-injection-container) lapu vairāk informācijai. +Ja vēlaties izmantot atkarību injekciju caur konteineru (PSR-11, PHP-DI, Dice utt.), vienīgais maršrutu veids, kur tas ir pieejams, ir vai nu tieši izveidojot objektu pats un izmantojot konteineru, lai izveidotu savu objektu, vai arī varat izmantot virknes, lai definētu klasi un metodi, ko izsaukt. Jūs varat doties uz [Atkarību injekcijas](/learn/dependency-injection-container) lapu, lai iegūtu vairāk informācijas. Šeit ir ātrs piemērs: @@ -292,7 +353,7 @@ Flight::start(); ### Izpildes nodošana nākamajam maršrutam Novecojis -Jūs varat nodot izpildi nākamajam saskaņotajam maršrutam, atgriežot `true` no jūsu atsauces funkcijas. +Jūs varat nodot izpildi nākamajam saskaņotajam maršrutam, atgriežot `true` no jūsu atgriezeniskās saites funkcijas. ```php Flight::route('/user/@name', function (string $name) { @@ -310,8 +371,8 @@ Flight::route('/user/*', function () { Tagad ieteicams izmantot [vidutīni](/learn/middleware), lai apstrādātu sarežģītus gadījumus kā šis. -### Maršruta segvārds -Piešķirot segvārdu maršrutam, jūs varat vēlāk dinamiski izsaukt šo segvārdu savā lietojumprogrammā, lai tas tiktu ģenerēts vēlāk jūsu kodā (piem.: saite HTML veidnē vai ģenerējot pāradresācijas URL). +### Maršruta aliasēšana +Piešķirot aliasu maršrutam, jūs varat vēlāk dinamiski izsaukt šo aliasu savā lietojumprogrammā, lai tas tiktu ģenerēts vēlāk jūsu kodā (piem.: saite HTML veidnē vai ģenerējot pāradresācijas URL). ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); @@ -332,10 +393,10 @@ class UserController { ``` -Tas ir īpaši noderīgi, ja jūsu URL gadās mainīties. Iepriekšējā piemērā pieņemsim, ka lietotāji tika pārvietoti uz `/admin/users/@id` vietā. -Ar segvārdu vietā maršrutam jums vairs nav jāmeklē visi vecie URL jūsu kodā un jāmaina tie, jo segvārds tagad atgriezīs `/admin/users/5`, kā piemērā iepriekš. +Tas ir īpaši noderīgi, ja jūsu URL gadās mainīties. Iepriekšējā piemērā, pieņemsim, ka lietotāji tika pārvietoti uz `/admin/users/@id` vietā. +Ar aliasēšanu vietā maršrutam, jums vairs nav jāmeklē visi vecie URL jūsu kodā un jāmaina tie, jo alias tagad atgriezīs `/admin/users/5`, kā piemērā iepriekš. -Maršruta segvārdi joprojām darbojas grupās: +Maršruta aliasēšana joprojām darbojas grupās: ```php Flight::group('/users', function() { @@ -349,7 +410,7 @@ Flight::group('/users', function() { Ja vēlaties pārbaudīt saskaņoto maršruta informāciju, ir 2 veidi, kā to izdarīt: 1. Jūs varat izmantot `executedRoute` īpašību uz `Flight::router()` objekta. -2. Jūs varat pieprasīt, lai maršruta objekts tiktu nodots jūsu atsauces funkcijai, nododot `true` kā trešo parametru maršruta metodē. Maršruta objekts vienmēr būs pēdējais parametrs, kas nodots jūsu atsauces funkcijai. +2. Jūs varat pieprasīt, lai maršruta objekts tiktu nodots jūsu atgriezeniskajai saitei, nododot `true` kā trešo parametru maršruta metodē. Maršruta objekts vienmēr būs pēdējais parametrs, kas nodots jūsu atgriezeniskajai funkcijai. #### `executedRoute` ```php @@ -379,9 +440,9 @@ Flight::route('/', function() { }); ``` -> **Piezīme:** `executedRoute` īpašība tiks iestatīta tikai pēc tam, kad maršruts ir izpildīts. Ja mēģināsiet tam piekļūt pirms maršruta izpildes, tas būs `NULL`. Jūs varat izmantot executedRoute arī [vidutīnos](/learn/middleware)! +> **Piezīme:** `executedRoute` īpašība tiks iestatīta tikai pēc tam, kad maršruts ir izpildīts. Ja mēģināsiet piekļūt tai pirms maršruta izpildes, tā būs `NULL`. Jūs varat izmantot executedRoute arī [vidutīnos](/learn/middleware)! -#### Ievadīt `true` maršruta definīcijā +#### Padojiet `true` maršruta definīcijā ```php Flight::route('/', function(\flight\net\Route $route) { // Array of HTTP methods matched against @@ -407,8 +468,8 @@ Flight::route('/', function(\flight\net\Route $route) { }, true);// <-- This true parameter is what makes that happen ``` -### Maršrutu grupēšana un vidutīni -Var būt gadījumi, kad vēlaties grupēt saistītus maršrutus kopā (piemēram, `/api/v1`). +### Maršruta grupēšana un vidutīni +Var būt gadījumi, kad vēlaties grupēt saistītos maršrutus kopā (piemēram, `/api/v1`). Jūs varat to izdarīt, izmantojot `group` metodi: ```php @@ -453,7 +514,7 @@ Flight::group('/api', function () { #### Grupēšana ar objekta kontekstu -Jūs joprojām varat izmantot maršrutu grupēšanu ar `Engine` objektu šādā veidā: +Jūs joprojām varat izmantot maršruta grupēšanu ar `Engine` objektu šādā veidā: ```php $app = Flight::app(); @@ -475,7 +536,7 @@ $app->group('/api/v1', function (Router $router) { #### Grupēšana ar vidutīniem -Jūs varat piešķirt vidutīnus grupai maršrutu: +Jūs varat arī piešķirt vidutīnus grupai maršrutu: ```php Flight::group('/api/v1', function () { @@ -487,16 +548,16 @@ Flight::group('/api/v1', function () { Skatiet vairāk detaļu [grupas vidutīnos](/learn/middleware#grouping-middleware) lapā. -### Resursu maršrutēšana +### Resursu maršrutizēšana Jūs varat izveidot maršrutu kopu resursam, izmantojot `resource` metodi. Tas izveidos maršrutu kopu resursam, kas seko RESTful konvencijām. -Lai izveidotu resursu, dariet šādi: +Lai izveidotu resursu, dariet šādu: ```php Flight::resource('/users', UsersController::class); ``` -Un fonā tas izveidos šādus maršrutus: +Un kas notiks fonā, tas izveidos šādus maršrutus: ```php [ @@ -547,14 +608,16 @@ class UsersController > **Piezīme**: Jūs varat skatīt jaunos pievienotos maršrutus ar `runway`, palaižot `php runway routes`. -#### Pielāgošana resursu maršrutiem +#### Resursu maršrutu pielāgošana Ir dažas opcijas resursu maršrutu konfigurēšanai. ##### Alias bāze -Jūs varat konfigurēt `aliasBase`. Pēc noklusējuma alias ir pēdējā URL daļa, kas norādīta. -Piemēram, `/users/` rezultētos `aliasBase` kā `users`. Kad šie maršruti tiek izveidoti, alias ir `users.index`, `users.create` utt. Ja vēlaties mainīt alias, iestatiet `aliasBase` uz vēlamo vērtību. +Jūs varat konfigurēt `aliasBase`. Pēc noklusējuma alias ir pēdējā URL norādītās daļa. +Piemēram `/users/` rezultētos ar `aliasBase` no `users`. Kad šie maršruti tiek izveidoti, +aliasi ir `users.index`, `users.create` utt. Ja vēlaties mainīt alias, iestatiet `aliasBase` +uz vērtību, ko vēlaties. ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); @@ -574,27 +637,27 @@ Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` -Šie ir balstīti uz balto sarakstu un melno sarakstu opcijām, lai norādītu, kurus maršrutus vēlaties izveidot. +Šie ir pamatā baltā saraksta un melnā saraksta opcijas, lai jūs varētu norādīt, kurus maršrutus vēlaties izveidot. ##### Vidutīni -Jūs varat norādīt vidutīnus, kas jāizpilda katram no `resource` metodes izveidotajiem maršrutiem. +Jūs varat norādīt vidutīnus, kas jāizpilda katram no maršrutiem, ko izveido `resource` metode. ```php Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]); ``` -### Plūsmas atbildes +### Strumēšanas atbildes -Jūs tagad varat plūst atbildes klientam, izmantojot `stream()` vai `streamWithHeaders()`. -Tas ir noderīgi lielu failu nosūtīšanai, garām procesiem vai lielu atbilžu ģenerēšanai. -Maršruta plūsmošana tiek apstrādāta nedaudz savādāk nekā regulārs maršruts. +Jūs tagad varat straumēt atbildes klientam, izmantojot `stream()` vai `streamWithHeaders()`. +Tas ir noderīgi lielu failu nosūtīšanai, ilgstošiem procesiem vai lielu atbilžu ģenerēšanai. +Strumēšanas maršruta apstrāde ir nedaudz atšķirīga no parasta maršruta. -> **Piezīme:** Plūsmas atbildes ir pieejamas tikai tad, ja jums ir [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) iestatīts uz `false`. +> **Piezīme:** Strumēšanas atbildes ir pieejamas tikai tad, ja jums ir [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) iestatīts uz `false`. -#### Plūsma ar manuāliem galvenes +#### Strumēšana ar manuālām galvenēm -Jūs varat plūst atbildi klientam, izmantojot `stream()` metodi maršrutā. Ja dariet to, jums jāiestata visi galvenes ar roku, pirms izvadat jebko klientam. +Jūs varat straumēt atbildi klientam, izmantojot `stream()` metodi maršrutā. Ja dariet to, jums jāiestata visas galvenes ar roku, pirms izvadat kaut ko klientam. Tas tiek darīts ar `header()` php funkciju vai `Flight::response()->setRealHeader()` metodi. ```php @@ -631,9 +694,9 @@ Flight::route('/@filename', function($filename) { })->stream(); ``` -#### Plūsma ar galvenēm +#### Strumēšana ar galvenēm -Jūs varat izmantot `streamWithHeaders()` metodi, lai iestatītu galvenes, pirms sākat plūst. +Jūs varat izmantot `streamWithHeaders()` metodi, lai iestatītu galvenes pirms sākat straumēt. ```php Flight::route('/stream-users', function() { @@ -667,25 +730,24 @@ Flight::route('/stream-users', function() { ``` ## Skatīt arī -- [Vidutīni](/learn/middleware) - Vidutīņu lietošana ar maršrutiem autentifikācijai, žurnālveidošanai utt. -- [Atkarību injekcija](/learn/dependency-injection-container) - Objektu izveides un pārvaldības vienkāršošana maršrutos. -- [Kāpēc ietvars?](/learn/why-frameworks) - Ietvara kā Flight izmantošanas priekšrocību saprašana. -- [Paplašināšana](/learn/extending) - Kā paplašināt Flight ar savu funkcionalitāti, ieskaitot `notFound` metodi. +- [Vidutīni](/learn/middleware) - Vidutīņu lietošana ar maršrutiem autentifikācijai, žurnālošanai utt. +- [Atkarību injekcija](/learn/dependency-injection-container) - Objektu izveides un vadības vienkāršošana maršrutos. +- [Kāpēc ietvars?](/learn/why-frameworks) - Ietvara izmantošanas priekšrocību saprašana, piemēram, Flight. +- [Paplašināšana](/learn/extending) - Kā paplašināt Flight ar savu funkcionalitāti, tostarp `notFound` metodi. - [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - PHP funkcija regulāro izteiksmju saskaņošanai. ## Traucējummeklēšana -- Maršruta parametri tiek saskaņoti pēc secības, nevis nosaukuma. Pārliecinieties, ka atsauces parametru secība atbilst maršruta definīcijai. -- `Flight::get()` lietošana nedefinē maršrutu; izmantojiet `Flight::route('GET /...')` maršrutēšanai vai Maršrutētāja objekta kontekstu grupās (piem. `$router->get(...)`). +- Maršruta parametri tiek saskaņoti pēc secības, nevis pēc nosaukuma. Pārliecinieties, ka atgriezeniskās saites parametru secība atbilst maršruta definīcijai. +- `Flight::get()` lietošana nedefinē maršrutu; izmantojiet `Flight::route('GET /...')` maršrutizēšanai vai Maršrutētāja objekta kontekstu grupās (piem. `$router->get(...)`). - executedRoute īpašība tiek iestatīta tikai pēc maršruta izpildes; tā ir NULL pirms izpildes. -- Plūsmošanai ir jāatspējo mantojamā Flight izvades buferizācijas funkcionalitāte (`flight.v2.output_buffering = false`). -- Atkarību injekcijai tikai noteiktas maršruta definīcijas atbalsta konteineru balstītu instantiāciju. +- Strumēšanai ir jāatspējo legacy Flight izvades buferizēšanas funkcionalitāte (`flight.v2.output_buffering = false`). +- Atkarību injekcijai atbalsta tikai noteiktas maršruta definīcijas konteineru balstītai instantiācijai. ### 404 Nav atrasts vai negaidīta maršruta uzvedība -Ja redzat 404 Nav atrasts kļūdu (bet esat pārliecināts uz savu dzīvi, ka tas tiešām ir tur un tas nav drukas kļūda), tas patiesībā varētu būt problēma ar jūsu atgriežamo vērtību jūsu maršruta galapunktā, nevis tikai izvadi. Iemesls tam ir tīšs, bet var uzbrukt dažiem izstrādātājiem. +Ja redzat 404 Nav atrasts kļūdu (bet esat pārliecināts uz savu dzīvību, ka tas tiešām ir tur un tas nav drukas kļūda), tas patiesībā varētu būt problēma ar jūsu atgriežamo vērtību maršruta galapunktā, nevis tikai to izvadi. Iemesls tam ir tīšs, bet var uzbrukt dažiem izstrādātājiem. ```php - Flight::route('/hello', function(){ // This might cause a 404 Not Found error return 'Hello World'; @@ -695,12 +757,11 @@ Flight::route('/hello', function(){ Flight::route('/hello', function(){ echo 'Hello World'; }); - ``` -Iemesls tam ir īpašs mehānisms, kas iebūvēts maršrutētājā, kas apstrādā atgriežamo izvadi kā signālu "iet uz nākamo maršrutu". -Jūs varat redzēt uzvedību, kas dokumentēta [Maršrutēšanas](/learn/routing#passing) sadaļā. +Iemesls tam ir īpašs mehānisms, kas iebūvēts maršrutētājā, kas apstrādā atgriezenisko izvadi kā signālu "doties uz nākamo maršrutu". +Jūs varat redzēt uzvedību, kas dokumentēta [Maršrutizēšanas](/learn/routing#passing) sadaļā. ## Izmaiņu žurnāls -- v3: Pievienota resursu maršrutēšana, maršruta segvārdi un plūsmas atbalsts, maršruta grupas un vidutīņu atbalsts. -- v1: Liela daļa pamata funkciju pieejama. \ No newline at end of file +- v3: Pievienota resursu maršrutizēšana, maršruta aliasēšana un straumēšanas atbalsts, maršruta grupas un vidutīnu atbalsts. +- v1: Liela daļa pamata funkciju ir pieejamas. \ No newline at end of file diff --git a/content/v3/pt/awesome-plugins/apm.md b/content/v3/pt/awesome-plugins/apm.md index a5552ccc..85b109bc 100644 --- a/content/v3/pt/awesome-plugins/apm.md +++ b/content/v3/pt/awesome-plugins/apm.md @@ -1,12 +1,14 @@ -# Documentação do FlightPHP APM +# Documentação do APM do FlightPHP -Bem-vindo ao FlightPHP APM—seu treinador pessoal de desempenho do aplicativo! Este guia é o seu roteiro para configurar, usar e dominar o Monitoramento de Desempenho de Aplicações (APM) com FlightPHP. Seja caçando solicitações lentas ou apenas se empolgando com gráficos de latência, cobrimos tudo. Vamos tornar seu aplicativo mais rápido, seus usuários mais felizes e suas sessões de depuração uma brisa! +Bem-vindo ao FlightPHP APM—o treinador pessoal de desempenho do seu app! Este guia é o seu mapa para configurar, usar e dominar o Application Performance Monitoring (APM) com FlightPHP. Seja caçando requisições lentas ou apenas querendo se aprofundar em gráficos de latência, nós cobrimos tudo. Vamos tornar seu app mais rápido, seus usuários mais felizes e suas sessões de depuração uma brisa! + +Veja uma [demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) do dashboard para o site Flight Docs. ![FlightPHP APM](/images/apm.png) -## Por que o APM Importa +## Por Que o APM Importa -Imagine isso: seu aplicativo é um restaurante movimentado. Sem uma forma de rastrear quanto tempo as ordens levam ou onde a cozinha está travando, você está adivinhando por que os clientes estão saindo irritados. O APM é seu subchef—ele observa cada etapa, desde solicitações de entrada até consultas de banco de dados, e marca qualquer coisa que esteja desacelerando você. Páginas lentas perdem usuários (estudos dizem que 53% abandonam se um site leva mais de 3 segundos para carregar!), e o APM ajuda a capturar esses problemas *antes* que eles machuquem. É uma paz de espírito proativa—menos momentos de “por que isso está quebrado?”, mais vitórias de “olha como isso roda bem!”. +Imagine isso: seu app é um restaurante movimentado. Sem uma forma de rastrear quanto tempo as ordens demoram ou onde a cozinha está travando, você está adivinhando por que os clientes estão saindo irritados. O APM é o seu sous-chef—ele observa cada passo, desde requisições de entrada até consultas de banco de dados, e sinaliza qualquer coisa que esteja te atrasando. Páginas lentas perdem usuários (estudos dizem que 53% abandonam se um site demora mais de 3 segundos para carregar!), e o APM te ajuda a capturar esses problemas *antes* que eles doam. É uma paz de espírito proativa—menos momentos de “por que isso está quebrado?”, mais vitórias de “olha como isso roda suave!”. ## Instalação @@ -16,18 +18,18 @@ Comece com o Composer: composer require flightphp/apm ``` -Você precisará: -- **PHP 7.4+**: Mantém compatibilidade com distribuições LTS do Linux enquanto suporta PHP moderno. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: O framework leve que estamos melhorando. +Você precisará de: +- **PHP 7.4+**: Mantém compatibilidade com distros Linux LTS enquanto suporta PHP moderno. +- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: O framework leve que estamos impulsionando. ## Bancos de Dados Suportados O FlightPHP APM atualmente suporta os seguintes bancos de dados para armazenar métricas: -- **SQLite3**: Simples, baseado em arquivo e ótimo para desenvolvimento local ou aplicativos pequenos. Opção padrão na maioria das configurações. +- **SQLite3**: Simples, baseado em arquivo, e ótimo para desenvolvimento local ou apps pequenos. Opção padrão na maioria das configurações. - **MySQL/MariaDB**: Ideal para projetos maiores ou ambientes de produção onde você precisa de armazenamento robusto e escalável. -Você pode escolher o tipo de banco de dados durante a etapa de configuração (veja abaixo). Certifique-se de que seu ambiente PHP tenha as extensões necessárias instaladas (por exemplo, `pdo_sqlite` ou `pdo_mysql`). +Você pode escolher o tipo de banco de dados durante o passo de configuração (veja abaixo). Certifique-se de que seu ambiente PHP tenha as extensões necessárias instaladas (ex.: `pdo_sqlite` ou `pdo_mysql`). ## Começando @@ -35,7 +37,7 @@ Aqui está o seu passo a passo para o APM incrível: ### 1. Registrar o APM -Adicione isso ao seu `index.php` ou um arquivo `services.php` para começar a rastrear: +Adicione isso no seu `index.php` ou arquivo `services.php` para começar o rastreamento: ```php use flight\apm\logger\LoggerFactory; @@ -47,23 +49,23 @@ $Apm->bindEventsToFlightInstance($app); // Se você estiver adicionando uma conexão de banco de dados // Deve ser PdoWrapper ou PdoQueryCapture das Extensões Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True necessário para habilitar o rastreamento no APM. +$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True necessário para habilitar rastreamento no APM. $Apm->addPdoConnection($pdo); ``` **O que está acontecendo aqui?** - `LoggerFactory::create()` pega sua configuração (mais sobre isso em breve) e configura um logger—SQLite por padrão. -- `Apm` é a estrela—ele escuta os eventos do Flight (solicitações, rotas, erros, etc.) e coleta métricas. -- `bindEventsToFlightInstance($app)` liga tudo ao seu aplicativo Flight. +- `Apm` é a estrela—ele escuta os eventos do Flight (requisições, rotas, erros, etc.) e coleta métricas. +- `bindEventsToFlightInstance($app)` conecta tudo ao seu app Flight. -**Dica Profissional: Amostragem** -Se seu aplicativo estiver movimentado, registrar *toda* solicitação pode sobrecarregar as coisas. Use uma taxa de amostragem (0.0 a 1.0): +**Dica Pro: Amostragem** +Se o seu app estiver ocupado, registrar *todas* as requisições pode sobrecarregar as coisas. Use uma taxa de amostragem (0.0 a 1.0): ```php -$Apm = new Apm($ApmLogger, 0.1); // Registra 10% das solicitações +$Apm = new Apm($ApmLogger, 0.1); // Registra 10% das requisições ``` -Isso mantém o desempenho ágil enquanto ainda fornece dados sólidos. +Isso mantém o desempenho ágil enquanto ainda te dá dados sólidos. ### 2. Configure-o @@ -74,9 +76,9 @@ php vendor/bin/runway apm:init ``` **O que isso faz?** -- Inicia um assistente perguntando de onde vêm as métricas brutas (origem) e para onde vão os dados processados (destino). -- Padrão é SQLite—por exemplo, `sqlite:/tmp/apm_metrics.sqlite` para origem, outro para destino. -- Você terminará com uma configuração como: +- Inicia um assistente perguntando de onde vêm as métricas brutas (fonte) e para onde vão os dados processados (destino). +- Padrão é SQLite—ex.: `sqlite:/tmp/apm_metrics.sqlite` para fonte, outro para destino. +- Você acabará com uma configuração como: ```json { "apm": { @@ -88,32 +90,32 @@ php vendor/bin/runway apm:init } ``` -> Esse processo também perguntará se você deseja executar as migrações para essa configuração. Se você estiver configurando isso pela primeira vez, a resposta é sim. +> Esse processo também perguntará se você quer executar as migrações para essa configuração. Se você estiver configurando pela primeira vez, a resposta é sim. **Por que dois locais?** -Métricas brutas se acumulam rapidamente (pense em logs não filtrados). O worker processa-as em um destino estruturado para o painel. Mantém as coisas organizadas! +Métricas brutas se acumulam rápido (pense em logs não filtrados). O worker as processa em um destino estruturado para o dashboard. Mantém tudo organizado! ### 3. Processar Métricas com o Worker -O worker transforma métricas brutas em dados prontos para o painel. Execute-o uma vez: +O worker transforma métricas brutas em dados prontos para o dashboard. Execute uma vez: ```bash php vendor/bin/runway apm:worker ``` **O que ele está fazendo?** -- Lê da sua origem (por exemplo, `apm_metrics.sqlite`). -- Processa até 100 métricas (tamanho do lote padrão) no seu destino. -- Para quando terminar ou se não houver métricas restantes. +- Lê da sua fonte (ex.: `apm_metrics.sqlite`). +- Processa até 100 métricas (tamanho de lote padrão) para o seu destino. +- Para quando termina ou se não há métricas restantes. -**Mantenha-o Executando** -Para aplicativos ao vivo, você desejará processamento contínuo. Aqui estão suas opções: +**Mantenha-o Rodando** +Para apps ao vivo, você quer processamento contínuo. Aqui estão suas opções: - **Modo Daemon**: ```bash php vendor/bin/runway apm:worker --daemon ``` - Executa para sempre, processando métricas à medida que elas chegam. Ótimo para dev ou configurações pequenas. + Roda para sempre, processando métricas conforme chegam. Ótimo para dev ou configurações pequenas. - **Crontab**: Adicione isso ao seu crontab (`crontab -e`): @@ -129,30 +131,30 @@ Para aplicativos ao vivo, você desejará processamento contínuo. Aqui estão s php vendor/bin/runway apm:worker --daemon # Ctrl+B, então D para destacar; `tmux attach -t apm-worker` para reconectar ``` - Mantém executando mesmo se você sair. + Mantém rodando mesmo se você sair. - **Ajustes Personalizados**: ```bash php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 ``` - - `--batch_size 50`: Processa 50 métricas de cada vez. + - `--batch_size 50`: Processa 50 métricas de uma vez. - `--max_messages 1000`: Para após 1000 métricas. - `--timeout 300`: Sai após 5 minutos. -**Por que se incomodar?** -Sem o worker, seu painel está vazio. É a ponte entre logs brutos e insights acionáveis. +**Por que se preocupar?** +Sem o worker, seu dashboard está vazio. É a ponte entre logs brutos e insights acionáveis. -### 4. Iniciar o Painel +### 4. Inicie o Dashboard -Veja os sinais vitais do seu aplicativo: +Veja os vitais do seu app: ```bash php vendor/bin/runway apm:dashboard ``` -**O que isso é?** +**O que é isso?** - Inicia um servidor PHP em `http://localhost:8001/apm/dashboard`. -- Mostra logs de solicitações, rotas lentas, taxas de erros e mais. +- Mostra logs de requisições, rotas lentas, taxas de erro e mais. **Personalize-o**: ```bash @@ -160,43 +162,43 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l ``` - `--host 0.0.0.0`: Acessível de qualquer IP (útil para visualização remota). - `--port 8080`: Use uma porta diferente se 8001 estiver ocupada. -- `--php-path`: Aponte para PHP se ele não estiver no seu PATH. +- `--php-path`: Aponta para PHP se não estiver no seu PATH. Acesse a URL no seu navegador e explore! -#### Modo de Produção +#### Modo Produção -Para produção, você pode precisar tentar algumas técnicas para fazer o painel funcionar, pois provavelmente há firewalls e outras medidas de segurança no lugar. Aqui estão algumas opções: +Para produção, você pode precisar tentar algumas técnicas para fazer o dashboard rodar, já que provavelmente há firewalls e outras medidas de segurança no lugar. Aqui estão algumas opções: -- **Use um Proxy Inverso**: Configure Nginx ou Apache para encaminhar solicitações para o painel. -- **Túnel SSH**: Se você puder SSH no servidor, use `ssh -L 8080:localhost:8001 youruser@yourserver` para tunelizar o painel para sua máquina local. -- **VPN**: Se seu servidor estiver atrás de uma VPN, conecte-se a ela e acesse o painel diretamente. -- **Configure Firewall**: Abra a porta 8001 para seu IP ou a rede do servidor. (ou qualquer porta que você definir). -- **Configure Apache/Nginx**: Se você tiver um servidor web na frente do seu aplicativo, você pode configurá-lo para um domínio ou subdomínio. Se fizer isso, defina o diretório raiz para `/path/to/your/project/vendor/flightphp/apm/dashboard`. +- **Use um Reverse Proxy**: Configure Nginx ou Apache para encaminhar requisições para o dashboard. +- **Túnel SSH**: Se você puder fazer SSH no servidor, use `ssh -L 8080:localhost:8001 youruser@yourserver` para tunelar o dashboard para sua máquina local. +- **VPN**: Se o seu servidor estiver atrás de uma VPN, conecte-se a ela e acesse o dashboard diretamente. +- **Configure Firewall**: Abra a porta 8001 para o seu IP ou a rede do servidor. (ou qualquer porta que você definiu). +- **Configure Apache/Nginx**: Se você tiver um servidor web na frente do seu app, você pode configurá-lo para um domínio ou subdomínio. Se fizer isso, você definirá a raiz do documento para `/path/to/your/project/vendor/flightphp/apm/dashboard` -#### Quer um painel diferente? +#### Quer um dashboard diferente? -Você pode criar seu próprio painel se quiser! Olhe no diretório vendor/flightphp/apm/src/apm/presenter para ideias sobre como apresentar os dados para o seu próprio painel! +Você pode construir o seu próprio dashboard se quiser! Olhe no diretório vendor/flightphp/apm/src/apm/presenter para ideias de como apresentar os dados para o seu próprio dashboard! -## Recursos do Painel +## Recursos do Dashboard -O painel é sua sede do APM—aqui está o que você verá: +O dashboard é o seu QG do APM—aqui está o que você verá: -- **Log de Solicitações**: Cada solicitação com carimbo de data/hora, URL, código de resposta e tempo total. Clique em “Detalhes” para middleware, consultas e erros. -- **Solicitações Mais Lentas**: As 5 principais solicitações consumindo tempo (por exemplo, “/api/heavy” em 2.5s). -- **Rotas Mais Lentas**: As 5 principais rotas pelo tempo médio—ótimo para identificar padrões. -- **Taxa de Erros**: Porcentagem de solicitações falhando (por exemplo, 2.3% de 500s). -- **Percentis de Latência**: 95º (p95) e 99º (p99) tempos de resposta—conheça seus cenários piores. -- **Gráfico de Códigos de Resposta**: Visualize 200s, 404s, 500s ao longo do tempo. -- **Consultas/Middleware Longas**: As 5 principais chamadas de banco de dados lentas e camadas de middleware. -- **Acerto/Falha de Cache**: Quão frequentemente seu cache salva o dia. +- **Log de Requisições**: Toda requisição com timestamp, URL, código de resposta e tempo total. Clique em “Detalhes” para middleware, consultas e erros. +- **Requisições Mais Lentas**: Top 5 requisições consumindo tempo (ex.: “/api/heavy” em 2.5s). +- **Rotas Mais Lentas**: Top 5 rotas por tempo médio—ótimo para identificar padrões. +- **Taxa de Erro**: Percentual de requisições falhando (ex.: 2.3% de 500s). +- **Percentis de Latência**: 95º (p95) e 99º (p99) tempos de resposta—conheça seus cenários de pior caso. +- **Gráfico de Código de Resposta**: Visualize 200s, 404s, 500s ao longo do tempo. +- **Consultas/Middleware Longas**: Top 5 chamadas de banco de dados lentas e camadas de middleware. +- **Acerto/Erro de Cache**: Com que frequência seu cache salva o dia. **Extras**: -- Filtre por “Última Hora”, “Último Dia” ou “Última Semana”. -- Ative o modo escuro para aquelas sessões noturnas tardias. +- Filtre por “Última Hora”, “Último Dia” ou “Última Semana.” +- Ative o modo escuro para aquelas sessões noturnas. **Exemplo**: -Uma solicitação para `/users` pode mostrar: +Uma requisição para `/users` pode mostrar: - Tempo Total: 150ms - Middleware: `AuthMiddleware->handle` (50ms) - Consulta: `SELECT * FROM users` (80ms) @@ -216,8 +218,8 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ])); ``` -**Onde isso aparece?** -Nos detalhes da solicitação do painel sob “Eventos Personalizados”—expansível com formatação JSON bonita. +**Onde aparece?** +Nos detalhes da requisição do dashboard sob “Eventos Personalizados”—expandível com formatação JSON bonita. **Caso de Uso**: ```php @@ -229,7 +231,7 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -Agora você verá se essa API está arrastando seu aplicativo para baixo! +Agora você verá se essa API está arrastando seu app para baixo! ## Monitoramento de Banco de Dados @@ -238,21 +240,21 @@ Rastreie consultas PDO assim: ```php use flight\database\PdoWrapper; -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True necessário para habilitar o rastreamento no APM. +$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True necessário para habilitar rastreamento no APM. $Apm->addPdoConnection($pdo); ``` -**O que Você Obtém**: -- Texto da consulta (por exemplo, `SELECT * FROM users WHERE id = ?`) -- Tempo de execução (por exemplo, 0.015s) -- Contagem de linhas (por exemplo, 42) +**O Que Você Obtém**: +- Texto da consulta (ex.: `SELECT * FROM users WHERE id = ?`) +- Tempo de execução (ex.: 0.015s) +- Contagem de linhas (ex.: 42) **Atenção**: -- **Opcional**: Pule isso se você não precisar de rastreamento de DB. -- **Apenas PdoWrapper**: O PDO principal ainda não está conectado—fique ligado! -- **Aviso de Desempenho**: Registrar cada consulta em um site pesado de DB pode desacelerar as coisas. Use amostragem (`$Apm = new Apm($ApmLogger, 0.1)`) para aliviar a carga. +- **Opcional**: Pule isso se não precisar de rastreamento de BD. +- **Apenas PdoWrapper**: PDO principal ainda não está conectado—fique ligado! +- **Aviso de Desempenho**: Registrar toda consulta em um site pesado de BD pode desacelerar as coisas. Use amostragem (`$Apm = new Apm($ApmLogger, 0.1)`) para aliviar a carga. -**Exemplo de Saída**: +**Saída de Exemplo**: - Consulta: `SELECT name FROM products WHERE price > 100` - Tempo: 0.023s - Linhas: 15 @@ -262,48 +264,48 @@ $Apm->addPdoConnection($pdo); Ajuste o worker ao seu gosto: - `--timeout 300`: Para após 5 minutos—bom para testes. -- `--max_messages 500`: Limita em 500 métricas—mantém finito. +- `--max_messages 500`: Limita a 500 métricas—mantém finito. - `--batch_size 200`: Processa 200 de uma vez—equilibra velocidade e memória. -- `--daemon`: Executa sem parar—ideal para monitoramento ao vivo. +- `--daemon`: Roda sem parar—ideal para monitoramento ao vivo. **Exemplo**: ```bash php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ``` -Executa por uma hora, processando 100 métricas de cada vez. +Roda por uma hora, processando 100 métricas de uma vez. -## ID de Solicitação no Aplicativo +## ID de Requisição no App -Cada solicitação tem um ID de solicitação único para rastreamento. Você pode usar esse ID no seu aplicativo para correlacionar logs e métricas. Por exemplo, você pode adicionar o ID de solicitação a uma página de erro: +Cada requisição tem um ID de requisição único para rastreamento. Você pode usar esse ID no seu app para correlacionar logs e métricas. Por exemplo, você pode adicionar o ID de requisição a uma página de erro: ```php Flight::map('error', function($message) { - // Obtenha o ID de solicitação do cabeçalho de resposta X-Flight-Request-Id + // Obtenha o ID de requisição do cabeçalho de resposta X-Flight-Request-Id $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - // Além disso, você poderia buscá-lo da variável Flight - // Esse método não funcionará bem em plataformas swoole ou outras assíncronas. + // Além disso, você poderia obtê-lo da variável Flight + // Esse método não funcionará bem em swoole ou outras plataformas assíncronas. // $requestId = Flight::get('apm.request_id'); - echo "Error: $message (Request ID: $requestId)"; + echo "Erro: $message (ID de Requisição: $requestId)"; }); ``` ## Atualizando -Se você estiver atualizando para uma versão mais recente do APM, há uma chance de que haja migrações de banco de dados que precisam ser executadas. Você pode fazer isso executando o seguinte comando: +Se você estiver atualizando para uma versão mais nova do APM, há uma chance de que haja migrações de banco de dados que precisam ser executadas. Você pode fazer isso executando o comando a seguir: ```bash php vendor/bin/runway apm:migrate ``` Isso executará quaisquer migrações necessárias para atualizar o esquema do banco de dados para a versão mais recente. -**Nota:** Se o banco de dados do seu APM for grande, essas migrações podem levar algum tempo para executar. Você pode querer executar esse comando durante horas de pico baixo. +**Nota:** Se o seu banco de dados APM for grande em tamanho, essas migrações podem demorar um pouco para rodar. Você pode querer executar esse comando durante horários de baixa atividade. ## Limpando Dados Antigos -Para manter seu banco de dados organizado, você pode limpar dados antigos. Isso é especialmente útil se você estiver executando um aplicativo movimentado e quiser manter o tamanho do banco de dados gerenciável. -Você pode fazer isso executando o seguinte comando: +Para manter seu banco de dados organizado, você pode limpar dados antigos. Isso é especialmente útil se você estiver rodando um app movimentado e quiser manter o tamanho do banco de dados gerenciável. +Você pode fazer isso executando o comando a seguir: ```bash php vendor/bin/runway apm:purge @@ -317,18 +319,18 @@ Isso removerá todos os dados mais antigos que 7 dias do banco de dados. ## Solução de Problemas -Preso? Tente esses: +Travado? Tente estes: -- **Nenhum Dado no Painel?** - - O worker está executando? Verifique `ps aux | grep apm:worker`. +- **Sem Dados no Dashboard?** + - O worker está rodando? Verifique `ps aux | grep apm:worker`. - Caminhos de configuração correspondem? Verifique se os DSNs em `.runway-config.json` apontam para arquivos reais. - Execute `php vendor/bin/runway apm:worker` manualmente para processar métricas pendentes. - **Erros no Worker?** - - Dê uma olhada nos seus arquivos SQLite (por exemplo, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Verifique os logs do PHP para rastreamentos de pilha. + - Dê uma olhada nos seus arquivos SQLite (ex.: `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). + - Verifique os logs PHP para traces de pilha. -- **Painel Não Inicia?** +- **Dashboard Não Inicia?** - Porta 8001 em uso? Use `--port 8080`. - PHP não encontrado? Use `--php-path /usr/bin/php`. - Firewall bloqueando? Abra a porta ou use `--host localhost`. @@ -338,8 +340,8 @@ Preso? Tente esses: - Reduza o tamanho do lote: `--batch_size 20`. - **Não Rastreando Exceções/Erros?** - - Se você tiver [Tracy](https://tracy.nette.org/) habilitado para o seu projeto, ele substituirá o tratamento de erros do Flight. Você precisará desabilitar o Tracy e garantir que `Flight::set('flight.handle_errors', true);` esteja definido. + - Se você tiver [Tracy](https://tracy.nette.org/) habilitado para o seu projeto, ele substituirá o tratamento de erros do Flight. Você precisará desabilitar o Tracy e depois garantir que `Flight::set('flight.handle_errors', true);` esteja definido. - **Não Rastreando Consultas de Banco de Dados?** - - Certifique-se de estar usando `PdoWrapper` para suas conexões de banco de dados. + - Certifique-se de estar usando `PdoWrapper` para as suas conexões de banco de dados. - Certifique-se de que o último argumento no construtor seja `true`. \ No newline at end of file diff --git a/content/v3/pt/learn/ai.md b/content/v3/pt/learn/ai.md index 7c95673c..717ab1de 100644 --- a/content/v3/pt/learn/ai.md +++ b/content/v3/pt/learn/ai.md @@ -2,20 +2,20 @@ ## Visão Geral -Flight facilita o superdesempenho dos seus projetos PHP com ferramentas alimentadas por IA e fluxos de trabalho modernos para desenvolvedores. Com comandos integrados para conectar a provedores de LLM (Large Language Model) e gerar instruções de codificação específicas para o projeto com IA, Flight ajuda você e sua equipe a tirar o máximo proveito de assistentes de IA como GitHub Copilot, Cursor e Windsurf. +Flight facilita o superpoder de seus projetos PHP com ferramentas alimentadas por IA e fluxos de trabalho modernos para desenvolvedores. Com comandos integrados para conectar a provedores de LLM (Large Language Model) e gerar instruções de codificação específicas do projeto alimentadas por IA, Flight ajuda você e sua equipe a tirar o máximo de assistentes de IA como GitHub Copilot, Cursor e Windsurf. ## Entendendo -Assistentes de codificação com IA são mais úteis quando entendem o contexto, convenções e objetivos do seu projeto. Os ajudantes de IA do Flight permitem que você: +Assistentes de codificação de IA são mais úteis quando entendem o contexto, convenções e objetivos do seu projeto. Os ajudantes de IA do Flight permitem que você: - Conecte seu projeto a provedores populares de LLM (OpenAI, Grok, Claude, etc.) -- Gere e atualize instruções específicas para o projeto para ferramentas de IA, para que todos recebam ajuda consistente e relevante +- Gere e atualize instruções específicas do projeto para ferramentas de IA, para que todos recebam ajuda consistente e relevante - Mantenha sua equipe alinhada e produtiva, com menos tempo gasto explicando o contexto Esses recursos estão integrados ao CLI principal do Flight e ao projeto inicial oficial [flightphp/skeleton](https://github.com/flightphp/skeleton). ## Uso Básico -### 1. Configurando Credenciais de LLM +### Configurando Credenciais de LLM O comando `ai:init` o guia na conexão do seu projeto a um provedor de LLM. @@ -34,15 +34,15 @@ Isso cria um arquivo `.runway-creds.json` na raiz do seu projeto (e garante que ``` Bem-vindo ao AI Init! Qual API de LLM você deseja usar? [1] openai, [2] grok, [3] claude: 1 -Digite a URL base para a API de LLM [https://api.openai.com]: -Digite sua chave de API para openai: sk-... -Digite o nome do modelo que você deseja usar (ex. gpt-4, claude-3-opus, etc) [gpt-4o]: +Insira a URL base para a API de LLM [https://api.openai.com]: +Insira sua chave de API para openai: sk-... +Insira o nome do modelo que você deseja usar (ex. gpt-4, claude-3-opus, etc) [gpt-4o]: Credenciais salvas em .runway-creds.json ``` -### 2. Gerando Instruções Específicas para o Projeto com IA +### Gerando Instruções Específicas do Projeto para IA -O comando `ai:generate-instructions` ajuda você a criar ou atualizar instruções para assistentes de codificação com IA, adaptadas ao seu projeto. +O comando `ai:generate-instructions` ajuda você a criar ou atualizar instruções para assistentes de codificação de IA, adaptadas ao seu projeto. ```bash php runway ai:generate-instructions @@ -57,7 +57,7 @@ Você responderá a algumas perguntas sobre seu projeto (descrição, banco de d ``` Por favor, descreva para que serve seu projeto? Minha API incrível Qual banco de dados você planeja usar? MySQL -Qual mecanismo de templating HTML você planeja usar (se houver)? latte +Qual engine de templating HTML você planeja usar (se houver)? latte A segurança é um elemento importante deste projeto? (y/n) y ... Instruções de IA atualizadas com sucesso. @@ -67,7 +67,7 @@ Agora, suas ferramentas de IA darão sugestões mais inteligentes e relevantes c ## Uso Avançado -- Você pode personalizar a localização dos arquivos de credenciais ou instruções usando opções de comando (veja `--help` para cada comando). +- Você pode personalizar a localização dos seus arquivos de credenciais ou instruções usando opções de comando (veja `--help` para cada comando). - Os ajudantes de IA são projetados para funcionar com qualquer provedor de LLM que suporte APIs compatíveis com OpenAI. - Se você quiser atualizar suas instruções à medida que seu projeto evolui, basta executar novamente `ai:generate-instructions` e responder aos prompts novamente. @@ -80,7 +80,7 @@ Agora, suas ferramentas de IA darão sugestões mais inteligentes e relevantes c - Se você vir "Missing .runway-creds.json", execute `php runway ai:init` primeiro. - Certifique-se de que sua chave de API é válida e tem acesso ao modelo selecionado. -- Se as instruções não estiverem atualizando, verifique as permissões de arquivos no diretório do seu projeto. +- Se as instruções não estiverem atualizando, verifique as permissões de arquivo no diretório do seu projeto. ## Changelog diff --git a/content/v3/pt/learn/requests.md b/content/v3/pt/learn/requests.md index 99912a2d..0274c59f 100644 --- a/content/v3/pt/learn/requests.md +++ b/content/v3/pt/learn/requests.md @@ -2,7 +2,8 @@ ## Visão Geral -Flight encapsula a requisição HTTP em um único objeto, que pode ser acessado fazendo: +Flight encapsula a requisição HTTP em um único objeto, que pode ser +acessado fazendo: ```php $request = Flight::request(); @@ -10,13 +11,13 @@ $request = Flight::request(); ## Entendendo -Requisições HTTP são um dos aspectos principais para entender sobre o ciclo de vida HTTP. Um usuário realiza uma ação em um navegador web ou em um cliente HTTP, e eles enviam uma série de cabeçalhos, corpo, URL, etc para o seu projeto. Você pode capturar esses cabeçalhos (a linguagem do navegador, que tipo de compressão eles podem lidar, o agente do usuário, etc) e capturar o corpo e a URL que é enviada para a sua aplicação Flight. Essas requisições são essenciais para que sua app entenda o que fazer em seguida. +Requisições HTTP são um dos aspectos principais a serem compreendidos sobre o ciclo de vida HTTP. Um usuário realiza uma ação em um navegador web ou cliente HTTP, e eles enviam uma série de cabeçalhos, corpo, URL, etc. para o seu projeto. Você pode capturar esses cabeçalhos (a linguagem do navegador, o tipo de compressão que eles podem lidar, o agente do usuário, etc.) e capturar o corpo e a URL que é enviada para a sua aplicação Flight. Essas requisições são essenciais para que o seu app entenda o que fazer em seguida. ## Uso Básico -PHP tem vários super globais incluindo `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` e `$_COOKIE`. Flight abstrai esses para [Collections](/learn/collections) práticas. Você pode acessar as propriedades `query`, `data`, `cookies` e `files` como arrays ou objetos. +PHP possui várias super globais incluindo `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` e `$_COOKIE`. Flight abstrai essas em coleções práticas [Collections](/learn/collections). Você pode acessar as propriedades `query`, `data`, `cookies` e `files` como arrays ou objetos. -> **Nota:** É **ALTAMENTE** desaconselhado usar esses super globais no seu projeto e eles devem ser referenciados através do objeto `request()`. +> **Nota:** É **ALTAMENTE** desencorajado usar essas super globais no seu projeto e elas devem ser referenciadas através do objeto `request()`. > **Nota:** Não há abstração disponível para `$_ENV`. @@ -68,7 +69,7 @@ Flight::route('GET /login', function(){ }); ``` -Para ajuda em definir novos valores de cookies, veja [overclokk/cookie](/awesome-plugins/php-cookie) +Para ajuda em definir novos valores de cookie, veja [overclokk/cookie](/awesome-plugins/php-cookie) ### `$_SERVER` @@ -96,7 +97,8 @@ Veja [Uploaded File Handler](/learn/uploaded-file) para mais informações. _v3.12.0_ -Você pode processar uploads de arquivos usando o framework com alguns métodos auxiliares. Basicamente, isso se resume a puxar os dados do arquivo da requisição e movê-lo para um novo local. +Você pode processar uploads de arquivos usando o framework com alguns métodos auxiliares. Basicamente, +isso se resume a extrair os dados do arquivo da requisição e movê-lo para um novo local. ```php Flight::route('POST /upload', function(){ @@ -107,7 +109,7 @@ Flight::route('POST /upload', function(){ }); ``` -Se você tiver múltiplos arquivos enviados, você pode iterar através deles: +Se você tiver múltiplos arquivos enviados, você pode iterar por eles: ```php Flight::route('POST /upload', function(){ @@ -119,22 +121,24 @@ Flight::route('POST /upload', function(){ }); ``` -> **Nota de Segurança:** Sempre valide e sanitize a entrada do usuário, especialmente ao lidar com uploads de arquivos. Sempre valide o tipo de extensões que você permitirá serem enviadas, mas você também deve validar os "magic bytes" do arquivo para garantir que é realmente o tipo de arquivo que o usuário afirma ser. Há [artigos](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [e](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [bibliotecas](https://github.com/RikudouSage/MimeTypeDetector) disponíveis para ajudar com isso. +> **Nota de Segurança:** Sempre valide e sanitize a entrada do usuário, especialmente ao lidar com uploads de arquivos. Sempre valide o tipo de extensões que você permitirá ser enviadas, mas você também deve validar os "magic bytes" do arquivo para garantir que é realmente o tipo de arquivo que o usuário afirma ser. Há [artigos](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [e](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [bibliotecas](https://github.com/RikudouSage/MimeTypeDetector) disponíveis para ajudar com isso. ### Corpo da Requisição -Para obter o corpo raw da requisição HTTP, por exemplo ao lidar com requisições POST/PUT, você pode fazer: +Para obter o corpo raw da requisição HTTP, por exemplo ao lidar com requisições POST/PUT, +você pode fazer: ```php Flight::route('POST /users/xml', function(){ $xmlBody = Flight::request()->getBody(); - // fazer algo com o XML que foi enviado. + // faça algo com o XML que foi enviado. }); ``` ### Corpo JSON -Se você receber uma requisição com o tipo de conteúdo `application/json` e os dados de exemplo `{"id": 123}`, ele estará disponível na propriedade `data`: +Se você receber uma requisição com o tipo de conteúdo `application/json` e os dados de exemplo `{"id": 123}` +ele estará disponível da propriedade `data`: ```php $id = Flight::request()->data->id; @@ -166,9 +170,10 @@ $method = Flight::request()->method; // na verdade populado pelo getMethod() $method = Flight::request()->getMethod(); ``` -**Nota:** O método `getMethod()` primeiro puxa o método de `$_SERVER['REQUEST_METHOD']`, então ele pode ser sobrescrito por `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` se existir ou `$_REQUEST['_method']` se existir. +**Nota:** O método `getMethod()` primeiro puxa o método de `$_SERVER['REQUEST_METHOD']`, então ele pode ser sobrescrito +por `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` se existir ou `$_REQUEST['_method']` se existir. -## Propriedades do Objeto Requisição +## Propriedades do Objeto de Requisição O objeto de requisição fornece as seguintes propriedades: @@ -184,18 +189,18 @@ O objeto de requisição fornece as seguintes propriedades: - **type** - O tipo de conteúdo - **length** - O comprimento do conteúdo - **query** - Parâmetros da string de consulta -- **data** - Dados de post ou dados JSON -- **cookies** - Dados de cookies +- **data** - Dados post ou dados JSON +- **cookies** - Dados de cookie - **files** - Arquivos enviados - **secure** - Se a conexão é segura -- **accept** - Parâmetros HTTP accept -- **proxy_ip** - Endereço IP proxy do cliente. Varre o array `$_SERVER` por `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` nessa ordem. +- **accept** - Parâmetros de aceitação HTTP +- **proxy_ip** - Endereço IP proxy do cliente. Escaneia o array `$_SERVER` por `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` nessa ordem. - **host** - O nome do host da requisição - **servername** - O SERVER_NAME de `$_SERVER` -## Métodos Auxiliares de URL +## Métodos Auxiliares -Há alguns métodos auxiliares para montar partes de uma URL para sua conveniência. +Há alguns métodos auxiliares para montar partes de uma URL ou lidar com certos cabeçalhos. ### URL Completa @@ -205,6 +210,7 @@ Você pode acessar a URL completa da requisição usando o método `getFullUrl() $url = Flight::request()->getFullUrl(); // https://example.com/some/path?foo=bar ``` + ### URL Base Você pode acessar a URL base usando o método `getBaseUrl()`: @@ -225,6 +231,29 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` +## Negociar Tipos de Aceitação de Conteúdo + +_v3.17.2_ + +Você pode usar o método `negotiateContentType()` para determinar o melhor tipo de conteúdo para responder com base no cabeçalho `Accept` enviado pelo cliente. + +```php + +// Exemplo de cabeçalho Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// O abaixo define o que você suporta. +$availableTypes = ['application/json', 'application/xml']; +$typeToServe = Flight::request()->negotiateContentType($availableTypes); +if ($typeToServe === 'application/json') { + // Servir resposta JSON +} elseif ($typeToServe === 'application/xml') { + // Servir resposta XML +} else { + // Padrão para algo mais ou lançar um erro +} +``` + +> **Nota:** Se nenhum dos tipos disponíveis for encontrado no cabeçalho `Accept`, o método retornará `null`. Se não houver cabeçalho `Accept` definido, o método retornará o primeiro tipo no array `$availableTypes`. + ## Veja Também - [Routing](/learn/routing) - Veja como mapear rotas para controladores e renderizar views. - [Responses](/learn/responses) - Como personalizar respostas HTTP. @@ -236,5 +265,6 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); - `request()->ip` e `request()->proxy_ip` podem ser diferentes se o seu servidor web estiver atrás de um proxy, balanceador de carga, etc. ## Changelog +- v3.17.2 - Adicionado negotiateContentType() - v3.12.0 - Adicionada capacidade de lidar com uploads de arquivos através do objeto de requisição. - v1.0 - Lançamento inicial. \ No newline at end of file diff --git a/content/v3/pt/learn/responses.md b/content/v3/pt/learn/responses.md index 36d826d3..4486515f 100644 --- a/content/v3/pt/learn/responses.md +++ b/content/v3/pt/learn/responses.md @@ -2,17 +2,17 @@ ## Visão Geral -Flight ajuda a gerar parte dos cabeçalhos de resposta para você, mas você tem a maior parte do controle sobre o que envia de volta ao usuário. Na maioria das vezes, você acessará o objeto `response()` diretamente, mas Flight tem alguns métodos auxiliares para definir alguns dos cabeçalhos de resposta para você. +Flight ajuda a gerar parte dos cabeçalhos de resposta para você, mas você mantém a maior parte do controle sobre o que envia de volta ao usuário. Na maioria das vezes, você acessará o objeto `response()` diretamente, mas Flight tem alguns métodos auxiliares para definir alguns dos cabeçalhos de resposta para você. ## Entendendo -Após o usuário enviar sua [request](/learn/requests) para sua aplicação, você precisa gerar uma resposta apropriada para eles. Eles enviaram informações como a linguagem que preferem, se podem lidar com certos tipos de compressão, seu agente de usuário, etc., e após processar tudo, é hora de enviar de volta uma resposta apropriada. Isso pode ser definindo cabeçalhos, exibindo um corpo de HTML ou JSON para eles, ou redirecionando para uma página. +Após o usuário enviar sua [request](/learn/requests) para sua aplicação, você precisa gerar uma resposta apropriada para eles. Eles enviaram informações como a linguagem que preferem, se podem lidar com certos tipos de compressão, seu agente de usuário, etc., e após processar tudo, é hora de enviar de volta uma resposta apropriada. Isso pode ser definir cabeçalhos, produzir um corpo de HTML ou JSON para eles, ou redirecioná-los para uma página. ## Uso Básico ### Enviando um Corpo de Resposta -Flight usa `ob_start()` para bufferizar a saída. Isso significa que você pode usar `echo` ou `print` para enviar uma resposta ao usuário e Flight a capturará e enviará de volta ao usuário com os cabeçalhos apropriados. +Flight usa `ob_start()` para armazenar em buffer a saída. Isso significa que você pode usar `echo` ou `print` para enviar uma resposta ao usuário e Flight a capturará e a enviará de volta ao usuário com os cabeçalhos apropriados. ```php @@ -49,12 +49,12 @@ passa alguns dados para serem codificados em JSON: ```php Flight::route('/@companyId/users', function(int $companyId) { - // de alguma forma, puxe seus usuários de um banco de dados, por exemplo + // de alguma forma, extraia seus usuários de um banco de dados, por exemplo $users = Flight::db()->fetchAll("SELECT id, first_name, last_name FROM users WHERE company_id = ?", [ $companyId ]); Flight::json($users); }); -// [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* mais usuários */ ] +// [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* more users */ ] ``` > **Nota:** Por padrão, Flight enviará um cabeçalho `Content-Type: application/json` com a resposta. Ele também usará as flags `JSON_THROW_ON_ERROR` e `JSON_UNESCAPED_SLASHES` ao codificar o JSON. @@ -77,8 +77,8 @@ Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT); #### Alterando a Ordem dos Argumentos JSON -`Flight::json()` é um método muito legado, mas o objetivo do Flight é manter a compatibilidade com versões anteriores -para projetos. Na verdade, é muito simples se você quiser redefinir a ordem dos argumentos para usar uma sintaxe mais simples, +`Flight::json()` é um método muito antigo, mas o objetivo do Flight é manter a compatibilidade retroativa +para projetos. Na verdade, é muito simples se você quiser refazer a ordem dos argumentos para usar uma sintaxe mais simples, você pode apenas remapear o método JSON [como qualquer outro método do Flight](/learn/extending): ```php @@ -97,20 +97,20 @@ Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT); _v3.10.0_ Se você quiser enviar uma resposta JSON e parar a execução, você pode usar o método `jsonHalt()`. -Isso é útil para casos em que você está verificando algum tipo de autorização e se +Isso é útil para casos em que você está verificando talvez algum tipo de autorização e se o usuário não estiver autorizado, você pode enviar uma resposta JSON imediatamente, limpar o conteúdo do corpo existente e parar a execução. ```php Flight::route('/users', function() { $authorized = someAuthorizationCheck(); - // Verifique se o usuário está autorizado + // Verifica se o usuário está autorizado if($authorized === false) { Flight::jsonHalt(['error' => 'Unauthorized'], 401); // sem exit; necessário aqui. } - // Continue com o resto da rota + // Continua com o resto da rota }); ``` @@ -119,12 +119,12 @@ Antes da v3.10.0, você teria que fazer algo assim: ```php Flight::route('/users', function() { $authorized = someAuthorizationCheck(); - // Verifique se o usuário está autorizado + // Verifica se o usuário está autorizado if($authorized === false) { Flight::halt(401, json_encode(['error' => 'Unauthorized'])); } - // Continue com o resto da rota + // Continua com o resto da rota }); ``` @@ -142,7 +142,7 @@ Flight::route('/', function() { }); ``` -O caso de uso acima provavelmente não é comum, no entanto, poderia ser mais comum se usado em um [middleware](/learn/middleware). +O caso de uso acima provavelmente não é comum, no entanto, poderia ser mais comum se isso fosse usado em um [middleware](/learn/middleware). ### Executando um Callback no Corpo da Resposta @@ -155,7 +155,7 @@ Flight::route('/users', function() { Flight::render('users_table', ['users' => $users]); }); -// Isso fará gzip de todas as respostas para qualquer rota +// Isso fará gzip em todas as respostas para qualquer rota Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); @@ -163,7 +163,7 @@ Flight::response()->addResponseBodyCallback(function($body) { Você pode adicionar múltiplos callbacks e eles serão executados na ordem em que foram adicionados. Como isso pode aceitar qualquer [callable](https://www.php.net/manual/en/language.types.callable.php), pode aceitar um array de classe `[ $class, 'method' ]`, uma closure `$strReplace = function($body) { str_replace('hi', 'there', $body); };`, ou um nome de função `'minify'` se você tivesse uma função para minificar seu código HTML, por exemplo. -**Nota:** Os callbacks de rota não funcionarão se você estiver usando a opção de configuração `flight.v2.output_buffering`. +**Nota:** Callbacks de rota não funcionarão se você estiver usando a opção de configuração `flight.v2.output_buffering`. #### Callback de Rota Específica @@ -175,7 +175,7 @@ Flight::route('/users', function() { $users = $db->fetchAll("SELECT * FROM users"); Flight::render('users_table', ['users' => $users]); - // Isso fará gzip apenas da resposta desta rota + // Isso fará gzip apenas na resposta desta rota Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); @@ -289,13 +289,13 @@ Flight::halt(200, 'Be right back...'); ``` Chamar `halt` descartará qualquer conteúdo de resposta até aquele ponto e parará toda a execução. -Se você quiser parar o framework e exibir a resposta atual, use o método `stop`: +Se você quiser parar o framework e produzir a resposta atual, use o método `stop`: ```php Flight::stop($httpStatusCode = null); ``` -> **Nota:** `Flight::stop()` tem um comportamento estranho, como exibir a resposta, mas continuar executando seu script, o que pode não ser o que você deseja. Você pode usar `exit` ou `return` após chamar `Flight::stop()` para evitar execução adicional, mas geralmente é recomendado usar `Flight::halt()`. +> **Nota:** `Flight::stop()` tem algum comportamento estranho, como produzir a resposta, mas continuar executando seu script, o que pode não ser o que você deseja. Você pode usar `exit` ou `return` após chamar `Flight::stop()` para prevenir execução adicional, mas geralmente é recomendado usar `Flight::halt()`. Isso salvará a chave e o valor do cabeçalho no objeto de resposta. No final do ciclo de vida da solicitação, ele construirá os cabeçalhos e enviará uma resposta. @@ -334,12 +334,12 @@ my_func({"id":123}); Se você não passar um nome de parâmetro de consulta, ele usará `jsonp` por padrão. -> **Nota:** Se você ainda estiver usando solicitações JSONP em 2025 e além, entre no chat e nos diga por quê! Adoramos ouvir boas histórias de batalha/horror! +> **Nota:** Se você ainda estiver usando solicitações JSONP em 2025 e além, entre no chat e nos diga por quê! Adoramos ouvir algumas boas histórias de batalha/horror! ### Limpando Dados de Resposta -Você pode limpar o corpo da resposta e os cabeçalhos usando o método `clear()`. Isso limpará -qualquer cabeçalho atribuído à resposta, limpará o corpo da resposta e definirá o código de status como `200`. +Você pode limpar o corpo da resposta e cabeçalhos usando o método `clear()`. Isso limpará +quaisquer cabeçalhos atribuídos à resposta, limpará o corpo da resposta e definirá o código de status para `200`. ```php Flight::response()->clear(); @@ -347,10 +347,11 @@ Flight::response()->clear(); #### Limpando Apenas o Corpo da Resposta -Se você quiser apenas limpar o corpo da resposta, pode usar o método `clearBody()`: +Se você quiser limpar apenas o corpo da resposta, pode usar o método `clearBody()`: ```php // Isso ainda manterá quaisquer cabeçalhos definidos no objeto response(). +// Isso ainda manterá quaisquer cabeçalhos definidos no objeto response(). Flight::response()->clearBody(); ``` @@ -362,11 +363,11 @@ cliente solicitar o mesmo recurso, eles serão solicitados a usar sua versão em #### Cache no Nível de Rota -Se você quiser cachear toda a sua resposta, pode usar o método `cache()` e passar o tempo para cachear. +Se você quiser armazenar em cache toda a sua resposta, pode usar o método `cache()` e passar o tempo para cache. ```php -// Isso cacheará a resposta por 5 minutos +// Isso armazenará em cache a resposta por 5 minutos Flight::route('/news', function () { Flight::response()->cache(time() + 300); echo 'This content will be cached.'; @@ -383,8 +384,8 @@ Flight::route('/news', function () { ### Last-Modified Você pode usar o método `lastModified` e passar um timestamp UNIX para definir a data -e hora em que uma página foi modificada pela última vez. O cliente continuará a usar seu cache até -que o valor de última modificação seja alterado. +e hora em que uma página foi modificada pela última vez. O cliente continuará usando seu cache até +que o valor da última modificação seja alterado. ```php Flight::route('/news', function () { @@ -413,11 +414,13 @@ uma resposta `HTTP 304` e parará o processamento. _v3.12.0_ -Há um método auxiliar para transmitir um arquivo para o usuário final. Você pode usar o método `download` e passar o caminho. +Há um método auxiliar para transmitir um arquivo ao usuário final. Você pode usar o método `download` e passar o caminho. ```php Flight::route('/download', function () { Flight::download('/path/to/file.txt'); + // A partir da v3.17.1, você pode especificar um nome de arquivo personalizado para o download + Flight::download('/path/to/file.txt', 'custom_name.txt'); }); ``` @@ -425,14 +428,15 @@ Flight::route('/download', function () { - [Routing](/learn/routing) - Como mapear rotas para controladores e renderizar visualizações. - [Requests](/learn/requests) - Entendendo como lidar com solicitações de entrada. - [Middleware](/learn/middleware) - Usando middleware com rotas para autenticação, logging, etc. -- [Why a Framework?](/learn/why-frameworks) - Entendendo os benefícios de usar um framework como Flight. +- [Por que um Framework?](/learn/why-frameworks) - Entendendo os benefícios de usar um framework como Flight. - [Extending](/learn/extending) - Como estender Flight com sua própria funcionalidade. ## Solução de Problemas -- Se você estiver com problemas com redirecionamentos não funcionando, certifique-se de adicionar um `return;` ao método. +- Se você estiver tendo problemas com redirecionamentos não funcionando, certifique-se de adicionar um `return;` ao método. - `stop()` e `halt()` não são a mesma coisa. `halt()` parará a execução imediatamente, enquanto `stop()` permitirá que a execução continue. ## Changelog +- v3.17.1 - Adicionado `$fileName` ao método `downloadFile()`. - v3.12.0 - Adicionado método auxiliar downloadFile. - v3.10.0 - Adicionado `jsonHalt`. - v1.0 - Lançamento inicial. \ No newline at end of file diff --git a/content/v3/pt/learn/routing.md b/content/v3/pt/learn/routing.md index 59926faf..b9adda56 100644 --- a/content/v3/pt/learn/routing.md +++ b/content/v3/pt/learn/routing.md @@ -1,17 +1,17 @@ # Roteamento ## Visão Geral -O roteamento no Flight PHP mapeia padrões de URL para funções de callback ou métodos de classe, permitindo o tratamento rápido e simples de requisições. Ele é projetado para overhead mínimo, uso amigável para iniciantes e extensibilidade sem dependências externas. +O roteamento no Flight PHP mapeia padrões de URL para funções de callback ou métodos de classe, permitindo o tratamento rápido e simples de requisições. Ele é projetado para sobrecarga mínima, uso amigável para iniciantes e extensibilidade sem dependências externas. ## Entendendo -O roteamento é o mecanismo central que conecta requisições HTTP à lógica da sua aplicação no Flight. Ao definir rotas, você especifica como diferentes URLs acionam código específico, seja através de funções, métodos de classe ou ações de controlador. O sistema de roteamento do Flight é flexível, suportando padrões básicos, parâmetros nomeados, expressões regulares e recursos avançados como injeção de dependência e roteamento de recursos. Essa abordagem mantém seu código organizado e fácil de manter, enquanto permanece rápido e simples para iniciantes e extensível para usuários avançados. +O roteamento é o mecanismo central que conecta requisições HTTP à lógica da sua aplicação no Flight. Ao definir rotas, você especifica como diferentes URLs acionam código específico, seja através de funções, métodos de classe ou ações de controlador. O sistema de roteamento do Flight é flexível, suportando padrões básicos, parâmetros nomeados, expressões regulares e recursos avançados como injeção de dependência e roteamento resource-oriented. Essa abordagem mantém seu código organizado e fácil de manter, enquanto permanece rápido e simples para iniciantes e extensível para usuários avançados. -> **Nota:** Quer entender mais sobre roteamento? Confira a página ["por que um framework?](/learn/why-frameworks)" para uma explicação mais aprofundada. +> **Nota:** Quer entender mais sobre roteamento? Confira a página ["por que um framework?](/learn/why-frameworks) para uma explicação mais aprofundada. ## Uso Básico ### Definindo uma Rota Simples -O roteamento básico no Flight é feito combinando um padrão de URL com uma função de callback ou um array de classe e método. +O roteamento básico no Flight é feito ao combinar um padrão de URL com uma função de callback ou um array de uma classe e método. ```php Flight::route('/', function(){ @@ -22,7 +22,7 @@ Flight::route('/', function(){ > As rotas são combinadas na ordem em que são definidas. A primeira rota que combinar com uma requisição será invocada. ### Usando Funções como Callbacks -O callback pode ser qualquer objeto que seja chamável. Então você pode usar uma função regular: +O callback pode ser qualquer objeto que seja chamável. Então, você pode usar uma função regular: ```php function hello() { @@ -92,8 +92,8 @@ Flight::route('POST /', function () { echo 'I received a POST request.'; }); -// Você não pode usar Flight::get() para rotas, pois esse é um método -// para obter variáveis, não para criar uma rota. +// You cannot use Flight::get() for routes as that is a method +// to get variables, not create a route. Flight::post('/', function() { /* code */ }); Flight::patch('/', function() { /* code */ }); Flight::put('/', function() { /* code */ }); @@ -108,6 +108,38 @@ Flight::route('GET|POST /', function () { }); ``` +### Tratamento Especial para Requisições HEAD e OPTIONS + +O Flight fornece tratamento integrado para requisições HTTP `HEAD` e `OPTIONS`: + +#### Requisições HEAD + +- **Requisições HEAD** são tratadas exatamente como requisições `GET`, mas o Flight remove automaticamente o corpo da resposta antes de enviá-lo ao cliente. +- Isso significa que você pode definir uma rota para `GET`, e requisições HEAD para a mesma URL retornarão apenas cabeçalhos (sem conteúdo), conforme esperado pelos padrões HTTP. + +```php +Flight::route('GET /info', function() { + echo 'This is some info!'; +}); +// A HEAD request to /info will return the same headers, but no body. +``` + +#### Requisições OPTIONS + +Requisições `OPTIONS` são tratadas automaticamente pelo Flight para qualquer rota definida. +- Quando uma requisição OPTIONS é recebida, o Flight responde com um status `204 No Content` e um cabeçalho `Allow` listando todos os métodos HTTP suportados para essa rota. +- Você não precisa definir uma rota separada para OPTIONS, a menos que queira um comportamento personalizado ou modificar a resposta. + +```php +// For a route defined as: +Flight::route('GET|POST /users', function() { /* ... */ }); + +// An OPTIONS request to /users will respond with: +// +// Status: 204 No Content +// Allow: GET, POST, HEAD, OPTIONS +``` + ### Usando o Objeto Router Adicionalmente, você pode obter o objeto Router, que tem alguns métodos auxiliares para você usar: @@ -116,12 +148,12 @@ Adicionalmente, você pode obter o objeto Router, que tem alguns métodos auxili $router = Flight::router(); -// mapeia todos os métodos assim como Flight::route() +// maps all methods just like Flight::route() $router->map('/', function() { echo 'hello world!'; }); -// Requisição GET +// GET request $router->get('/users', function() { echo 'users'; }); @@ -136,14 +168,14 @@ Você pode usar expressões regulares em suas rotas: ```php Flight::route('/user/[0-9]+', function () { - // Isso combinará com /user/1234 + // This will match /user/1234 }); ``` Embora esse método esteja disponível, é recomendado usar parâmetros nomeados, ou parâmetros nomeados com expressões regulares, pois eles são mais legíveis e fáceis de manter. ### Parâmetros Nomeados -Você pode especificar parâmetros nomeados em suas rotas, que serão passados para a função de callback. **Isso é mais para legibilidade da rota do que qualquer outra coisa. Por favor, veja a seção abaixo sobre uma ressalva importante.** +Você pode especificar parâmetros nomeados em suas rotas, que serão passados para sua função de callback. **Isso é mais para a legibilidade da rota do que qualquer outra coisa. Por favor, veja a seção abaixo sobre uma ressalva importante.** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -155,8 +187,8 @@ Você também pode incluir expressões regulares com seus parâmetros nomeados u ```php Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { - // Isso combinará com /bob/123 - // Mas não combinará com /bob/12345 + // This will match /bob/123 + // But will not match /bob/12345 }); ``` @@ -164,7 +196,7 @@ Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { #### Ressalva Importante -Embora no exemplo acima pareça que `@name` está diretamente ligado à variável `$name`, não é. A ordem dos parâmetros na função de callback é o que determina o que é passado para ela. Se você trocar a ordem dos parâmetros na função de callback, as variáveis também serão trocadas. Aqui está um exemplo: +Embora no exemplo acima pareça que `@name` está diretamente ligado à variável `$name`, não é assim. A ordem dos parâmetros na função de callback é o que determina o que é passado para ela. Se você inverter a ordem dos parâmetros na função de callback, as variáveis também serão invertidas. Aqui está um exemplo: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -182,7 +214,7 @@ Você pode especificar parâmetros nomeados que são opcionais para combinação Flight::route( '/blog(/@year(/@month(/@day)))', function(?string $year, ?string $month, ?string $day) { - // Isso combinará com as seguintes URLs: + // This will match the following URLS: // /blog/2012/12/10 // /blog/2012/12 // /blog/2012 @@ -193,12 +225,12 @@ Flight::route( Quaisquer parâmetros opcionais que não forem combinados serão passados como `NULL`. -### Roteamento de Curinga -A combinação é feita apenas em segmentos individuais de URL. Se você quiser combinar múltiplos segmentos, pode usar o curinga `*`. +### Roteamento Wildcard +A combinação é feita apenas em segmentos individuais de URL. Se você quiser combinar múltiplos segmentos, pode usar o wildcard `*`. ```php Flight::route('/blog/*', function () { - // Isso combinará com /blog/2000/02/01 + // This will match /blog/2000/02/01 }); ``` @@ -206,23 +238,23 @@ Para rotear todas as requisições para um único callback, você pode fazer: ```php Flight::route('*', function () { - // Faça algo + // Do something }); ``` ### Manipulador de 404 Não Encontrado Por padrão, se uma URL não puder ser encontrada, o Flight enviará uma resposta `HTTP 404 Not Found` que é muito simples e simples. -Se você quiser ter uma resposta 404 mais personalizada, você pode [mapear](/learn/extending) seu próprio método `notFound`: +Se você quiser uma resposta 404 mais personalizada, pode [mapear](/learn/extending) seu próprio método `notFound`: ```php Flight::map('notFound', function() { $url = Flight::request()->url; - // Você também poderia usar Flight::render() com um template personalizado. + // You could also use Flight::render() with a custom template. $output = <<Meu 404 Não Encontrado Personalizado -

A página que você solicitou {$url} não pôde ser encontrada.

+

My Custom 404 Not Found

+

The page you have requested {$url} could not be found.

HTML; $this->response() @@ -233,10 +265,39 @@ Flight::map('notFound', function() { }); ``` +### Manipulador de Método Não Encontrado + +Por padrão, se uma URL for encontrada, mas o método não for permitido, o Flight enviará uma resposta `HTTP 405 Method Not Allowed` que é muito simples e simples (Ex: Method Not Allowed. Allowed Methods are: GET, POST). Ele também incluirá um cabeçalho `Allow` com os métodos permitidos para essa URL. + +Se você quiser uma resposta 405 mais personalizada, pode [mapear](/learn/extending) seu próprio método `methodNotFound`: + +```php +use flight\net\Route; + +Flight::map('methodNotFound', function(Route $route) { + $url = Flight::request()->url; + $methods = implode(', ', $route->methods); + + // You could also use Flight::render() with a custom template. + $output = <<My Custom 405 Method Not Allowed +

The method you have requested for {$url} is not allowed.

+

Allowed Methods are: {$methods}

+ HTML; + + $this->response() + ->clearBody() + ->status(405) + ->setHeader('Allow', $methods) + ->write($output) + ->send(); +}); +``` + ## Uso Avançado ### Injeção de Dependência em Rotas -Se você quiser usar injeção de dependência via um contêiner (PSR-11, PHP-DI, Dice, etc), o único tipo de rotas onde isso está disponível é criando o objeto diretamente você mesmo e usando o contêiner para criar seu objeto ou você pode usar strings para definir a classe e o método a chamar. Você pode ir à página [Injeção de Dependência](/learn/dependency-injection-container) para mais informações. +Se você quiser usar injeção de dependência via um contêiner (PSR-11, PHP-DI, Dice, etc), o único tipo de rotas onde isso está disponível é criando o objeto diretamente você mesmo e usando o contêiner para criar seu objeto, ou você pode usar strings para definir a classe e o método a chamar. Você pode ir à página [Injeção de Dependência](/learn/dependency-injection-container) para mais informações. Aqui está um exemplo rápido: @@ -253,7 +314,7 @@ class Greeting } public function hello(int $id) { - // faça algo com $this->pdoWrapper + // do something with $this->pdoWrapper $name = $this->pdoWrapper->fetchField("SELECT name FROM users WHERE id = ?", [ $id ]); echo "Hello, world! My name is {$name}!"; } @@ -261,11 +322,11 @@ class Greeting // index.php -// Configure o contêiner com os parâmetros que você precisar -// Veja a página de Injeção de Dependência para mais informações sobre PSR-11 +// Setup the container with whatever params you need +// See the Dependency Injection page for more information on PSR-11 $dice = new \Dice\Dice(); -// Não esqueça de reatribuir a variável com '$dice = '!!!!! +// Don't forget to reassign the variable with '$dice = '!!!!! $dice = $dice->addRule('flight\database\PdoWrapper', [ 'shared' => true, 'constructParams' => [ @@ -275,72 +336,72 @@ $dice = $dice->addRule('flight\database\PdoWrapper', [ ] ]); -// Registre o manipulador de contêiner +// Register the container handler Flight::registerContainerHandler(function($class, $params) use ($dice) { return $dice->create($class, $params); }); -// Rotas como normal +// Routes like normal Flight::route('/hello/@id', [ 'Greeting', 'hello' ]); -// ou +// or Flight::route('/hello/@id', 'Greeting->hello'); -// ou +// or Flight::route('/hello/@id', 'Greeting::hello'); Flight::start(); ``` ### Passando Execução para a Próxima Rota -Depreciado -Você pode passar a execução para a próxima rota combinada retornando `true` da sua função de callback. +Deprecated +Você pode passar a execução para a próxima rota que combine retornando `true` da sua função de callback. ```php Flight::route('/user/@name', function (string $name) { - // Verifique alguma condição + // Check some condition if ($name !== "Bob") { - // Continue para a próxima rota + // Continue to next route return true; } }); Flight::route('/user/*', function () { - // Isso será chamado + // This will get called }); ``` Agora é recomendado usar [middleware](/learn/middleware) para lidar com casos de uso complexos como este. -### Alias de Rota -Ao atribuir um alias a uma rota, você pode chamar esse alias dinamicamente na sua aplicação para ser gerado mais tarde no seu código (ex: um link em um template HTML, ou gerando uma URL de redirecionamento). +### Apelidos de Rota +Ao atribuir um apelido a uma rota, você pode chamar esse apelido dinamicamente em sua aplicação para ser gerado mais tarde no seu código (ex: um link em um template HTML, ou gerando uma URL de redirecionamento). ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); -// ou +// or Flight::route('/users/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view'); -// mais tarde no código em algum lugar +// later in code somewhere class UserController { public function update() { - // código para salvar o usuário... - $id = $user['id']; // 5 por exemplo + // code to save user... + $id = $user['id']; // 5 for example - $redirectUrl = Flight::getUrl('user_view', [ 'id' => $id ]); // retornará '/users/5' + $redirectUrl = Flight::getUrl('user_view', [ 'id' => $id ]); // will return '/users/5' Flight::redirect($redirectUrl); } } ``` -Isso é especialmente útil se a sua URL acontecer de mudar. No exemplo acima, digamos que users foi movido para `/admin/users/@id` em vez disso. -Com o alias no lugar para a rota, você não precisa mais encontrar todas as URLs antigas no seu código e alterá-las porque o alias agora retornará `/admin/users/5` como no exemplo acima. +Isso é especialmente útil se sua URL acontecer de mudar. No exemplo acima, digamos que users foi movido para `/admin/users/@id` em vez disso. +Com apelidos em vigor para a rota, você não precisa mais encontrar todas as URLs antigas no seu código e alterá-las porque o apelido agora retornará `/admin/users/5` como no exemplo acima. -O alias de rota ainda funciona em grupos também: +Apelidos de rota ainda funcionam em grupos também: ```php Flight::group('/users', function() { Flight::route('/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); - // ou + // or Flight::route('/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view'); }); ``` @@ -348,77 +409,77 @@ Flight::group('/users', function() { ### Inspecionando Informações de Rota Se você quiser inspecionar as informações da rota combinada, há 2 maneiras de fazer isso: -1. Você pode usar a propriedade `executedRoute` no objeto `Flight::router()`. -2. Você pode solicitar que o objeto de rota seja passado para o seu callback passando `true` como o terceiro parâmetro no método de rota. O objeto de rota sempre será o último parâmetro passado para a sua função de callback. +1. Você pode usar uma propriedade `executedRoute` no objeto `Flight::router()`. +2. Você pode solicitar que o objeto da rota seja passado para seu callback passando `true` como o terceiro parâmetro no método de rota. O objeto da rota sempre será o último parâmetro passado para sua função de callback. #### `executedRoute` ```php Flight::route('/', function() { $route = Flight::router()->executedRoute; - // Faça algo com $route - // Array de métodos HTTP combinados + // Do something with $route + // Array of HTTP methods matched against $route->methods; - // Array de parâmetros nomeados + // Array of named parameters $route->params; - // Expressão regular combinada + // Matching regular expression $route->regex; - // Contém o conteúdo de qualquer '*' usado no padrão de URL + // Contains the contents of any '*' used in the URL pattern $route->splat; - // Mostra o caminho da url....se você realmente precisar + // Shows the url path....if you really need it $route->pattern; - // Mostra o middleware atribuído a isso + // Shows what middleware is assigned to this $route->middleware; - // Mostra o alias atribuído a esta rota + // Shows the alias assigned to this route $route->alias; }); ``` -> **Nota:** A propriedade `executedRoute` só será definida após uma rota ter sido executada. Se você tentar acessá-la antes de uma rota ter sido executada, ela será `NULL`. Você também pode usar executedRoute em [middleware](/learn/middleware)! +> **Nota:** A propriedade `executedRoute` só será definida após uma rota ter sido executada. Se você tentar acessá-la antes de uma rota ter sido executada, ela será `NULL`. Você também pode usar executedRoute em [middleware](/learn/middleware) também! -#### Passando `true` na definição de rota +#### Passar `true` na definição de rota ```php Flight::route('/', function(\flight\net\Route $route) { - // Array de métodos HTTP combinados + // Array of HTTP methods matched against $route->methods; - // Array de parâmetros nomeados + // Array of named parameters $route->params; - // Expressão regular combinada + // Matching regular expression $route->regex; - // Contém o conteúdo de qualquer '*' usado no padrão de URL + // Contains the contents of any '*' used in the URL pattern $route->splat; - // Mostra o caminho da url....se você realmente precisar + // Shows the url path....if you really need it $route->pattern; - // Mostra o middleware atribuído a isso + // Shows what middleware is assigned to this $route->middleware; - // Mostra o alias atribuído a esta rota + // Shows the alias assigned to this route $route->alias; -}, true);// <-- Este parâmetro true é o que faz isso acontecer +}, true);// <-- This true parameter is what makes that happen ``` ### Agrupamento de Rotas e Middleware -Pode haver vezes em que você queira agrupar rotas relacionadas juntas (como `/api/v1`). +Pode haver momentos em que você queira agrupar rotas relacionadas juntas (como `/api/v1`). Você pode fazer isso usando o método `group`: ```php Flight::group('/api/v1', function () { Flight::route('/users', function () { - // Combina com /api/v1/users + // Matches /api/v1/users }); Flight::route('/posts', function () { - // Combina com /api/v1/posts + // Matches /api/v1/posts }); }); ``` @@ -428,24 +489,24 @@ Você pode até aninhar grupos de grupos: ```php Flight::group('/api', function () { Flight::group('/v1', function () { - // Flight::get() obtém variáveis, não define uma rota! Veja o contexto de objeto abaixo + // Flight::get() gets variables, it doesn't set a route! See object context below Flight::route('GET /users', function () { - // Combina com GET /api/v1/users + // Matches GET /api/v1/users }); Flight::post('/posts', function () { - // Combina com POST /api/v1/posts + // Matches POST /api/v1/posts }); Flight::put('/posts/1', function () { - // Combina com PUT /api/v1/posts + // Matches PUT /api/v1/posts }); }); Flight::group('/v2', function () { - // Flight::get() obtém variáveis, não define uma rota! Veja o contexto de objeto abaixo + // Flight::get() gets variables, it doesn't set a route! See object context below Flight::route('GET /users', function () { - // Combina com GET /api/v2/users + // Matches GET /api/v2/users }); }); }); @@ -460,13 +521,13 @@ $app = Flight::app(); $app->group('/api/v1', function (Router $router) { - // use a variável $router + // user the $router variable $router->get('/users', function () { - // Combina com GET /api/v1/users + // Matches GET /api/v1/users }); $router->post('/posts', function () { - // Combina com POST /api/v1/posts + // Matches POST /api/v1/posts }); }); ``` @@ -480,9 +541,9 @@ Você também pode atribuir middleware a um grupo de rotas: ```php Flight::group('/api/v1', function () { Flight::route('/users', function () { - // Combina com /api/v1/users + // Matches /api/v1/users }); -}, [ MyAuthMiddleware::class ]); // ou [ new MyAuthMiddleware() ] se você quiser usar uma instância +}, [ MyAuthMiddleware::class ]); // or [ new MyAuthMiddleware() ] if you want to use an instance ``` Veja mais detalhes na página [middleware de grupo](/learn/middleware#grouping-middleware). @@ -510,7 +571,7 @@ E o que acontecerá em segundo plano é que ele criará as seguintes rotas: ] ``` -E o seu controlador usará os seguintes métodos: +E seu controlador usará os seguintes métodos: ```php class UsersController @@ -551,10 +612,10 @@ class UsersController Há algumas opções para configurar as rotas de recursos. -##### Base de Alias +##### Base de Apelido -Você pode configurar o `aliasBase`. Por padrão, o alias é a última parte da URL especificada. -Por exemplo, `/users/` resultaria em um `aliasBase` de `users`. Quando essas rotas são criadas, os aliases são `users.index`, `users.create`, etc. Se você quiser alterar o alias, defina o `aliasBase` para o valor que deseja. +Você pode configurar o `aliasBase`. Por padrão, o apelido é a última parte da URL especificada. +Por exemplo, `/users/` resultaria em um `aliasBase` de `users`. Quando essas rotas são criadas, os apelidos são `users.index`, `users.create`, etc. Se você quiser alterar o apelido, defina o `aliasBase` para o valor que deseja. ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); @@ -565,16 +626,16 @@ Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); Você também pode especificar quais rotas deseja criar usando as opções `only` e `except`. ```php -// Lista branca apenas desses métodos e lista negra do resto +// Whitelist only these methods and blacklist the rest Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' ] ]); ``` ```php -// Lista negra apenas desses métodos e lista branca do resto +// Blacklist only these methods and whitelist the rest Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` -Essas são basicamente opções de lista branca e lista negra para que você possa especificar quais rotas deseja criar. +Essas são basicamente opções de whitelisting e blacklisting para que você possa especificar quais rotas deseja criar. ##### Middleware @@ -586,9 +647,9 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid ### Respostas em Streaming -Você agora pode transmitir respostas para o cliente usando `stream()` ou `streamWithHeaders()`. +Agora você pode transmitir respostas para o cliente usando `stream()` ou `streamWithHeaders()`. Isso é útil para enviar arquivos grandes, processos de longa duração ou gerar respostas grandes. -Transmitir uma rota é tratado um pouco diferente de uma rota regular. +Transmitir uma rota é tratada um pouco diferente de uma rota regular. > **Nota:** Respostas em streaming só estão disponíveis se você tiver [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) definido como `false`. @@ -603,15 +664,15 @@ Flight::route('/@filename', function($filename) { $response = Flight::response(); - // obviamente você sanitizaria o caminho e o que mais. + // obviously you would sanitize the path and whatnot. $fileNameSafe = basename($filename); - // Se você tiver cabeçalhos adicionais para definir aqui após a rota ter sido executada - // você deve defini-los antes de qualquer coisa ser ecoada. - // Eles devem ser todos uma chamada crua para a função header() ou - // uma chamada para Flight::response()->setRealHeader() + // If you have additional headers to set here after the route has executed + // you must define them before anything is echoed out. + // They must all be a raw call to the header() function or + // a call to Flight::response()->setRealHeader() header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); - // ou + // or $response->setRealHeader('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); $filePath = '/some/path/to/files/'.$fileNameSafe; @@ -620,15 +681,15 @@ Flight::route('/@filename', function($filename) { Flight::halt(404, 'File not found'); } - // defina manualmente o comprimento do conteúdo se quiser + // manually set the content length if you'd like header('Content-Length: '.filesize($filePath)); - // ou + // or $response->setRealHeader('Content-Length: '.filesize($filePath)); - // Transmita o arquivo para o cliente enquanto ele é lido + // Stream the file to the client as it's read readfile($filePath); -// Esta é a linha mágica aqui +// This is the magic line here })->stream(); ``` @@ -639,10 +700,10 @@ Você também pode usar o método `streamWithHeaders()` para definir os cabeçal ```php Flight::route('/stream-users', function() { - // você pode adicionar quaisquer cabeçalhos adicionais que quiser aqui - // você só deve usar header() ou Flight::response()->setRealHeader() + // you can add any additional headers you want here + // you just must use header() or Flight::response()->setRealHeader() - // no entanto, da maneira que você puxa seus dados, apenas como exemplo... + // however you pull your data, just as an example... $users_stmt = Flight::db()->query("SELECT id, first_name, last_name FROM users"); echo '{'; @@ -653,16 +714,16 @@ Flight::route('/stream-users', function() { echo ','; } - // Isso é necessário para enviar os dados para o cliente + // This is required to send the data to the client ob_flush(); } echo '}'; -// É assim que você definirá os cabeçalhos antes de começar a transmitir. +// This is how you'll set the headers before you start streaming. })->streamWithHeaders([ 'Content-Type' => 'application/json', 'Content-Disposition' => 'attachment; filename="users.json"', - // código de status opcional, padrão para 200 + // optional status code, defaults to 200 'status' => 200 ]); ``` @@ -678,31 +739,28 @@ Flight::route('/stream-users', function() { - Parâmetros de rota são combinados por ordem, não por nome. Certifique-se de que a ordem dos parâmetros do callback corresponda à definição da rota. - Usar `Flight::get()` não define uma rota; use `Flight::route('GET /...')` para roteamento ou o contexto do objeto Router em grupos (ex: `$router->get(...)`). - A propriedade executedRoute só é definida após uma rota ser executada; ela é NULL antes da execução. -- Streaming requer que a funcionalidade de buffer de saída legado do Flight seja desabilitada (`flight.v2.output_buffering = false`). +- Streaming requer que a funcionalidade de buffering de saída legada do Flight esteja desabilitada (`flight.v2.output_buffering = false`). - Para injeção de dependência, apenas certas definições de rota suportam instanciação baseada em contêiner. ### 404 Não Encontrado ou Comportamento Inesperado de Rota -Se você estiver vendo um erro 404 Não Encontrado (mas você jura pela sua vida que ele está realmente lá e não é um erro de digitação), isso na verdade pode ser um problema -com você retornando um valor no seu endpoint de rota em vez de apenas ecoá-lo. A razão para isso é intencional, mas pode surpreender alguns desenvolvedores. +Se você estiver vendo um erro 404 Não Encontrado (mas você jura pela sua vida que ele realmente está lá e não é um erro de digitação), isso na verdade pode ser um problema com você retornando um valor no seu endpoint de rota em vez de apenas ecoá-lo. A razão para isso é intencional, mas pode surpreender alguns desenvolvedores. ```php - Flight::route('/hello', function(){ - // Isso pode causar um erro 404 Não Encontrado + // This might cause a 404 Not Found error return 'Hello World'; }); -// O que você provavelmente quer +// What you probably want Flight::route('/hello', function(){ echo 'Hello World'; }); - ``` A razão para isso é por causa de um mecanismo especial incorporado no roteador que trata a saída de retorno como um sinal para "ir para a próxima rota". Você pode ver o comportamento documentado na seção [Roteamento](/learn/routing#passing). ## Changelog -- v3: Adicionado roteamento de recursos, alias de rota e suporte a streaming, grupos de rota e suporte a middleware. +- v3: Adicionado roteamento de recursos, apelidos de rota e suporte a streaming, grupos de rota e suporte a middleware. - v1: A vasta maioria dos recursos básicos disponíveis. \ No newline at end of file diff --git a/content/v3/ru/awesome-plugins/apm.md b/content/v3/ru/awesome-plugins/apm.md index 3e83e317..149f4d1f 100644 --- a/content/v3/ru/awesome-plugins/apm.md +++ b/content/v3/ru/awesome-plugins/apm.md @@ -1,12 +1,14 @@ # Документация FlightPHP APM -Добро пожаловать в FlightPHP APM — ваш личный тренер производительности приложения! Это руководство — ваша карта пути для настройки, использования и освоения мониторинга производительности приложения (APM) с FlightPHP. Будь то охота за медленными запросами или просто желание погрузиться в графики задержек, мы всё охватили. Давайте сделаем ваше приложение быстрее, пользователей счастливее и сессии отладки проще! +Добро пожаловать в FlightPHP APM — ваш личный тренер по производительности приложения! Это руководство — ваша дорожная карта по настройке, использованию и освоению мониторинга производительности приложений (APM) с FlightPHP. Будь вы охотником за медленными запросами или просто хотите погрузиться в графики задержек, мы вас прикроем. Давайте сделаем ваше приложение быстрее, ваших пользователей счастливее, а сессии отладки — легкими как ветер! + +Посмотрите [демо](https://flightphp-docs-apm.sky-9.com/apm/dashboard) панели управления для сайта Flight Docs. ![FlightPHP APM](/images/apm.png) -## Почему APM важно +## Почему APM важен -Представьте: ваше приложение — это оживлённый ресторан. Без отслеживания времени заказов или выявления проблем в кухне вы просто угадываете, почему клиенты уходят недовольными. APM — ваш помощник-шеф-повар — он наблюдает за каждым шагом, от входящих запросов до запросов к базе данных, и отмечает всё, что замедляет процесс. Медленные страницы отпугивают пользователей (исследования показывают, что 53% уходят, если сайт загружается более 3 секунд!), и APM помогает выявить эти проблемы *до* того, как они ударят. Это proactive спокойствие — меньше моментов "почему это сломалось?", больше побед "смотрите, как гладко это работает!". +Представьте: ваше приложение — это оживленный ресторан. Без способа отслеживать, сколько времени занимают заказы или где кухня тормозит, вы угадываете, почему клиенты уходят недовольными. APM — ваш су-шеф: он следит за каждым шагом, от входящих запросов до запросов к базе данных, и отмечает всё, что вас замедляет. Медленные страницы отпугивают пользователей (исследования говорят, что 53% уходят, если сайт загружается дольше 3 секунд!), а APM помогает поймать эти проблемы *до* того, как они укусят. Это проактивное спокойствие — меньше моментов «почему это сломано?», больше побед «смотрите, как круто это работает!». ## Установка @@ -17,55 +19,55 @@ composer require flightphp/apm ``` Вам понадобится: -- **PHP 7.4+**: Обеспечивает совместимость с LTS-дистрибутивами Linux и поддержку современного PHP. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Легковесный фреймворк, который мы улучшаем. +- **PHP 7.4+**: Обеспечивает совместимость с LTS-дистрибутивами Linux, поддерживая современный PHP. +- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Легковесный фреймворк, который мы усиливаем. ## Поддерживаемые базы данных FlightPHP APM в настоящее время поддерживает следующие базы данных для хранения метрик: -- **SQLite3**: Простая, на основе файла, идеально подходит для локальной разработки или небольших приложений. Вариант по умолчанию в большинстве настроек. -- **MySQL/MariaDB**: Идеально для крупных проектов или production-сред, где нужна надёжная, масштабируемая хранение. +- **SQLite3**: Простая, на основе файлов, идеальна для локальной разработки или небольших приложений. Вариант по умолчанию в большинстве настроек. +- **MySQL/MariaDB**: Идеально для крупных проектов или производственных сред, где нужна надежная, масштабируемая хранилище. -Вы можете выбрать тип базы данных на этапе конфигурации (см. ниже). Убедитесь, что в вашей среде PHP установлены необходимые расширения (например, `pdo_sqlite` или `pdo_mysql`). +Вы можете выбрать тип базы данных на шаге конфигурации (см. ниже). Убедитесь, что в вашей среде PHP установлены необходимые расширения (например, `pdo_sqlite` или `pdo_mysql`). ## Начало работы -Вот ваш пошаговый план к крутизне APM: +Вот ваш пошаговый путь к крутости APM: -### 1. Зарегистрируйте APM +### 1. Регистрация APM -Добавьте это в ваш `index.php` или файл `services.php`, чтобы начать отслеживание: +Вставьте это в ваш `index.php` или файл `services.php`, чтобы начать отслеживание: ```php use flight\apm\logger\LoggerFactory; use flight\Apm; -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json); // Создаёт логгер на основе конфигурации (подробнее скоро) +$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); $Apm = new Apm($ApmLogger); $Apm->bindEventsToFlightInstance($app); -// Если вы добавляете соединение с базой данных -// Должно быть PdoWrapper или PdoQueryCapture из Tracy Extensions -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True обязательно, чтобы включить отслеживание в APM. +// Если вы добавляете подключение к базе данных +// Должно быть PdoWrapper или PdoQueryCapture из расширений Tracy +$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True обязательно для включения отслеживания в APM. $Apm->addPdoConnection($pdo); ``` **Что здесь происходит?** -- `LoggerFactory::create()` берёт вашу конфигурацию (подробнее скоро) и настраивает логгер — SQLite по умолчанию. -- `Apm` — звезда — он слушает события Flight (запросы, маршруты, ошибки и т.д.) и собирает метрики. +- `LoggerFactory::create()` берет вашу конфигурацию (подробнее об этом скоро) и настраивает логгер — по умолчанию SQLite. +- `Apm` — звезда: он слушает события Flight (запросы, маршруты, ошибки и т.д.) и собирает метрики. - `bindEventsToFlightInstance($app)` связывает всё с вашим приложением Flight. -**Профессиональный совет: Сэмплирование** -Если ваше приложение загружено, логирование *каждого* запроса может перегрузить систему. Используйте коэффициент сэмплирования (от 0.0 до 1.0): +**Про-совет: Сэмплинг** +Если ваше приложение загружено, логирование *каждого* запроса может перегрузить систему. Используйте коэффициент сэмплинга (от 0.0 до 1.0): ```php $Apm = new Apm($ApmLogger, 0.1); // Логирует 10% запросов ``` -Это сохраняет производительность, при этом давая надёжные данные. +Это сохраняет производительность высокой, при этом давая надежные данные. -### 2. Настройте это +### 2. Настройка Запустите это, чтобы создать `.runway-config.json`: @@ -75,8 +77,8 @@ php vendor/bin/runway apm:init **Что это делает?** - Запускает мастер, спрашивающий, откуда берутся сырые метрики (источник) и куда идут обработанные данные (назначение). -- По умолчанию — SQLite, например, `sqlite:/tmp/apm_metrics.sqlite` для источника, другой для назначения. -- В результате вы получите конфигурацию вроде: +- По умолчанию SQLite — например, `sqlite:/tmp/apm_metrics.sqlite` для источника, другой для назначения. +- В итоге вы получите конфигурацию вроде: ```json { "apm": { @@ -88,14 +90,14 @@ php vendor/bin/runway apm:init } ``` -> Этот процесс также спросит, хотите ли вы запустить миграции для этой настройки. Если вы настраиваете это в первый раз, ответ — да. +> Этот процесс также спросит, хотите ли вы запустить миграции для этой настройки. Если вы настраиваете это впервые, ответ — да. **Почему два места?** -Сырые метрики накапливаются быстро (думайте о нефильтрованных логах). Рабочий процесс обрабатывает их в структурированное назначение для дашборда. Это поддерживает порядок! +Сырые метрики накапливаются быстро (представьте нефильтрованные логи). Воркер обрабатывает их в структурированное назначение для панели. Держит всё в порядке! -### 3. Обработайте метрики с помощью воркера +### 3. Обработка метрик с помощью воркера -Воркер превращает сырые метрики в данные, готовые для дашборда. Запустите его один раз: +Воркер превращает сырые метрики в данные, готовые для панели. Запустите его один раз: ```bash php vendor/bin/runway apm:worker @@ -103,11 +105,11 @@ php vendor/bin/runway apm:worker **Что он делает?** - Читает из вашего источника (например, `apm_metrics.sqlite`). -- Обрабатывает до 100 метрик (размер пакета по умолчанию) в назначение. -- Останавливается, когда закончено или если метрик не осталось. +- Обрабатывает до 100 метрик (размер пакета по умолчанию) в ваше назначение. +- Останавливается, когда закончит или если метрик больше нет. -**Сделайте его непрерывным** -Для живых приложений вам нужна постоянная обработка. Вот варианты: +**Держите его запущенным** +Для живых приложений вам понадобится непрерывная обработка. Вот ваши варианты: - **Режим демона**: ```bash @@ -120,16 +122,16 @@ php vendor/bin/runway apm:worker ```bash * * * * * php /path/to/project/vendor/bin/runway apm:worker ``` - Запускается каждую минуту — идеально для production. + Запускается каждую минуту — идеально для производства. - **Tmux/Screen**: - Запустите сеанс, который можно отсоединить: + Начните отсоединяемую сессию: ```bash tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon - # Ctrl+B, затем D для отсоединения; `tmux attach -t apm-worker` для подключения + # Ctrl+B, затем D для отсоединения; `tmux attach -t apm-worker` для переподключения ``` - Поддерживает работу даже после выхода. + Держит его запущенным даже при выходе из системы. - **Пользовательские настройки**: ```bash @@ -139,72 +141,72 @@ php vendor/bin/runway apm:worker - `--max_messages 1000`: Останавливается после 1000 метрик. - `--timeout 300`: Выходит через 5 минут. -**Почему это важно?** -Без воркера дашборд будет пустым. Это мост между сырыми логами и полезными инсайтами. +**Зачем это нужно?** +Без воркера ваша панель пуста. Это мост между сырыми логами и полезными инсайтами. -### 4. Запустите дашборд +### 4. Запуск панели -Посмотрите на виталы вашего приложения: +Посмотрите жизненные показатели вашего приложения: ```bash php vendor/bin/runway apm:dashboard ``` **Что это?** -- Запускает PHP-сервер по адресу `http://localhost:8001/apm/dashboard`. -- Показывает логи запросов, медленные маршруты, процент ошибок и многое другое. +- Запускает PHP-сервер на `http://localhost:8001/apm/dashboard`. +- Показывает логи запросов, медленные маршруты, уровень ошибок и многое другое. **Настройте это**: ```bash php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php ``` -- `--host 0.0.0.0`: Доступно с любого IP (полезно для удалённого просмотра). +- `--host 0.0.0.0`: Доступно с любого IP (удобно для удаленного просмотра). - `--port 8080`: Используйте другой порт, если 8001 занят. - `--php-path`: Укажите путь к PHP, если он не в PATH. Откройте URL в браузере и исследуйте! -#### Режим production +#### Режим производства -Для production может потребоваться несколько техник, чтобы запустить дашборд, учитывая файрволы и другие меры безопасности. Вот варианты: +Для производства вам может потребоваться несколько техник, чтобы запустить панель, поскольку, вероятно, есть файрволы и другие меры безопасности. Вот несколько вариантов: -- **Используйте обратный прокси**: Настройте Nginx или Apache для переадресации запросов на дашборд. -- **SSH Tunnel**: Если вы можете SSH на сервер, используйте `ssh -L 8080:localhost:8001 youruser@yourserver`, чтобы туннелировать дашборд на вашу локальную машину. -- **VPN**: Если сервер за VPN, подключитесь и получите доступ к дашборду напрямую. -- **Настройте файрвол**: Откройте порт 8001 для вашего IP или сети сервера (или любого другого порта). -- **Настройте Apache/Nginx**: Если у вас есть веб-сервер перед приложением, настройте его на домен или поддомен. В этом случае установите корень документов на `/path/to/your/project/vendor/flightphp/apm/dashboard`. +- **Используйте обратный прокси**: Настройте Nginx или Apache для перенаправления запросов на панель. +- **SSH-туннель**: Если вы можете SSH на сервер, используйте `ssh -L 8080:localhost:8001 youruser@yourserver`, чтобы туннелировать панель на вашу локальную машину. +- **VPN**: Если ваш сервер за VPN, подключитесь к нему и получите доступ к панели напрямую. +- **Настройте файрвол**: Откройте порт 8001 для вашего IP или сети сервера (или любого порта, который вы установили). +- **Настройте Apache/Nginx**: Если у вас есть веб-сервер перед приложением, вы можете настроить его на домен или поддомен. Если вы это сделаете, установите корень документов в `/path/to/your/project/vendor/flightphp/apm/dashboard`. -#### Хотите другой дашборд? +#### Хотите другую панель? -Вы можете создать свой собственный дашборд, если хотите! Посмотрите в каталог vendor/flightphp/apm/src/apm/presenter за идеями, как представить данные для вашего дашборда! +Вы можете построить свою собственную панель, если хотите! Посмотрите директорию vendor/flightphp/apm/src/apm/presenter для идей, как представить данные для вашей собственной панели! -## Функции дашборда +## Возможности панели -Дашборд — ваш штаб APM — вот что вы увидите: +Панель — ваш штаб APM: вот что вы увидите: -- **Лог запросов**: Каждый запрос с временной меткой, URL, кодом ответа и общим временем. Нажмите "Детали", чтобы увидеть посредников, запросы и ошибки. -- **Самые медленные запросы**: Топ-5 запросов, которые занимают много времени (например, “/api/heavy” за 2.5s). -- **Самые медленные маршруты**: Топ-5 маршрутов по среднему времени — отлично для выявления шаблонов. -- **Процент ошибок**: Процент неудачных запросов (например, 2.3% 500s). -- **Перцентили задержек**: 95-й (p95) и 99-й (p99) времена ответа — знайте ваши худшие сценарии. -- **Диаграмма кодов ответов**: Визуализируйте 200s, 404s, 500s со временем. -- **Долгие запросы/Посредники**: Топ-5 медленных вызовов базы данных и слоёв посредников. -- **Попадания/Промахи кэша**: Насколько часто кэш спасает ситуацию. +- **Журнал запросов**: Каждый запрос с временной меткой, URL, кодом ответа и общим временем. Нажмите «Детали» для middleware, запросов и ошибок. +- **Самые медленные запросы**: Топ-5 запросов, поглощающих время (например, «/api/heavy» за 2.5с). +- **Самые медленные маршруты**: Топ-5 маршрутов по среднему времени — отлично для выявления паттернов. +- **Уровень ошибок**: Процент неудачных запросов (например, 2.3% 500-х). +- **Перцентили задержек**: 95-й (p95) и 99-й (p99) времена ответа — знайте худшие сценарии. +- **График кодов ответа**: Визуализируйте 200-е, 404-е, 500-е со временем. +- **Длинные запросы/Middleware**: Топ-5 медленных вызовов базы данных и слоев middleware. +- **Попадания/промахи кэша**: Как часто кэш спасает день. **Дополнительно**: -- Фильтруйте по "Последний час", "Последний день" или "Последняя неделя". -- Переключайте тёмный режим для поздних ночных сессий. +- Фильтруйте по «Последний час», «Последний день» или «Последняя неделя». +- Переключайте темный режим для поздних ночных сессий. **Пример**: Запрос к `/users` может показать: -- Общее время: 150ms -- Посредник: `AuthMiddleware->handle` (50ms) -- Запрос: `SELECT * FROM users` (80ms) -- Кэш: Попадание на `user_list` (5ms) +- Общее время: 150мс +- Middleware: `AuthMiddleware->handle` (50мс) +- Запрос: `SELECT * FROM users` (80мс) +- Кэш: Попадание в `user_list` (5мс) ## Добавление пользовательских событий -Отслеживайте всё — например, вызов API или процесс оплаты: +Отслеживайте что угодно — например, вызов API или процесс оплаты: ```php use flight\apm\CustomEvent; @@ -216,10 +218,10 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ])); ``` -**Где это отобразится?** -В деталях запроса дашборда под "Пользовательскими событиями" — расширяемо с красивым форматом JSON. +**Где это появится?** +В деталях запроса панели под «Пользовательские события» — расширяемо с красивым форматированием JSON. -**Применение**: +**Пример использования**: ```php $start = microtime(true); $apiResponse = file_get_contents('https://api.example.com/data'); @@ -229,42 +231,42 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -Теперь вы увидите, если этот API замедляет ваше приложение! +Теперь вы увидите, тянет ли этот API ваше приложение вниз! ## Мониторинг базы данных -Отслеживайте запросы PDO вот так: +Отслеживайте PDO-запросы так: ```php use flight\database\PdoWrapper; -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True обязательно, чтобы включить отслеживание в APM. +$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True обязательно для включения отслеживания в APM. $Apm->addPdoConnection($pdo); ``` -**Что вы получите**: +**Что вы получаете**: - Текст запроса (например, `SELECT * FROM users WHERE id = ?`) -- Время выполнения (например, 0.015s) +- Время выполнения (например, 0.015с) - Количество строк (например, 42) **Внимание**: -- **Опционально**: Пропустите это, если вам не нужен отслеживание БД. -- **Только PdoWrapper**: Обычный PDO пока не подключён — следите за обновлениями! -- **Предупреждение о производительности**: Логирование каждого запроса на сайте с большой нагрузкой на БД может замедлить всё. Используйте сэмплирование (`$Apm = new Apm($ApmLogger, 0.1)`), чтобы облегчить нагрузку. +- **Опционально**: Пропустите это, если не нужно отслеживание БД. +- **Только PdoWrapper**: Основной PDO еще не подключен — следите за обновлениями! +- **Предупреждение о производительности**: Логирование каждого запроса на сайте с тяжелой БД может замедлить вещи. Используйте сэмплинг (`$Apm = new Apm($ApmLogger, 0.1)`), чтобы облегчить нагрузку. **Пример вывода**: - Запрос: `SELECT name FROM products WHERE price > 100` -- Время: 0.023s +- Время: 0.023с - Строки: 15 ## Опции воркера -Настройте воркер по вашему вкусу: +Настройте воркер по вкусу: -- `--timeout 300`: Останавливается через 5 минут — хорошо для тестов. -- `--max_messages 500`: Ограничивается 500 метриками — делает это конечным. +- `--timeout 300`: Останавливается через 5 минут — хорошо для тестирования. +- `--max_messages 500`: Ограничивает 500 метриками — держит конечным. - `--batch_size 200`: Обрабатывает 200 за раз — балансирует скорость и память. -- `--daemon`: Работает nonstop — идеально для живого мониторинга. +- `--daemon`: Работает без остановки — идеально для живого мониторинга. **Пример**: ```bash @@ -274,15 +276,15 @@ php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ## ID запроса в приложении -Каждый запрос имеет уникальный ID для отслеживания. Вы можете использовать этот ID в приложении, чтобы коррелировать логи и метрики. Например, добавьте ID запроса на страницу ошибок: +Каждый запрос имеет уникальный ID запроса для отслеживания. Вы можете использовать этот ID в вашем приложении для корреляции логов и метрик. Например, вы можете добавить ID запроса на страницу ошибок: ```php Flight::map('error', function($message) { // Получите ID запроса из заголовка ответа X-Flight-Request-Id $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - // Кроме того, вы можете получить его из переменной Flight - // Этот метод может не работать хорошо в swoole или других асинхронных платформах. + // Кроме того, вы могли бы получить его из переменной Flight + // Этот метод не будет работать хорошо в swoole или других асинхронных платформах. // $requestId = Flight::get('apm.request_id'); echo "Error: $message (Request ID: $requestId)"; @@ -291,55 +293,55 @@ Flight::map('error', function($message) { ## Обновление -Если вы обновляетесь до новой версии APM, возможно, потребуется запустить миграции базы данных. Сделайте это командой: +Если вы обновляетесь до новой версии APM, возможно, потребуется запустить миграции базы данных. Вы можете сделать это, запустив следующую команду: ```bash php vendor/bin/runway apm:migrate ``` Это запустит любые необходимые миграции для обновления схемы базы данных до последней версии. -**Примечание:** Если ваша база данных APM велика, эти миграции могут занять время. Запустите команду в часы низкой нагрузки. +**Примечание:** Если ваша база данных APM большая по размеру, эти миграции могут занять некоторое время. Вы можете захотеть запустить эту команду в непиковые часы. ## Очистка старых данных -Чтобы сохранить базу данных в порядке, очистите старые данные. Это особенно полезно для загруженных приложений, чтобы сохранить размер базы управляемым. -Запустите команду: +Чтобы держать базу данных в порядке, вы можете очистить старые данные. Это особенно полезно, если вы запускаете загруженное приложение и хотите держать размер базы управляемым. +Вы можете сделать это, запустив следующую команду: ```bash php vendor/bin/runway apm:purge ``` -Это удалит все данные старше 30 дней. Вы можете изменить количество дней, передавая другой значение в опции `--days`: +Это удалит все данные старше 30 дней из базы данных. Вы можете скорректировать количество дней, передав другое значение опции `--days`: ```bash php vendor/bin/runway apm:purge --days 7 ``` -Это удалит все данные старше 7 дней. +Это удалит все данные старше 7 дней из базы данных. ## Устранение неисправностей -Зависли? Попробуйте: +Застряли? Попробуйте эти: -- **Нет данных в дашборде?** - - Работает ли воркер? Проверьте `ps aux | grep apm:worker`. - - Совпадают ли пути в конфигурации? Проверьте DSN в `.runway-config.json`, чтобы они указывали на реальные файлы. - - Запустите `php vendor/bin/runway apm:worker` вручную, чтобы обработать ожидающие метрики. +- **Нет данных в панели?** + - Запущен ли воркер? Проверьте `ps aux | grep apm:worker`. + - Пути конфигурации совпадают? Проверьте, что DSN в `.runway-config.json` указывают на реальные файлы. + - Запустите `php vendor/bin/runway apm:worker` вручную для обработки ожидающих метрик. - **Ошибки воркера?** - - Посмотрите в файлы SQLite (например, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Проверьте логи PHP на стек-трейсы. + - Загляните в ваши файлы SQLite (например, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). + - Проверьте логи PHP на наличие стек-трейсов. -- **Дашборд не запускается?** - - Занят ли порт 8001? Используйте `--port 8080`. +- **Панель не запускается?** + - Порт 8001 занят? Используйте `--port 8080`. - PHP не найден? Используйте `--php-path /usr/bin/php`. - Файрвол блокирует? Откройте порт или используйте `--host localhost`. - **Слишком медленно?** - - Уменьшите коэффициент сэмплирования: `$Apm = new Apm($ApmLogger, 0.05)` (5%). + - Уменьшите коэффициент сэмплинга: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - Уменьшите размер пакета: `--batch_size 20`. -- **Не отслеживаются исключения/Ошибки?** - - Если у вас включён [Tracy](https://tracy.nette.org/) в проекте, он переопределяет обработку ошибок Flight. Отключите Tracy и убедитесь, что `Flight::set('flight.handle_errors', true);` установлено. +- **Не отслеживает исключения/ошибки?** + - Если у вас включен [Tracy](https://tracy.nette.org/) для проекта, он переопределит обработку ошибок Flight. Вам нужно отключить Tracy и убедиться, что `Flight::set('flight.handle_errors', true);` установлено. -- **Не отслеживаются запросы к базе данных?** - - Убедитесь, что вы используете `PdoWrapper` для соединений с базой. - - Убедитесь, что последний аргумент в конструкторе — `true`. \ No newline at end of file +- **Не отслеживает запросы к базе данных?** + - Убедитесь, что вы используете `PdoWrapper` для подключений к базе данных. + - Убедитесь, что последний аргумент в конструкторе `true`. \ No newline at end of file diff --git a/content/v3/ru/learn/ai.md b/content/v3/ru/learn/ai.md index 8c1cef8f..c4c34042 100644 --- a/content/v3/ru/learn/ai.md +++ b/content/v3/ru/learn/ai.md @@ -2,20 +2,20 @@ ## Обзор -Flight упрощает суперзарядку ваших PHP-проектов с помощью инструментов на базе ИИ и современных рабочих процессов разработчика. С встроенными командами для подключения к провайдерам LLM (Large Language Model) и генерации инструкций по кодированию ИИ, специфичных для проекта, Flight помогает вам и вашей команде извлечь максимум из ИИ-ассистентов, таких как GitHub Copilot, Cursor и Windsurf. +Flight упрощает суперзарядку ваших PHP-проектов с помощью инструментов на базе ИИ и современных рабочих процессов разработчика. С встроенными командами для подключения к провайдерам LLM (Large Language Model) и генерации специфических для проекта инструкций по кодированию с ИИ, Flight помогает вам и вашей команде извлекать максимум из ИИ-ассистентов, таких как GitHub Copilot, Cursor и Windsurf. ## Понимание -ИИ-ассистенты для кодирования наиболее полезны, когда они понимают контекст вашего проекта, конвенции и цели. ИИ-помощники Flight позволяют вам: +ИИ-ассистенты для кодирования наиболее полезны, когда они понимают контекст, конвенции и цели вашего проекта. ИИ-помощники Flight позволяют вам: - Подключить ваш проект к популярным провайдерам LLM (OpenAI, Grok, Claude и т.д.) -- Генерировать и обновлять инструкции, специфичные для проекта, для ИИ-инструментов, чтобы все получали последовательную, релевантную помощь +- Генерировать и обновлять специфические для проекта инструкции для ИИ-инструментов, чтобы все получали последовательную, релевантную помощь - Сохранять вашу команду в согласованности и продуктивности, тратя меньше времени на объяснение контекста Эти функции встроены в основной CLI Flight и официальный стартовый проект [flightphp/skeleton](https://github.com/flightphp/skeleton). ## Базовое использование -### 1. Настройка учетных данных LLM +### Настройка учетных данных LLM Команда `ai:init` проведет вас через процесс подключения вашего проекта к провайдеру LLM. @@ -40,7 +40,7 @@ Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: Credentials saved to .runway-creds.json ``` -### 2. Генерация инструкций ИИ, специфичных для проекта +### Генерация специфических для проекта инструкций ИИ Команда `ai:generate-instructions` помогает создать или обновить инструкции для ИИ-ассистентов кодирования, адаптированные к вашему проекту. @@ -48,7 +48,7 @@ Credentials saved to .runway-creds.json php runway ai:generate-instructions ``` -Вы ответите на несколько вопросов о вашем проекте (описание, база данных, шаблонизация, безопасность, размер команды и т.д.). Flight использует вашего провайдера LLM для генерации инструкций, а затем записывает их в: +Вы ответите на несколько вопросов о вашем проекте (описание, база данных, шаблонизация, безопасность, размер команды и т.д.). Flight использует вашего провайдера LLM для генерации инструкций, затем записывает их в: - `.github/copilot-instructions.md` (для GitHub Copilot) - `.cursor/rules/project-overview.mdc` (для Cursor) - `.windsurfrules` (для Windsurf) diff --git a/content/v3/ru/learn/requests.md b/content/v3/ru/learn/requests.md index b3009423..6f517fcf 100644 --- a/content/v3/ru/learn/requests.md +++ b/content/v3/ru/learn/requests.md @@ -10,15 +10,15 @@ $request = Flight::request(); ## Понимание -HTTP-запросы — это один из ключевых аспектов, которые нужно понять о жизненном цикле HTTP. Пользователь выполняет действие в веб-браузере или HTTP-клиенте, и они отправляют серию заголовков, тело, URL и т.д. в ваш проект. Вы можете захватывать эти заголовки (язык браузера, тип сжатия, который они могут обрабатывать, пользовательский агент и т.д.) и захватывать тело и URL, отправляемые в ваше приложение Flight. Эти запросы необходимы для вашего приложения, чтобы понять, что делать дальше. +HTTP-запросы — это один из ключевых аспектов, которые нужно понять в жизненном цикле HTTP. Пользователь выполняет действие в веб-браузере или HTTP-клиенте, и они отправляют серию заголовков, тела, URL и т.д. в ваш проект. Вы можете захватить эти заголовки (язык браузера, тип сжатия, который они могут обрабатывать, пользовательский агент и т.д.) и захватить тело и URL, которые отправляются в ваше приложение Flight. Эти запросы необходимы для вашего приложения, чтобы понять, что делать дальше. -## Базовое использование +## Основное использование PHP имеет несколько суперглобальных переменных, включая `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` и `$_COOKIE`. Flight абстрагирует их в удобные [Collections](/learn/collections). Вы можете обращаться к свойствам `query`, `data`, `cookies` и `files` как к массивам или объектам. -> **Примечание:** **СТРОГО** не рекомендуется использовать эти суперглобальные переменные в вашем проекте, и их следует ссылаться через объект `request()`. +> **Примечание:** **СИЛЬНО** не рекомендуется использовать эти суперглобальные переменные в вашем проекте, и их следует ссылаться через объект `request()`. -> **Примечание:** Нет доступной абстракции для `$_ENV`. +> **Примечание:** Для `$_ENV` нет доступной абстракции. ### `$_GET` @@ -68,7 +68,7 @@ Flight::route('GET /login', function(){ }); ``` -Для помощи по установке новых значений cookie см. [overclokk/cookie](/awesome-plugins/php-cookie) +Для помощи в установке новых значений cookie см. [overclokk/cookie](/awesome-plugins/php-cookie) ### `$_SERVER` @@ -84,7 +84,7 @@ $host = Flight::request()->getVar('HTTP_HOST'); Вы можете получить доступ к загруженным файлам через свойство `files`: ```php -// сырой доступ к свойству $_FILES. См. ниже рекомендуемый подход +// прямой доступ к свойству $_FILES. См. ниже рекомендуемый подход $uploadedFile = Flight::request()->files['myFile']; // или $uploadedFile = Flight::request()->files->myFile; @@ -107,7 +107,7 @@ Flight::route('POST /upload', function(){ }); ``` -Если у вас загружено несколько файлов, вы можете пройтись по ним в цикле: +Если у вас загружено несколько файлов, вы можете пройтись по ним циклом: ```php Flight::route('POST /upload', function(){ @@ -119,7 +119,7 @@ Flight::route('POST /upload', function(){ }); ``` -> **Примечание по безопасности:** Всегда проверяйте и очищайте пользовательский ввод, особенно при работе с загрузкой файлов. Всегда проверяйте типы расширений, которые вы разрешаете загружать, но также проверяйте "магические байты" файла, чтобы убедиться, что это действительно тип файла, который утверждает пользователь. Есть [статьи](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [и](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [библиотеки](https://github.com/RikudouSage/MimeTypeDetector), доступные для помощи в этом. +> **Примечание по безопасности:** Всегда проверяйте и очищайте ввод пользователя, особенно при работе с загрузкой файлов. Всегда проверяйте типы расширений, которые вы разрешаете загружать, но также проверяйте "магические байты" файла, чтобы убедиться, что это действительно тип файла, который заявляет пользователь. Есть [статьи](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [и](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [библиотеки](https://github.com/RikudouSage/MimeTypeDetector), доступные для помощи в этом. ### Тело запроса @@ -128,13 +128,13 @@ Flight::route('POST /upload', function(){ ```php Flight::route('POST /users/xml', function(){ $xmlBody = Flight::request()->getBody(); - // сделать что-то с отправленным XML. + // сделать что-то с XML, который был отправлен. }); ``` ### JSON-тело -Если вы получаете запрос с типом содержимого `application/json` и примерами данных `{"id": 123}`, оно будет доступно из свойства `data`: +Если вы получаете запрос с типом содержимого `application/json` и примером данных `{"id": 123}`, он будет доступен из свойства `data`: ```php $id = Flight::request()->data->id; @@ -151,7 +151,7 @@ $host = Flight::request()->getHeader('Authorization'); // или $host = Flight::request()->header('Authorization'); -// Если вам нужно получить все заголовки +// Если нужно получить все заголовки $headers = Flight::request()->getHeaders(); // или $headers = Flight::request()->headers(); @@ -193,9 +193,9 @@ $method = Flight::request()->getMethod(); - **host** - Имя хоста запроса - **servername** - SERVER_NAME из `$_SERVER` -## Вспомогательные методы для URL +## Вспомогательные методы -Есть несколько вспомогательных методов для сборки частей URL для вашего удобства. +Есть несколько вспомогательных методов для сборки частей URL или работы с определенными заголовками. ### Полный URL @@ -205,6 +205,7 @@ $method = Flight::request()->getMethod(); $url = Flight::request()->getFullUrl(); // https://example.com/some/path?foo=bar ``` + ### Базовый URL Вы можете получить доступ к базовому URL с помощью метода `getBaseUrl()`: @@ -213,7 +214,7 @@ $url = Flight::request()->getFullUrl(); // http://example.com/path/to/something/cool?query=yes+thanks $url = Flight::request()->getBaseUrl(); // https://example.com -// Обратите внимание, нет завершающего слеша. +// Обратите внимание, без завершающего слеша. ``` ## Разбор запроса @@ -225,16 +226,40 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` +## Переговоры по типам принимаемого содержимого + +_v3.17.2_ + +Вы можете использовать метод `negotiateContentType()`, чтобы определить лучший тип содержимого для ответа на основе заголовка `Accept`, отправленного клиентом. + +```php + +// Пример заголовка Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// Ниже определяются поддерживаемые типы. +$availableTypes = ['application/json', 'application/xml']; +$typeToServe = Flight::request()->negotiateContentType($availableTypes); +if ($typeToServe === 'application/json') { + // Отправить JSON-ответ +} elseif ($typeToServe === 'application/xml') { + // Отправить XML-ответ +} else { + // По умолчанию что-то другое или выбросить ошибку +} +``` + +> **Примечание:** Если ни один из доступных типов не найден в заголовке `Accept`, метод вернет `null`. Если заголовок `Accept` не определен, метод вернет первый тип в массиве `$availableTypes`. + ## См. также -- [Routing](/learn/routing) - Узнайте, как сопоставлять маршруты с контроллерами и рендерить представления. +- [Routing](/learn/routing) - См., как сопоставлять маршруты с контроллерами и рендерить представления. - [Responses](/learn/responses) - Как настраивать HTTP-ответы. - [Why a Framework?](/learn/why-frameworks) - Как запросы вписываются в общую картину. - [Collections](/learn/collections) - Работа с коллекциями данных. - [Uploaded File Handler](/learn/uploaded-file) - Обработка загрузки файлов. ## Устранение неисправностей -- `request()->ip` и `request()->proxy_ip` могут отличаться, если ваш веб-сервер находится за прокси, балансировщиком нагрузки и т.д. +- `request()->ip` и `request()->proxy_ip` могут отличаться, если ваш веб-сервер находится за прокси, балансировщиком нагрузки и т.д. ## Журнал изменений +- v3.17.2 - Добавлен negotiateContentType() - v3.12.0 - Добавлена возможность обработки загрузки файлов через объект запроса. - v1.0 - Первоначальный выпуск. \ No newline at end of file diff --git a/content/v3/ru/learn/responses.md b/content/v3/ru/learn/responses.md index 787faedf..0bdfea78 100644 --- a/content/v3/ru/learn/responses.md +++ b/content/v3/ru/learn/responses.md @@ -1,16 +1,16 @@ # Responses -## Overview +## Обзор -Flight помогает генерировать часть заголовков ответа для вас, но вы контролируете большую часть того, что отправляете обратно пользователю. Большинство времени вы будете обращаться напрямую к объекту `response()`, но Flight имеет некоторые вспомогательные методы для установки некоторых заголовков ответа для вас. +Flight помогает генерировать часть заголовков ответа для вас, но вы контролируете большую часть того, что отправляете обратно пользователю. Большинство времени вы будете обращаться напрямую к объекту `response()`, но Flight имеет некоторые вспомогательные методы для установки некоторых заголовков ответа за вас. -## Understanding +## Понимание -После того как пользователь отправит свой [request](/learn/requests) запрос в ваше приложение, вам нужно сгенерировать правильный ответ для него. Они отправили вам информацию, такую как предпочитаемый язык, могут ли они обрабатывать определенные типы сжатия, их пользовательский агент и т.д., и после обработки всего этого пришло время отправить им правильный ответ. Это может быть установка заголовков, вывод тела HTML или JSON для них или перенаправление на страницу. +После того как пользователь отправит свой [запрос](/learn/requests) в ваше приложение, вам нужно сгенерировать правильный ответ для него. Они отправили вам информацию, такую как предпочитаемый язык, могут ли они обрабатывать определенные типы сжатия, их пользовательский агент и т.д., и после обработки всего этого пришло время отправить им правильный ответ. Это может быть установка заголовков, вывод тела HTML или JSON для них или перенаправление на страницу. -## Basic Usage +## Базовое использование -### Sending a Response Body +### Отправка тела ответа Flight использует `ob_start()` для буферизации вывода. Это означает, что вы можете использовать `echo` или `print` для отправки ответа пользователю, и Flight захватит его и отправит обратно пользователю с соответствующими заголовками. @@ -31,7 +31,7 @@ Flight::route('/', function() { ```php // Это отправит "Hello, World!" в браузер пользователя Flight::route('/', function() { - // многословно, но иногда это необходимо + // подробно, но иногда это необходимо Flight::response()->write("Hello, World!"); // если вы хотите получить тело, которое вы установили на этом этапе @@ -42,7 +42,7 @@ Flight::route('/', function() { ### JSON -Flight предоставляет поддержку для отправки JSON и JSONP ответов. Чтобы отправить JSON-ответ, вы передаете данные для кодирования в JSON: +Flight предоставляет поддержку для отправки JSON и JSONP ответов. Чтобы отправить JSON-ответ, вы передаете некоторые данные для кодирования в JSON: ```php Flight::route('/@companyId/users', function(int $companyId) { @@ -51,7 +51,7 @@ Flight::route('/@companyId/users', function(int $companyId) { Flight::json($users); }); -// [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* more users */ ] +// [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* больше пользователей */ ] ``` > **Примечание:** По умолчанию Flight отправит заголовок `Content-Type: application/json` с ответом. Он также будет использовать флаги `JSON_THROW_ON_ERROR` и `JSON_UNESCAPED_SLASHES` при кодировании JSON. @@ -64,9 +64,9 @@ Flight::route('/@companyId/users', function(int $companyId) { Flight::json(['id' => 123], 201); ``` -#### JSON с красивым выводом +#### JSON с красивой печатью -Вы также можете передать аргумент в последнее положение для включения красивого вывода: +Вы также можете передать аргумент в последнее положение для включения красивой печати: ```php Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT); @@ -120,7 +120,7 @@ Flight::route('/users', function() { }); ``` -### Clearing a Response Body +### Очистка тела ответа Если вы хотите очистить тело ответа, вы можете использовать метод `clearBody`: @@ -136,9 +136,9 @@ Flight::route('/', function() { Случай использования выше, вероятно, не распространен, однако он может быть более распространен, если это используется в [middleware](/learn/middleware). -### Running a Callback on the Response Body +### Выполнение обратного вызова на теле ответа -Вы можете запустить обратный вызов на теле ответа, используя метод `addResponseBodyCallback`: +Вы можете выполнить обратный вызов на теле ответа, используя метод `addResponseBodyCallback`: ```php Flight::route('/users', function() { @@ -147,17 +147,17 @@ Flight::route('/users', function() { Flight::render('users_table', ['users' => $users]); }); -// Это gzip'ит все ответы для любого маршрута +// Это сожмет gzip все ответы для любого маршрута Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); ``` -Вы можете добавить несколько обратных вызовов, и они будут выполняться в порядке их добавления. Поскольку это может принимать любой [callable](https://www.php.net/manual/en/language.types.callable.php), он может принимать массив класса `[ $class, 'method' ]`, замыкание `$strReplace = function($body) { str_replace('hi', 'there', $body); };` или имя функции `'minify'`, если у вас есть функция для минификации вашего HTML-кода, например. +Вы можете добавить несколько обратных вызовов, и они будут выполняться в порядке добавления. Поскольку это может принимать любой [вызываемый](https://www.php.net/manual/en/language.types.callable.php), он может принимать массив класса `[ $class, 'method' ]`, замыкание `$strReplace = function($body) { str_replace('hi', 'there', $body); };` или имя функции `'minify'`, если у вас есть функция для минимизации вашего html-кода, например. **Примечание:** Обратные вызовы маршрутов не будут работать, если вы используете опцию конфигурации `flight.v2.output_buffering`. -#### Specific Route Callback +#### Обратный вызов конкретного маршрута Если вы хотите, чтобы это применялось только к конкретному маршруту, вы можете добавить обратный вызов в сам маршрут: @@ -167,14 +167,14 @@ Flight::route('/users', function() { $users = $db->fetchAll("SELECT * FROM users"); Flight::render('users_table', ['users' => $users]); - // Это gzip'ит только ответ для этого маршрута + // Это сожмет gzip только ответ для этого маршрута Flight::response()->addResponseBodyCallback(function($body) { return gzencode($body, 9); }); }); ``` -#### Middleware Option +#### Опция Middleware Вы также можете использовать [middleware](/learn/middleware) для применения обратного вызова ко всем маршрутам через middleware: @@ -182,14 +182,14 @@ Flight::route('/users', function() { // MinifyMiddleware.php class MinifyMiddleware { public function before() { - // Примените обратный вызов здесь к объекту response(). + // Примените обратный вызов здесь на объекте response(). Flight::response()->addResponseBodyCallback(function($body) { return $this->minify($body); }); } protected function minify(string $body): string { - // минифицируйте тело каким-то образом + // минимизируйте тело каким-то образом return $body; } } @@ -201,7 +201,7 @@ Flight::group('/users', function() { }, [ new MinifyMiddleware() ]); ``` -### Status Codes +### Коды статуса Вы можете установить код статуса ответа, используя метод `status`: @@ -217,13 +217,13 @@ Flight::route('/@id', function($id) { }); ``` -Если вы хотите получить текущий код статуса, вы можете использовать метод `status` без аргументов: +Если вы хотите получить текущий код статуса, вы можете использовать метод `status` без каких-либо аргументов: ```php Flight::response()->status(); // 200 ``` -### Setting a Response Header +### Установка заголовка ответа Вы можете установить заголовок, такой как тип содержимого ответа, используя метод `header`: @@ -237,7 +237,7 @@ Flight::route('/', function() { }); ``` -### Redirect +### Перенаправление Вы можете перенаправить текущий запрос, используя метод `redirect()` и передав новый URL: @@ -264,7 +264,7 @@ Flight::route('/login', function() { Flight::redirect('/new/location', 301); // постоянный ``` -### Stopping Route Execution +### Остановка выполнения маршрута Вы можете остановить фреймворк и немедленно выйти в любой момент, вызвав метод `halt`: @@ -272,13 +272,13 @@ Flight::redirect('/new/location', 301); // постоянный Flight::halt(); ``` -Вы также можете указать опциональный `HTTP` код статуса и сообщение: +Вы также можете указать опциональный код статуса `HTTP` и сообщение: ```php Flight::halt(200, 'Be right back...'); ``` -Вызов `halt` отбросит любое содержимое ответа на этом этапе и остановит все выполнение. Если вы хотите остановить фреймворк и вывести текущий ответ, используйте метод `stop`: +Вызов `halt` отбросит любое содержимое ответа до этого момента и остановит все выполнение. Если вы хотите остановить фреймворк и вывести текущий ответ, используйте метод `stop`: ```php Flight::stop($httpStatusCode = null); @@ -288,11 +288,11 @@ Flight::stop($httpStatusCode = null); Это сохранит ключ и значение заголовка в объекте ответа. В конце жизненного цикла запроса он построит заголовки и отправит ответ. -## Advanced Usage +## Расширенное использование -### Sending a Header Immediately +### Отправка заголовка немедленно -Могут быть случаи, когда вам нужно сделать что-то пользовательское с заголовком, и вам нужно отправить заголовок на той самой строке кода, с которой вы работаете. Если вы устанавливаете [streamed route](/learn/routing), это то, что вам нужно. Это достигается через `response()->setRealHeader()`. +Могут быть случаи, когда вам нужно сделать что-то пользовательское с заголовком, и вам нужно отправить заголовок на той самой строке кода, с которой вы работаете. Если вы устанавливаете [потоковый маршрут](/learn/routing), это то, что вам понадобится. Это достижимо через `response()->setRealHeader()`. ```php Flight::route('/', function() { @@ -319,9 +319,9 @@ my_func({"id":123}); Если вы не передадите имя параметра запроса, оно по умолчанию будет `jsonp`. -> **Примечание:** Если вы все еще используете JSONP-запросы в 2025 году и позже, присоединяйтесь к чату и расскажите нам почему! Мы любим слышать хорошие истории о битвах/ужасах! +> **Примечание:** Если вы все еще используете JSONP-запросы в 2025 году и позже, присоединяйтесь к чату и расскажите нам почему! Мы любим слышать хорошие истории сражений/ужасов! -### Clearing Response Data +### Очистка данных ответа Вы можете очистить тело ответа и заголовки, используя метод `clear()`. Это очистит любые заголовки, назначенные ответу, очистит тело ответа и установит код статуса в `200`. @@ -329,7 +329,7 @@ my_func({"id":123}); Flight::response()->clear(); ``` -#### Clearing Response Body Only +#### Очистка только тела ответа Если вы хотите очистить только тело ответа, вы можете использовать метод `clearBody()`: @@ -339,13 +339,13 @@ Flight::response()->clear(); Flight::response()->clearBody(); ``` -### HTTP Caching +### Кэширование HTTP -Flight предоставляет встроенную поддержку кэширования на уровне HTTP. Если условие кэширования выполнено, Flight вернет HTTP `304 Not Modified` ответ. В следующий раз, когда клиент запросит тот же ресурс, ему будет предложено использовать локально кэшированную версию. +Flight предоставляет встроенную поддержку кэширования на уровне HTTP. Если условие кэширования выполнено, Flight вернет HTTP-ответ `304 Not Modified`. В следующий раз, когда клиент запросит тот же ресурс, ему будет предложено использовать локально кэшированную версию. -#### Route Level Caching +#### Кэширование на уровне маршрута -Если вы хотите кэшировать весь свой ответ, вы можете использовать метод `cache()` и передать время для кэширования. +Если вы хотите кэшировать весь свой ответ, вы можете использовать метод `cache()` и передать время кэширования. ```php // Это закэширует ответ на 5 минут @@ -364,7 +364,7 @@ Flight::route('/news', function () { ### Last-Modified -Вы можете использовать метод `lastModified` и передать UNIX-временную метку для установки даты и времени, когда страница была последний раз изменена. Клиент продолжит использовать свой кэш, пока значение последнего изменения не изменится. +Вы можете использовать метод `lastModified` и передать UNIX-временную метку для установки даты и времени последнего изменения страницы. Клиент продолжит использовать свой кэш, пока значение последнего изменения не изменится. ```php Flight::route('/news', function () { @@ -384,9 +384,9 @@ Flight::route('/news', function () { }); ``` -Имейте в виду, что вызов либо `lastModified`, либо `etag` установит и проверит значение кэша. Если значение кэша одинаково между запросами, Flight немедленно отправит `HTTP 304` ответ и остановит обработку. +Имейте в виду, что вызов либо `lastModified`, либо `etag` установит и проверит значение кэша. Если значение кэша одинаково между запросами, Flight немедленно отправит ответ `HTTP 304` и остановит обработку. -### Download a File +### Скачивание файла _v3.12.0_ @@ -395,21 +395,24 @@ _v3.12.0_ ```php Flight::route('/download', function () { Flight::download('/path/to/file.txt'); + // Начиная с v3.17.1 вы можете указать пользовательское имя файла для скачивания + Flight::download('/path/to/file.txt', 'custom_name.txt'); }); ``` -## See Also -- [Routing](/learn/routing) - Как сопоставлять маршруты с контроллерами и рендерить представления. -- [Requests](/learn/requests) - Понимание того, как обрабатывать входящие запросы. -- [Middleware](/learn/middleware) - Использование middleware с маршрутами для аутентификации, логирования и т.д. -- [Why a Framework?](/learn/why-frameworks) - Понимание преимуществ использования фреймворка вроде Flight. -- [Extending](/learn/extending) - Как расширять Flight своей собственной функциональностью. +## См. также +- [Маршрутизация](/learn/routing) — Как сопоставлять маршруты с контроллерами и рендерить представления. +- [Запросы](/learn/requests) — Понимание того, как обрабатывать входящие запросы. +- [Middleware](/learn/middleware) — Использование middleware с маршрутами для аутентификации, логирования и т.д. +- [Почему фреймворк?](/learn/why-frameworks) — Понимание преимуществ использования фреймворка вроде Flight. +- [Расширение](/learn/extending) — Как расширять Flight своей собственной функциональностью. -## Troubleshooting -- Если у вас проблемы с тем, что перенаправления не работают, убедитесь, что вы добавили `return;` в метод. +## Устранение неисправностей +- Если у вас проблемы с перенаправлениями, которые не работают, убедитесь, что вы добавили `return;` в метод. - `stop()` и `halt()` — это не одно и то же. `halt()` остановит выполнение немедленно, в то время как `stop()` позволит выполнению продолжаться. -## Changelog -- v3.12.0 - Добавлен вспомогательный метод downloadFile. -- v3.10.0 - Добавлен `jsonHalt`. -- v1.0 - Первоначальный выпуск. \ No newline at end of file +## Журнал изменений +- v3.17.1 — Добавлен `$fileName` в метод `downloadFile()`. +- v3.12.0 — Добавлен вспомогательный метод downloadFile. +- v3.10.0 — Добавлен `jsonHalt`. +- v1.0 — Первое выпущение. \ No newline at end of file diff --git a/content/v3/ru/learn/routing.md b/content/v3/ru/learn/routing.md index 2e1bef95..a74d49e1 100644 --- a/content/v3/ru/learn/routing.md +++ b/content/v3/ru/learn/routing.md @@ -4,9 +4,9 @@ Маршрутизация в Flight PHP сопоставляет шаблоны URL с функциями обратного вызова или методами классов, обеспечивая быстрый и простой обработку запросов. Она разработана для минимальной нагрузки, удобства для начинающих и расширяемости без внешних зависимостей. ## Понимание -Маршрутизация — это основной механизм, который соединяет HTTP-запросы с логикой вашего приложения в Flight. Определяя маршруты, вы указываете, как разные URL запускают конкретный код, будь то через функции, методы классов или действия контроллера. Система маршрутизации Flight гибкая, поддерживает базовые шаблоны, именованные параметры, регулярные выражения и расширенные функции, такие как внедрение зависимостей и ресурсная маршрутизация. Этот подход позволяет держать ваш код организованным и легким в поддержке, оставаясь быстрым и простым для начинающих и расширяемым для продвинутых пользователей. +Маршрутизация — это основной механизм, который соединяет HTTP-запросы с логикой вашего приложения в Flight. Определяя маршруты, вы указываете, как разные URL запускают конкретный код, будь то через функции, методы классов или действия контроллера. Система маршрутизации Flight гибкая, поддерживает базовые шаблоны, именованные параметры, регулярные выражения и продвинутые функции, такие как внедрение зависимостей и ресурсная маршрутизация. Этот подход позволяет держать код организованным и легким в поддержке, оставаясь быстрым и простым для начинающих и расширяемым для продвинутых пользователей. -> **Примечание:** Хотите узнать больше о маршрутизации? Ознакомьтесь со страницей ["почему фреймворк?"](/learn/why-frameworks) для более подробного объяснения. +> **Примечание:** Хотите узнать больше о маршрутизации? Посмотрите страницу ["почему фреймворк?"](/learn/why-frameworks) для более подробного объяснения. ## Базовое использование @@ -21,7 +21,7 @@ Flight::route('/', function(){ > Маршруты сопоставляются в порядке их определения. Первый маршрут, соответствующий запросу, будет вызван. -### Использование функций в качестве обратных вызовов +### Использование функций как обратных вызовов Обратный вызов может быть любым объектом, который можно вызвать. Таким образом, вы можете использовать обычную функцию: ```php @@ -32,7 +32,7 @@ function hello() { Flight::route('/', 'hello'); ``` -### Использование классов и методов в качестве контроллера +### Использование классов и методов как контроллера Вы также можете использовать метод (статический или нет) класса: ```php @@ -108,7 +108,39 @@ Flight::route('GET|POST /', function () { }); ``` -### Использование объекта маршрутизатора +### Особая обработка запросов HEAD и OPTIONS + +Flight предоставляет встроенную обработку HTTP-запросов `HEAD` и `OPTIONS`: + +#### Запросы HEAD + +- **Запросы HEAD** обрабатываются так же, как запросы `GET`, но Flight автоматически удаляет тело ответа перед отправкой клиенту. +- Это означает, что вы можете определить маршрут для `GET`, и запросы HEAD к тому же URL вернут только заголовки (без содержимого), как ожидается по стандартам HTTP. + +```php +Flight::route('GET /info', function() { + echo 'This is some info!'; +}); +// Запрос HEAD к /info вернет те же заголовки, но без тела. +``` + +#### Запросы OPTIONS + +Запросы `OPTIONS` автоматически обрабатываются Flight для любого определенного маршрута. +- Когда получен запрос OPTIONS, Flight отвечает статусом `204 No Content` и заголовком `Allow`, перечисляющим все поддерживаемые HTTP-методы для этого маршрута. +- Вам не нужно определять отдельный маршрут для OPTIONS, если вы не хотите кастомное поведение или изменить ответ. + +```php +// Для маршрута, определенного как: +Flight::route('GET|POST /users', function() { /* ... */ }); + +// Запрос OPTIONS к /users ответит: +// +// Status: 204 No Content +// Allow: GET, POST, HEAD, OPTIONS +``` + +### Использование объекта Router Кроме того, вы можете получить объект Router, который имеет некоторые вспомогательные методы для вашего использования: @@ -116,7 +148,7 @@ Flight::route('GET|POST /', function () { $router = Flight::router(); -// сопоставляет все методы, как Flight::route() +// сопоставляет все методы так же, как Flight::route() $router->map('/', function() { echo 'hello world!'; }); @@ -136,14 +168,14 @@ $router->patch('/users/@id', function() { /* code */}); ```php Flight::route('/user/[0-9]+', function () { - // Это сопоставит /user/1234 + // Это будет соответствовать /user/1234 }); ``` Хотя этот метод доступен, рекомендуется использовать именованные параметры или именованные параметры с регулярными выражениями, поскольку они более читаемы и проще в поддержке. ### Именованные параметры -Вы можете указать именованные параметры в своих маршрутах, которые будут переданы в вашу функцию обратного вызова. **Это больше для читаемости маршрута, чем для чего-либо другого. Пожалуйста, ознакомьтесь с разделом ниже о важном предупреждении.** +Вы можете указать именованные параметры в своих маршрутах, которые будут переданы в вашу функцию обратного вызова. **Это больше для читаемости маршрута, чем что-либо еще. Пожалуйста, смотрите раздел ниже о важном предупреждении.** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -151,12 +183,12 @@ Flight::route('/@name/@id', function (string $name, string $id) { }); ``` -Вы также можете включить регулярные выражения с вашими именованными параметрами, используя разделитель `:`: +Вы также можете включить регулярные выражения с именованными параметрами, используя разделитель `:`: ```php Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { - // Это сопоставит /bob/123 - // Но не сопоставит /bob/12345 + // Это будет соответствовать /bob/123 + // Но не будет соответствовать /bob/12345 }); ``` @@ -173,7 +205,7 @@ Flight::route('/@name/@id', function (string $id, string $name) { ``` И если вы перейдете по следующему URL: `/bob/123`, вывод будет `hello, 123 (bob)!`. -_Пожалуйста, будьте осторожны_ при настройке ваших маршрутов и функций обратного вызова! +_Пожалуйста, будьте осторожны_ при настройке маршрутов и функций обратного вызова! ### Необязательные параметры Вы можете указать именованные параметры, которые являются необязательными для сопоставления, обернув сегменты в скобки. @@ -182,7 +214,7 @@ _Пожалуйста, будьте осторожны_ при настройк Flight::route( '/blog(/@year(/@month(/@day)))', function(?string $year, ?string $month, ?string $day) { - // Это сопоставит следующие URL: + // Это будет соответствовать следующим URL: // /blog/2012/12/10 // /blog/2012/12 // /blog/2012 @@ -198,7 +230,7 @@ Flight::route( ```php Flight::route('/blog/*', function () { - // Это сопоставит /blog/2000/02/01 + // Это будет соответствовать /blog/2000/02/01 }); ``` @@ -212,8 +244,8 @@ Flight::route('*', function () { ### Обработчик 404 Not Found -По умолчанию, если URL не найден, Flight отправит ответ `HTTP 404 Not Found`, который очень простой и обычный. -Если вы хотите иметь более кастомный ответ 404, вы можете [сопоставить](/learn/extending) свой собственный метод `notFound`: +По умолчанию, если URL не найден, Flight отправит простой и минималистичный ответ `HTTP 404 Not Found`. +Если вы хотите более кастомный ответ 404, вы можете [сопоставить](/learn/extending) свой собственный метод `notFound`: ```php Flight::map('notFound', function() { @@ -233,10 +265,39 @@ Flight::map('notFound', function() { }); ``` -## Расширенное использование +### Обработчик Method Not Found + +По умолчанию, если URL найден, но метод не разрешен, Flight отправит простой и минималистичный ответ `HTTP 405 Method Not Allowed` (Пример: Method Not Allowed. Allowed Methods are: GET, POST). Он также включит заголовок `Allow` с разрешенными методами для этого URL. + +Если вы хотите более кастомный ответ 405, вы можете [сопоставить](/learn/extending) свой собственный метод `methodNotFound`: + +```php +use flight\net\Route; + +Flight::map('methodNotFound', function(Route $route) { + $url = Flight::request()->url; + $methods = implode(', ', $route->methods); + + // Вы также можете использовать Flight::render() с кастомным шаблоном. + $output = <<My Custom 405 Method Not Allowed +

The method you have requested for {$url} is not allowed.

+

Allowed Methods are: {$methods}

+ HTML; + + $this->response() + ->clearBody() + ->status(405) + ->setHeader('Allow', $methods) + ->write($output) + ->send(); +}); +``` + +## Продвинутое использование ### Внедрение зависимостей в маршрутах -Если вы хотите использовать внедрение зависимостей через контейнер (PSR-11, PHP-DI, Dice и т.д.), единственный тип маршрутов, где это доступно, — это либо прямое создание объекта самостоятельно и использование контейнера для создания вашего объекта, либо вы можете использовать строки для определения класса и метода для вызова. Вы можете перейти на страницу [Внедрение зависимостей](/learn/dependency-injection-container) для получения дополнительной информации. +Если вы хотите использовать внедрение зависимостей через контейнер (PSR-11, PHP-DI, Dice и т.д.), единственный тип маршрутов, где это доступно, — это либо прямое создание объекта самостоятельно с использованием контейнера для создания вашего объекта, либо вы можете использовать строки для определения класса и метода для вызова. Вы можете перейти на страницу [Внедрение зависимостей](/learn/dependency-injection-container) для получения дополнительной информации. Вот быстрый пример: @@ -262,7 +323,7 @@ class Greeting // index.php // Настройте контейнер с любыми параметрами, которые вам нужны -// См. страницу Внедрения зависимостей для получения дополнительной информации о PSR-11 +// Смотрите страницу Внедрение зависимостей для дополнительной информации о PSR-11 $dice = new \Dice\Dice(); // Не забудьте переприсвоить переменную с '$dice = '!!!!! @@ -311,7 +372,7 @@ Flight::route('/user/*', function () { Теперь рекомендуется использовать [middleware](/learn/middleware) для обработки сложных случаев, таких как этот. ### Псевдонимы маршрутов -Назначая псевдоним маршруту, вы можете позже динамически вызывать этот псевдоним в вашем приложении для генерации позже в вашем коде (например: ссылка в HTML-шаблоне или генерация URL для перенаправления). +Присваивая псевдоним маршруту, вы можете позже динамически вызывать этот псевдоним в вашем приложении для генерации позже в коде (пример: ссылка в HTML-шаблоне или генерация URL перенаправления). ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); @@ -332,8 +393,8 @@ class UserController { ``` -Это особенно полезно, если ваш URL изменится. В приведенном выше примере предположим, что пользователи перемещены в `/admin/users/@id` вместо. -С псевдонимами на месте для маршрута вам больше не нужно искать все старые URL в вашем коде и изменять их, потому что псевдоним теперь вернет `/admin/users/5`, как в примере выше. +Это особенно полезно, если ваш URL изменится. В примере выше предположим, что пользователи перемещены в `/admin/users/@id` вместо этого. +С псевдонимами на месте для маршрута вам больше не нужно искать все старые URL в коде и изменять их, потому что псевдоним теперь вернет `/admin/users/5`, как в примере выше. Псевдонимы маршрутов все еще работают в группах: @@ -345,11 +406,11 @@ Flight::group('/users', function() { }); ``` -### Проверка информации о маршруте -Если вы хотите проверить информацию о соответствующем маршруте, есть 2 способа это сделать: +### Осмотр информации о маршруте +Если вы хотите осмотреть информацию о соответствующем маршруте, есть 2 способа это сделать: 1. Вы можете использовать свойство `executedRoute` на объекте `Flight::router()`. -2. Вы можете запросить передачу объекта маршрута в ваш обратный вызов, передав `true` в качестве третьего параметра в методе маршрута. Объект маршрута всегда будет последним параметром, переданным в вашу функцию обратного вызова. +2. Вы можете запросить, чтобы объект маршрута был передан в ваш обратный вызов, передав `true` в качестве третьего параметра в методе маршрута. Объект маршрута всегда будет последним параметром, переданным в вашу функцию обратного вызова. #### `executedRoute` ```php @@ -362,10 +423,10 @@ Flight::route('/', function() { // Массив именованных параметров $route->params; - // Сопоставляющее регулярное выражение + // Соответствующее регулярное выражение $route->regex; - // Содержит содержимое любого '*' используемого в шаблоне URL + // Содержит содержимое любого '*' , использованного в шаблоне URL $route->splat; // Показывает путь URL....если вам это действительно нужно @@ -390,10 +451,10 @@ Flight::route('/', function(\flight\net\Route $route) { // Массив именованных параметров $route->params; - // Сопоставляющее регулярное выражение + // Соответствующее регулярное выражение $route->regex; - // Содержит содержимое любого '*' используемого в шаблоне URL + // Содержит содержимое любого '*' , использованного в шаблоне URL $route->splat; // Показывает путь URL....если вам это действительно нужно @@ -404,21 +465,21 @@ Flight::route('/', function(\flight\net\Route $route) { // Показывает псевдоним, назначенный этому маршруту $route->alias; -}, true);// <-- Этот true параметр делает это возможным +}, true);// <-- Этот параметр true делает это возможным ``` ### Группировка маршрутов и Middleware -Могут быть случаи, когда вы хотите сгруппировать связанные маршруты вместе (например, `/api/v1`). +Может быть время, когда вы хотите сгруппировать связанные маршруты вместе (например, `/api/v1`). Вы можете сделать это, используя метод `group`: ```php Flight::group('/api/v1', function () { Flight::route('/users', function () { - // Сопоставляет /api/v1/users + // Соответствует /api/v1/users }); Flight::route('/posts', function () { - // Сопоставляет /api/v1/posts + // Соответствует /api/v1/posts }); }); ``` @@ -428,24 +489,24 @@ Flight::group('/api/v1', function () { ```php Flight::group('/api', function () { Flight::group('/v1', function () { - // Flight::get() получает переменные, он не устанавливает маршрут! См. контекст объекта ниже + // Flight::get() получает переменные, он не устанавливает маршрут! Смотрите контекст объекта ниже Flight::route('GET /users', function () { - // Сопоставляет GET /api/v1/users + // Соответствует GET /api/v1/users }); Flight::post('/posts', function () { - // Сопоставляет POST /api/v1/posts + // Соответствует POST /api/v1/posts }); Flight::put('/posts/1', function () { - // Сопоставляет PUT /api/v1/posts + // Соответствует PUT /api/v1/posts }); }); Flight::group('/v2', function () { - // Flight::get() получает переменные, он не устанавливает маршрут! См. контекст объекта ниже + // Flight::get() получает переменные, он не устанавливает маршрут! Смотрите контекст объекта ниже Flight::route('GET /users', function () { - // Сопоставляет GET /api/v2/users + // Соответствует GET /api/v2/users }); }); }); @@ -462,11 +523,11 @@ $app->group('/api/v1', function (Router $router) { // используйте переменную $router $router->get('/users', function () { - // Сопоставляет GET /api/v1/users + // Соответствует GET /api/v1/users }); $router->post('/posts', function () { - // Сопоставляет POST /api/v1/posts + // Соответствует POST /api/v1/posts }); }); ``` @@ -480,12 +541,12 @@ $app->group('/api/v1', function (Router $router) { ```php Flight::group('/api/v1', function () { Flight::route('/users', function () { - // Сопоставляет /api/v1/users + // Соответствует /api/v1/users }); }, [ MyAuthMiddleware::class ]); // или [ new MyAuthMiddleware() ], если вы хотите использовать экземпляр ``` -См. больше деталей на странице [групповое middleware](/learn/middleware#grouping-middleware). +Смотрите больше деталей на странице [групповое middleware](/learn/middleware#grouping-middleware). ### Ресурсная маршрутизация Вы можете создать набор маршрутов для ресурса, используя метод `resource`. Это создаст набор маршрутов для ресурса, следующий RESTful-конвенциям. @@ -496,7 +557,7 @@ Flight::group('/api/v1', function () { Flight::resource('/users', UsersController::class); ``` -И в фоне это создаст следующие маршруты: +И что произойдет в фоне — это создание следующих маршрутов: ```php [ @@ -545,7 +606,7 @@ class UsersController } ``` -> **Примечание**: Вы можете просмотреть newly added routes с помощью `runway`, запустив `php runway routes`. +> **Примечание**: Вы можете просмотреть недавно добавленные маршруты с помощью `runway`, запустив `php runway routes`. #### Настройка ресурсных маршрутов @@ -554,15 +615,13 @@ class UsersController ##### Базовый псевдоним Вы можете настроить `aliasBase`. По умолчанию псевдоним — это последняя часть указанного URL. -Например, `/users/` приведет к `aliasBase` равному `users`. Когда эти маршруты создаются, -псевдонимы — `users.index`, `users.create` и т.д. Если вы хотите изменить псевдоним, установите `aliasBase` -в желаемое значение. +Например, `/users/` приведет к `aliasBase` равному `users`. Когда эти маршруты созданы, псевдонимы — `users.index`, `users.create` и т.д. Если вы хотите изменить псевдоним, установите `aliasBase` в желаемое значение. ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); ``` -##### Только и Исключая +##### Only и Except Вы также можете указать, какие маршруты вы хотите создать, используя опции `only` и `except`. @@ -580,7 +639,7 @@ Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'st ##### Middleware -Вы также можете указать middleware для выполнения на каждом из маршрутов, созданных методом `resource`. +Вы также можете указать middleware, которое будет выполняться на каждом из маршрутов, созданных методом `resource`. ```php Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]); @@ -588,15 +647,15 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid ### Потоковые ответы -Теперь вы можете передавать потоковые ответы клиенту, используя `stream()` или `streamWithHeaders()`. -Это полезно для отправки больших файлов, длительных процессов или генерации больших ответов. -Потоковая передача маршрута обрабатывается немного иначе, чем обычный маршрут. +Теперь вы можете передавать потоковые ответы клиенту с помощью `stream()` или `streamWithHeaders()`. +Это полезно для отправки больших файлов, долгосрочных процессов или генерации больших ответов. +Потоковый маршрут обрабатывается немного иначе, чем обычный маршрут. > **Примечание:** Потоковые ответы доступны только если у вас установлен [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) в `false`. #### Поток с ручными заголовками -Вы можете передать потоковый ответ клиенту, используя метод `stream()` на маршруте. Если вы +Вы можете передавать потоковый ответ клиенту, используя метод `stream()` на маршруте. Если вы делаете это, вы должны установить все заголовки вручную перед выводом чего-либо клиенту. Это делается с помощью функции php `header()` или метода `Flight::response()->setRealHeader()`. @@ -609,7 +668,7 @@ Flight::route('/@filename', function($filename) { $fileNameSafe = basename($filename); // Если у вас есть дополнительные заголовки для установки здесь после выполнения маршрута - // вы должны определить их до того, как что-либо выведено. + // вы должны определить их до того, как что-либо будет выведено. // Они должны быть прямым вызовом функции header() или // вызовом Flight::response()->setRealHeader() header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); @@ -627,16 +686,16 @@ Flight::route('/@filename', function($filename) { // или $response->setRealHeader('Content-Length: '.filesize($filePath)); - // Передайте файл клиенту по мере чтения + // Потоково передайте файл клиенту по мере чтения readfile($filePath); -// Это волшебная строка здесь +// Это магическая строка здесь })->stream(); ``` #### Поток с заголовками -Вы также можете использовать метод `streamWithHeaders()` для установки заголовков перед началом потоковой передачи. +Вы также можете использовать метод `streamWithHeaders()` для установки заголовков перед началом потока. ```php Flight::route('/stream-users', function() { @@ -660,7 +719,7 @@ Flight::route('/stream-users', function() { } echo '}'; -// Вот как вы установите заголовки перед началом потоковой передачи. +// Вот как вы установите заголовки перед началом потока. })->streamWithHeaders([ 'Content-Type' => 'application/json', 'Content-Disposition' => 'attachment; filename="users.json"', @@ -673,23 +732,22 @@ Flight::route('/stream-users', function() { - [Middleware](/learn/middleware) - Использование middleware с маршрутами для аутентификации, логирования и т.д. - [Внедрение зависимостей](/learn/dependency-injection-container) - Упрощение создания и управления объектами в маршрутах. - [Почему фреймворк?](/learn/why-frameworks) - Понимание преимуществ использования фреймворка вроде Flight. -- [Расширение](/learn/extending) - Как расширить Flight своей функциональностью, включая метод `notFound`. +- [Расширение](/learn/extending) - Как расширить Flight своей собственной функциональностью, включая метод `notFound`. - [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - Функция PHP для сопоставления регулярных выражений. ## Устранение неисправностей - Параметры маршрута сопоставляются по порядку, а не по имени. Убедитесь, что порядок параметров обратного вызова соответствует определению маршрута. - Использование `Flight::get()` не определяет маршрут; используйте `Flight::route('GET /...')` для маршрутизации или контекст объекта Router в группах (например, `$router->get(...)`). -- Свойство executedRoute устанавливается только после выполнения маршрута; до выполнения оно NULL. -- Потоковая передача требует отключения функциональности буферизации вывода Flight (`flight.v2.output_buffering = false`). +- Свойство executedRoute устанавливается только после выполнения маршрута; оно NULL до выполнения. +- Для потоковой передачи требуется отключить устаревшую функциональность буферизации вывода Flight (`flight.v2.output_buffering = false`). - Для внедрения зависимостей только определенные определения маршрутов поддерживают создание на основе контейнера. ### 404 Not Found или неожиданное поведение маршрута Если вы видите ошибку 404 Not Found (но вы клянетесь своей жизнью, что она действительно там и это не опечатка), это на самом деле может быть проблема -с возвратом значения в конечной точке маршрута вместо простого вывода его. Причина для этого намеренная, но может подкрасться к некоторым разработчикам. +с тем, что вы возвращаете значение в конечной точке маршрута вместо простого вывода. Причина в этом намеренная, но может подкрасться к некоторым разработчикам. ```php - Flight::route('/hello', function(){ // Это может вызвать ошибку 404 Not Found return 'Hello World'; @@ -699,12 +757,11 @@ Flight::route('/hello', function(){ Flight::route('/hello', function(){ echo 'Hello World'; }); - ``` -Причина в том, что в маршрутизаторе есть специальный механизм, который обрабатывает возвращаемый вывод как сигнал "перейти к следующему маршруту". -Вы можете увидеть поведение, документированное в разделе [Маршрутизация](/learn/routing#passing). +Причина в этом — специальный механизм, встроенный в роутер, который обрабатывает возвращаемый вывод как сигнал "перейти к следующему маршруту". +Вы можете увидеть поведение, описанное в разделе [Маршрутизация](/learn/routing#passing). ## Журнал изменений -- v3: Добавлена ресурсная маршрутизация, псевдонимы маршрутов, поддержка потоковой передачи, группы маршрутов и поддержка middleware. -- v1: Подавляющее большинство базовых функций доступно. \ No newline at end of file +- v3: Добавлена ресурсная маршрутизация, псевдонимы маршрутов и поддержка потоковой передачи, группы маршрутов и поддержка middleware. +- v1: Большинство базовых функций доступны. \ No newline at end of file diff --git a/content/v3/uk/awesome-plugins/apm.md b/content/v3/uk/awesome-plugins/apm.md index d8db20ea..809cfea3 100644 --- a/content/v3/uk/awesome-plugins/apm.md +++ b/content/v3/uk/awesome-plugins/apm.md @@ -1,41 +1,43 @@ # Документація FlightPHP APM -Ласкаво просимо до FlightPHP APM — ваш особистий тренер продуктивності для додатків! Цей посібник є вашою картою для налаштування, використання та освоєння моніторингу продуктивності застосунків (APM) з FlightPHP. Чи ви полюєте на повільні запити, чи просто хочете насолоджуватися графіками затримок, ми все охопили. Давайте зробимо ваш додаток швидшим, користувачів щасливішими та сеанси налагодження легшими! +Ласкаво просимо до FlightPHP APM — вашого особистого тренера продуктивності для додатку! Цей посібник — ваша дорожня карта для налаштування, використання та освоєння Application Performance Monitoring (APM) з FlightPHP. Чи то ви полюєте на повільні запити, чи просто хочете зануритися в графіки затримок, ми вас охоплюємо. Давайте зробимо ваш додаток швидшим, ваших користувачів щасливішими, а сесії налагодження — легкими! + +Перегляньте [демо](https://flightphp-docs-apm.sky-9.com/apm/dashboard) панелі керування для сайту Flight Docs. ![FlightPHP APM](/images/apm.png) ## Чому APM важливий -Уявіть: ваш додаток — це зайнятий ресторан. Без способу відстежувати, скільки часу займають замовлення або де кухня гальмує, ви просто вгадуєте, чому клієнти йдуть незадоволеними. APM — це ваш помічник-кухар: він стежить за кожним кроком, від вхідних запитів до запитів бази даних, і позначає все, що сповільнює вас. Повільні сторінки втрачають користувачів (дослідження показують, що 53% відмовляються, якщо сайт завантажується більше 3 секунд!), а APM допомагає виявити ці проблеми *до* того, як вони завдадуть шкоди. Це проактивний спокій — менше моментів "чому це зламане?", більше перемог "дивись, як це працює гладко!". +Уявіть: ваш додаток — це зайнятий ресторан. Без способу відстежувати, скільки часу займають замовлення чи де кухня гальмує, ви вгадуєте, чому клієнти йдуть незадоволеними. APM — ваш помічник на кухні: він стежить за кожним кроком, від вхідних запитів до запитів до бази даних, і позначає все, що вас сповільнює. Повільні сторінки втрачають користувачів (дослідження кажуть, що 53% відскакують, якщо сайт завантажується понад 3 секунди!), а APM допомагає вам ловити ці проблеми *до* того, як вони вжаліть. Це проактивний спокій — менше моментів «чому це зламано?», більше перемог «дивись, як гладко це працює!». ## Встановлення -Розпочніть з Composer: +Почніть з Composer: ```bash composer require flightphp/apm ``` Вам знадобиться: -- **PHP 7.4+**: Забезпечує сумісність з LTS-розподілами Linux, одночасно підтримуючи сучасний PHP. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Легковаговий фреймворк, який ми вдосконалюємо. +- **PHP 7.4+**: Забезпечує сумісність з LTS дистрибутивами Linux, підтримуючи сучасний PHP. +- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Легкий фреймворк, який ми посилюємо. ## Підтримувані бази даних -FlightPHP APM наразі підтримує такі бази даних для зберігання метрик: +FlightPHP APM зараз підтримує такі бази даних для зберігання метрик: -- **SQLite3**: Проста, на основі файлів, і відмінна для локальної розробки або малих додатків. Опція за замовчуванням у більшості налаштувань. -- **MySQL/MariaDB**: Ідеальна для більших проєктів або виробничих середовищ, де потрібне надійне, масштабоване сховище. +- **SQLite3**: Простий, на основі файлів, чудовий для локальної розробки чи малих додатків. Варіант за замовчуванням у більшості налаштувань. +- **MySQL/MariaDB**: Ідеальний для більших проєктів чи продакшн-середовищ, де потрібне надійне, масштабоване сховище. -Ви можете вибрати тип бази даних під час кроку налаштування (див. нижче). Переконайтеся, що ваше середовище PHP має встановлені необхідні розширення (наприклад, `pdo_sqlite` або `pdo_mysql`). +Ви можете обрати тип бази даних під час кроку конфігурації (див. нижче). Переконайтеся, що ваше середовище PHP має встановлені необхідні розширення (наприклад, `pdo_sqlite` чи `pdo_mysql`). ## Початок роботи -Ось ваш покроковий план до чудового APM: +Ось ваш покроковий шлях до крутості APM: ### 1. Зареєструйте APM -Додайте це до вашого `index.php` або файлу `services.php`, щоб розпочати відстеження: +Додайте це до вашого `index.php` чи файлу `services.php`, щоб почати відстеження: ```php use flight\apm\logger\LoggerFactory; @@ -46,37 +48,37 @@ $Apm = new Apm($ApmLogger); $Apm->bindEventsToFlightInstance($app); // Якщо ви додаєте з'єднання з базою даних -// Має бути PdoWrapper або PdoQueryCapture з розширень Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True потрібне, щоб увімкнути відстеження в APM. +// Має бути PdoWrapper або PdoQueryCapture з Tracy Extensions +$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True обов'язково для увімкнення відстеження в APM. $Apm->addPdoConnection($pdo); ``` **Що тут відбувається?** -- `LoggerFactory::create()` отримує вашу конфігурацію (про це скоро) і налаштовує логгер — SQLite за замовчуванням. +- `LoggerFactory::create()` бере вашу конфігурацію (більше про це незабаром) і налаштовує логер — SQLite за замовчуванням. - `Apm` — зірка: він слухає події Flight (запити, маршрути, помилки тощо) і збирає метрики. - `bindEventsToFlightInstance($app)` пов'язує все з вашим додатком Flight. -**Професійна порада: Зразок** -Якщо ваш додаток зайнятий, логування *кожного* запиту може перевантажити систему. Використовуйте коефіцієнт зразка (від 0.0 до 1.0): +**Про порада: Збірка зразків** +Якщо ваш додаток зайнятий, логування *кожного* запиту може перевантажити. Використовуйте рівень вибірки (від 0.0 до 1.0): ```php $Apm = new Apm($ApmLogger, 0.1); // Логує 10% запитів ``` -Це зберігає продуктивність швидкою, одночасно надаючи корисні дані. +Це тримає продуктивність жвавою, але все одно дає солідні дані. -### 2. Налаштуйте його +### 2. Налаштуйте це -Запустіть це, щоб створити ваш `.runway-config.json`: +Запустіть це, щоб створити `.runway-config.json`: ```bash php vendor/bin/runway apm:init ``` **Що це робить?** -- Запускає майстра, який запитує, звідки беруться сирі метрики (джерело) і куди йдуть оброблені дані (призначення). -- За замовчуванням — SQLite, наприклад, `sqlite:/tmp/apm_metrics.sqlite` для джерела, інше для призначення. -- Ви отримаєте конфігурацію, як-от: +- Запускає майстер, який запитує, звідки беруться сирі метрики (джерело) і куди йде оброблені дані (призначення). +- За замовчуванням SQLite — наприклад, `sqlite:/tmp/apm_metrics.sqlite` для джерела, інше для призначення. +- Ви отримаєте конфігурацію на кшталт: ```json { "apm": { @@ -88,123 +90,123 @@ php vendor/bin/runway apm:init } ``` -> Цей процес також запитає, чи ви хочете запустити міграції для цієї налаштування. Якщо ви налаштовуєте це вперше, відповідь — так. +> Цей процес також запитає, чи хочете ви запустити міграції для цього налаштування. Якщо це перше налаштування, відповідь — так. **Чому два місця?** -Сірі метрики накопичуються швидко (думайте про нефільтровані журнали). Робочий процес обробляє їх у структуроване призначення для панелі керування. Це тримає все в порядку! +Сирі метрики накопичуються швидко (уявіть нефільтровані логи). Робочий процес обробляє їх у структуроване призначення для панелі керування. Тримає все охайним! -### 3. Обробка метрик за допомогою робочого процесу +### 3. Обробіть метрики з Worker -Робочий процес перетворює сирі метрики на дані, готові для панелі. Запустіть його один раз: +Робочий процес перетворює сирі метрики на дані, готові для панелі керування. Запустіть один раз: ```bash php vendor/bin/runway apm:worker ``` -**Що це робить?** +**Що він робить?** - Читає з вашого джерела (наприклад, `apm_metrics.sqlite`). -- Обробляє до 100 метрик (розмір пакета за замовчуванням) у ваше призначення. -- Зупиняється, коли завершено або якщо метрик не залишилося. +- Обробляє до 100 метрик (розмір партії за замовчуванням) у ваше призначення. +- Зупиняється, коли завершено або якщо метрик не лишилося. -**Тримайте його в роботі** -Для живих додатків ви захочете безперервну обробку. Ось ваші опції: +**Тримайте його запущеним** +Для живих додатків ви захочете безперервну обробку. Ось ваші варіанти: -- **Режим демона**: +- **Режим Daemon**: ```bash php vendor/bin/runway apm:worker --daemon ``` - Працює вічно, обробляючи метрики, як вони приходять. Чудово для розробки або малих налаштувань. + Працює вічно, обробляючи метрики по мірі надходження. Чудово для розробки чи малих налаштувань. - **Crontab**: Додайте це до вашого crontab (`crontab -e`): ```bash * * * * * php /path/to/project/vendor/bin/runway apm:worker ``` - Запускається що хвилину — ідеально для виробництва. + Запускається щохвилини — ідеально для продакшну. - **Tmux/Screen**: - Запустіть відокремлену сесію: + Почніть відокремлену сесію: ```bash tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon - # Ctrl+B, потім D, щоб відокремитися; `tmux attach -t apm-worker`, щоб підключитися + # Ctrl+B, then D to detach; `tmux attach -t apm-worker` to reconnect ``` - Тримає його в роботі навіть якщо ви вийдете. + Тримає запущеним навіть якщо ви вийшли з логіну. -- **Власні налаштування**: +- **Кастомні налаштування**: ```bash php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 ``` - `--batch_size 50`: Обробляє 50 метрик за раз. - `--max_messages 1000`: Зупиняється після 1000 метрик. - - `--timeout 300`: Вийти після 5 хвилин. + - `--timeout 300`: Виходить після 5 хвилин. **Чому турбуватися?** -Без робочого процесу ваша панель керування порожня. Це міст між сирими журналами та корисними висновками. +Без робочого процесу ваша панель керування порожня. Це міст між сирими логами та корисними інсайтами. ### 4. Запустіть панель керування -Перегляньте життєво важливі показники вашого додатку: +Побачите життєві показники вашого додатку: ```bash php vendor/bin/runway apm:dashboard ``` **Що це?** -- Запускає сервер PHP на `http://localhost:8001/apm/dashboard`. -- Показує журнали запитів, повільні маршрути, рівень помилок і більше. +- Запускає PHP-сервер на `http://localhost:8001/apm/dashboard`. +- Показує логи запитів, повільні маршрути, рівень помилок і більше. **Налаштуйте це**: ```bash php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php ``` -- `--host 0.0.0.0`: Доступне з будь-якої IP (зручно для віддаленого перегляду). +- `--host 0.0.0.0`: Доступний з будь-якого IP (корисно для віддаленого перегляду). - `--port 8080`: Використовуйте інший порт, якщо 8001 зайнятий. - `--php-path`: Вкажіть на PHP, якщо його немає в PATH. -Відкрийте URL у своєму браузері та досліджуйте! +Відкрийте URL у браузері та досліджуйте! -#### Режим виробництва +#### Режим продакшну -Для виробництва вам може знадобитися спробувати кілька технік, щоб запустити панель керування, оскільки там, ймовірно, є брандмауери та інші заходи безпеки. Ось кілька опцій: +Для продакшну вам може знадобитися спробувати кілька технік, щоб запустити панель керування, оскільки, ймовірно, є фаєрволи та інші заходи безпеки. Ось кілька варіантів: -- **Використовуйте зворотний проксі**: Налаштуйте Nginx або Apache для переадресації запитів на панель. -- **SSH-тунель**: Якщо ви можете підключитися до сервера по SSH, використовуйте `ssh -L 8080:localhost:8001 youruser@yourserver`, щоб створити тунель панелі до вашого локального комп'ютера. -- **VPN**: Якщо ваш сервер за VPN, підключіться до нього та отримуйте доступ до панелі безпосередньо. -- **Налаштуйте брандмауер**: Відкрийте порт 8001 для вашого IP або мережі сервера (або будь-який порт, який ви встановили). -- **Налаштуйте Apache/Nginx**: Якщо у вас є веб-сервер перед додатком, ви можете налаштувати його на домен або піддомен. Якщо ви це зробите, встановіть корінь документів на `/path/to/your/project/vendor/flightphp/apm/dashboard`. +- **Використовуйте зворотний проксі**: Налаштуйте Nginx чи Apache для перенаправлення запитів до панелі керування. +- **SSH-тунель**: Якщо ви можете SSH на сервер, використовуйте `ssh -L 8080:localhost:8001 youruser@yourserver`, щоб тунелювати панель керування на вашу локальну машину. +- **VPN**: Якщо ваш сервер за VPN, підключіться до нього та отримайте доступ до панелі керування безпосередньо. +- **Налаштуйте фаєрвол**: Відкрийте порт 8001 для вашого IP чи мережі сервера. (або який порт ви встановили). +- **Налаштуйте Apache/Nginx**: Якщо у вас є веб-сервер перед додатком, ви можете налаштувати його на домен чи піддомен. Якщо ви це робите, ви встановите корінь документів на `/path/to/your/project/vendor/flightphp/apm/dashboard` -#### Хочете іншу панель? +#### Хочете іншу панель керування? -Ви можете створити власну панель, якщо хочете! Подивіться у директорії `vendor/flightphp/apm/src/apm/presenter` за ідеями, як представити дані для вашої власної панелі! +Ви можете побудувати свою власну панель керування, якщо хочете! Подивіться на директорію vendor/flightphp/apm/src/apm/presenter для ідей, як представити дані для вашої власної панелі керування! ## Функції панелі керування -Панель керування — це ваш штаб APM — ось що ви побачите: +Панель керування — ваш штаб APM: ось що ви побачите: -- **Журнал запитів**: Кожний запит з часом, URL, кодом відповіді та загальним часом. Натисніть "Деталі", щоб побачити проміжне програмне забезпечення, запити та помилки. -- **Найповільніші запити**: Топ-5 запитів, які займають багато часу (наприклад, "/api/heavy" за 2.5с). -- **Найповільніші маршрути**: Топ-5 маршрутів за середнім часом — чудово для виявлення шаблонів. -- **Рівень помилок**: Відсоток запитів, які завершуються невдачею (наприклад, 2.3% 500s). -- **Перцентили затримок**: 95-й (p95) і 99-й (p99) часи відповідей — знайте ваші найгірші сценарії. -- **Діаграма кодів відповідей**: Візуалізуйте 200s, 404s, 500s з часом. -- **Довгі запити/проміжне програмне забезпечення**: Топ-5 повільних викликів бази даних і шарів проміжного програмного забезпечення. -- **Влучання/промах кешу**: Наскільки часто ваш кеш рятує ситуацію. +- **Лог запитів**: Кожен запит з міткою часу, URL, кодом відповіді та загальним часом. Клікніть «Деталі» для middleware, запитів та помилок. +- **Найповільніші запити**: Топ 5 запитів, що займають час (наприклад, «/api/heavy» за 2.5с). +- **Найповільніші маршрути**: Топ 5 маршрутів за середнім часом — чудово для виявлення патернів. +- **Рівень помилок**: Відсоток невдалих запитів (наприклад, 2.3% 500s). +- **Перцентилі затримок**: 95-й (p95) та 99-й (p99) часи відповідей — знайте ваші найгірші сценарії. +- **Графік кодів відповідей**: Візуалізуйте 200s, 404s, 500s з часом. +- **Довгі запити/Middleware**: Топ 5 повільних викликів бази даних та шарів middleware. +- **Попадання/промах кешу**: Як часто ваш кеш рятує ситуацію. **Додатково**: -- Фільтруйте за "Останню годину", "Останній день" або "Останній тиждень". -- Перемикайте темний режим для нічних сеансів. +- Фільтруйте за «Останню годину», «Останній день» чи «Останній тиждень». +- Перемикайте темний режим для пізніх сесій. **Приклад**: Запит до `/users` може показати: -- Загальний час: 150мс -- Проміжне програмне забезпечення: `AuthMiddleware->handle` (50мс) -- Запит: `SELECT * FROM users` (80мс) -- Кеш: Влучання на `user_list` (5мс) +- Загальний час: 150ms +- Middleware: `AuthMiddleware->handle` (50ms) +- Запит: `SELECT * FROM users` (80ms) +- Кеш: Попадання на `user_list` (5ms) -## Додавання власних подій +## Додавання кастомних подій -Відстежуйте все — як виклик API або процес оплати: +Відстежуйте будь-що — як виклик API чи процес платежу: ```php use flight\apm\CustomEvent; @@ -217,9 +219,9 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ``` **Де це з'являється?** -У деталях запиту панелі під "Власні події" — розгортається з красивим форматуванням JSON. +У деталях запиту панелі керування під «Кастомні події» — розширюється з гарним форматуванням JSON. -**Приклад використання**: +**Випадок використання**: ```php $start = microtime(true); $apiResponse = file_get_contents('https://api.example.com/data'); @@ -229,42 +231,42 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -Тепер ви побачите, якщо цей API сповільнює ваш додаток! +Тепер ви побачите, чи той API тягне ваш додаток вниз! ## Моніторинг бази даних -Відстежуйте запити PDO ось так: +Відстежуйте PDO-запити ось так: ```php use flight\database\PdoWrapper; -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True потрібне, щоб увімкнути відстеження в APM. +$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True обов'язково для увімкнення відстеження в APM. $Apm->addPdoConnection($pdo); ``` **Що ви отримуєте**: - Текст запиту (наприклад, `SELECT * FROM users WHERE id = ?`) -- Час виконання (наприклад, 0.015с) +- Час виконання (наприклад, 0.015s) - Кількість рядків (наприклад, 42) **Увага**: -- **Опційно**: Пропустіть це, якщо вам не потрібне відстеження БД. -- **Тільки PdoWrapper**: Основний PDO ще не підключений — слідкуйте за оновленнями! -- **Попередження про продуктивність**: Логування кожного запиту на сайті з важкою БД може сповільнити все. Використовуйте зразок (`$Apm = new Apm($ApmLogger, 0.1)`), щоб зменшити навантаження. +- **Опціонально**: Пропустіть це, якщо не потрібно відстеження БД. +- **Тільки PdoWrapper**: Основний PDO ще не підключений — чекайте! +- **Попередження про продуктивність**: Логування кожного запиту на БД-важкому сайті може сповільнити. Використовуйте вибірку (`$Apm = new Apm($ApmLogger, 0.1)`), щоб полегшити навантаження. -**Приклад виведення**: +**Приклад виводу**: - Запит: `SELECT name FROM products WHERE price > 100` -- Час: 0.023с +- Час: 0.023s - Рядки: 15 -## Опції робочого процесу +## Опції Worker Налаштуйте робочий процес на свій смак: - `--timeout 300`: Зупиняється після 5 хвилин — добре для тестування. -- `--max_messages 500`: Обмежує 500 метрик — тримає це скінченним. +- `--max_messages 500`: Обмежує 500 метриками — тримає скінченним. - `--batch_size 200`: Обробляє 200 за раз — балансує швидкість і пам'ять. -- `--daemon`: Працює без зупину — ідеально для живого моніторингу. +- `--daemon`: Працює без зупинки — ідеально для живого моніторингу. **Приклад**: ```bash @@ -272,17 +274,17 @@ php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ``` Працює годину, обробляючи 100 метрик за раз. -## ID запиту в додатку +## Request ID у додатку -Кожний запит має унікальний ID запиту для відстеження. Ви можете використовувати цей ID у своєму додатку, щоб корелювати журнали та метрики. Наприклад, ви можете додати ID запиту до сторінки помилок: +Кожен запит має унікальний ID запиту для відстеження. Ви можете використовувати цей ID у своєму додатку для кореляції логів і метрик. Наприклад, ви можете додати ID запиту на сторінку помилки: ```php Flight::map('error', function($message) { // Отримайте ID запиту з заголовка відповіді X-Flight-Request-Id $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - // Крім того, ви могли б отримати його з змінної Flight - // Цей метод не працюватиме добре в swoole або інших асинхронних платформах. + // Додатково ви можете отримати його з змінної Flight + // Цей метод не працюватиме добре в swoole чи інших асинхронних платформах. // $requestId = Flight::get('apm.request_id'); echo "Error: $message (Request ID: $requestId)"; @@ -296,50 +298,50 @@ Flight::map('error', function($message) { ```bash php vendor/bin/runway apm:migrate ``` -Це запустить будь-які необхідні міграції, щоб оновити схему бази даних до останньої версії. +Це запустить будь-які необхідні міграції для оновлення схеми бази даних до останньої версії. -**Примітка:** Якщо ваша база даних APM велика, ці міграції можуть зайняти деякий час. Ви можете запустити цю команду під час непікового часу. +**Примітка:** Якщо ваша база даних APM велика за розміром, ці міграції можуть зайняти деякий час. Ви можете запустити цю команду під час непікових годин. ## Очищення старих даних -Щоб тримати вашу базу даних в порядку, ви можете очистити старі дані. Це особливо корисно, якщо ви запускаєте зайнятий додаток і хочете тримати розмір бази керованим. +Щоб тримати вашу базу даних охайною, ви можете очистити старі дані. Це особливо корисно, якщо ви ведете зайнятий додаток і хочете тримати розмір бази даних керованою. Ви можете зробити це, запустивши таку команду: ```bash php vendor/bin/runway apm:purge ``` -Це видалить всі дані старші за 30 днів з бази. Ви можете налаштувати кількість днів, передаючи інше значення опції `--days`: +Це видалить усі дані старші за 30 днів з бази даних. Ви можете скоригувати кількість днів, передавши інше значення опції `--days`: ```bash php vendor/bin/runway apm:purge --days 7 ``` -Це видалить всі дані старші за 7 днів з бази. +Це видалить усі дані старші за 7 днів з бази даних. -## Усунення проблем +## Вирішення проблем -Зависли? Спробуйте ці: +Застрягли? Спробуйте ці: -- **Немає даних на панелі?** - - Чи працює робочий процес? Перевірте `ps aux | grep apm:worker`. +- **Немає даних у панелі керування?** + - Чи запущений робочий процес? Перевірте `ps aux | grep apm:worker`. - Шляхи конфігурації збігаються? Перевірте, чи DSN у `.runway-config.json` вказують на реальні файли. - - Запустіть `php vendor/bin/runway apm:worker` вручну, щоб обробити очікувані метрики. + - Запустіть `php vendor/bin/runway apm:worker` вручну для обробки очікуваних метрик. - **Помилки робочого процесу?** - - Погляньте на ваші файли SQLite (наприклад, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Перевірте журнали PHP на стек-треси. + - Подивіться на ваші SQLite-файли (наприклад, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). + - Перевірте логи PHP на стек-трейси. -- **Панель не запускається?** +- **Панель керування не запускається?** - Порт 8001 зайнятий? Використовуйте `--port 8080`. - PHP не знайдено? Використовуйте `--php-path /usr/bin/php`. - - Брандмауер блокує? Відкрийте порт або використовуйте `--host localhost`. + - Фаєрвол блокує? Відкрийте порт або використовуйте `--host localhost`. - **Занадто повільно?** - - Зменшіть коефіцієнт зразка: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Зменшіть розмір пакета: `--batch_size 20`. + - Зменште рівень вибірки: `$Apm = new Apm($ApmLogger, 0.05)` (5%). + - Зменште розмір партії: `--batch_size 20`. - **Не відстежує винятки/помилки?** - - Якщо у вас увімкнено [Tracy](https://tracy.nette.org/) для вашого проєкту, це перевизначить обробку помилок Flight. Вам потрібно вимкнути Tracy і переконатися, що `Flight::set('flight.handle_errors', true);` встановлено. + - Якщо у вас увімкнено [Tracy](https://tracy.nette.org/) для проєкту, це перекриє обробку помилок Flight. Вам потрібно вимкнути Tracy і переконатися, що `Flight::set('flight.handle_errors', true);` встановлено. -- **Не відстежує запити бази даних?** +- **Не відстежує запити до бази даних?** - Переконайтеся, що ви використовуєте `PdoWrapper` для з'єднань з базою даних. - Переконайтеся, що останній аргумент у конструкторі — `true`. \ No newline at end of file diff --git a/content/v3/uk/learn/ai.md b/content/v3/uk/learn/ai.md index b63f085e..02f8c884 100644 --- a/content/v3/uk/learn/ai.md +++ b/content/v3/uk/learn/ai.md @@ -2,20 +2,20 @@ ## Огляд -Flight полегшує суперзарядку ваших PHP-проектів за допомогою інструментів на базі ШІ та сучасних робочих процесів розробників. З вбудованими командами для підключення до постачальників LLM (Велика мовна модель) та генерації проектно-специфічних інструкцій для кодування з ШІ, Flight допомагає вам і вашій команді отримати максимум від асистентів ШІ, таких як GitHub Copilot, Cursor та Windsurf. +Flight полегшує прискорення ваших PHP-проектів за допомогою інструментів на основі ШІ та сучасних робочих процесів розробників. З вбудованими командами для підключення до постачальників LLM (Велика мовна модель) та генерації проектно-специфічних інструкцій для кодування ШІ, Flight допомагає вам і вашій команді отримати максимум від асистентів ШІ, таких як GitHub Copilot, Cursor та Windsurf. ## Розуміння -Асистенти для кодування з ШІ найбільш корисні, коли вони розуміють контекст вашого проекту, конвенції та цілі. Допоміжники ШІ від Flight дозволяють вам: +Асистенти для кодування ШІ найбільш корисні, коли вони розуміють контекст вашого проекту, конвенції та цілі. Допоміжники ШІ від Flight дозволяють вам: - Підключити ваш проект до популярних постачальників LLM (OpenAI, Grok, Claude тощо) - Генерувати та оновлювати проектно-специфічні інструкції для інструментів ШІ, щоб кожен отримував послідовну, релевантну допомогу - Зберігати вашу команду узгодженою та продуктивною, витрачаючи менше часу на пояснення контексту Ці функції вбудовані в основний CLI Flight та офіційний стартовий проект [flightphp/skeleton](https://github.com/flightphp/skeleton). -## Базове використання +## Основне використання -### 1. Налаштування облікових даних LLM +### Налаштування облікових даних LLM Команда `ai:init` проведе вас через процес підключення вашого проекту до постачальника LLM. @@ -28,39 +28,39 @@ php runway ai:init - Ввести ваш API-ключ - Встановити базовий URL та назву моделі -Це створює файл `.runway-creds.json` в корені вашого проекту (і забезпечує його додавання до `.gitignore`). +Це створює файл `.runway-creds.json` у корені вашого проекту (і забезпечує його додавання до `.gitignore`). **Приклад:** ``` -Ласкаво просимо до AI Init! -Який LLM API ви хочете використовувати? [1] openai, [2] grok, [3] claude: 1 -Введіть базовий URL для LLM API [https://api.openai.com]: -Введіть ваш API-ключ для openai: sk-... -Введіть назву моделі, яку ви хочете використовувати (наприклад, gpt-4, claude-3-opus тощо) [gpt-4o]: -Облікові дані збережено в .runway-creds.json +Welcome to AI Init! +Which LLM API do you want to use? [1] openai, [2] grok, [3] claude: 1 +Enter the base URL for the LLM API [https://api.openai.com]: +Enter your API key for openai: sk-... +Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: +Credentials saved to .runway-creds.json ``` -### 2. Генерація проектно-специфічних інструкцій для ШІ +### Генерація проектно-специфічних інструкцій ШІ -Команда `ai:generate-instructions` допомагає створити або оновити інструкції для асистентів кодування з ШІ, адаптовані до вашого проекту. +Команда `ai:generate-instructions` допомагає створити або оновити інструкції для асистентів кодування ШІ, адаптовані до вашого проекту. ```bash php runway ai:generate-instructions ``` -Ви відповість на кілька запитань про ваш проект (опис, база даних, шаблонізація, безпека, розмір команди тощо). Flight використовує ваш постачальник LLM для генерації інструкцій, а потім записує їх до: +Ви відповість на кілька питань про ваш проект (опис, база даних, шаблонізація, безпека, розмір команди тощо). Flight використовує ваш постачальник LLM для генерації інструкцій, а потім записує їх до: - `.github/copilot-instructions.md` (для GitHub Copilot) - `.cursor/rules/project-overview.mdc` (для Cursor) - `.windsurfrules` (для Windsurf) **Приклад:** ``` -Будь ласка, опишіть, для чого ваш проект? Мій крутий API -Яку базу даних ви плануєте використовувати? MySQL -Який HTML-движок шаблонізації ви плануєте використовувати (якщо є)? latte -Чи є безпека важливим елементом цього проекту? (y/n) y +Please describe what your project is for? My awesome API +What database are you planning on using? MySQL +What HTML templating engine will you plan on using (if any)? latte +Is security an important element of this project? (y/n) y ... -Інструкції ШІ успішно оновлено. +AI instructions updated successfully. ``` Тепер ваші інструменти ШІ надаватимуть розумніші, більш релевантні пропозиції на основі реальних потреб вашого проекту. @@ -69,18 +69,18 @@ php runway ai:generate-instructions - Ви можете налаштувати розташування файлів з обліковими даними або інструкціями за допомогою опцій команди (див. `--help` для кожної команди). - Допоміжники ШІ розроблені для роботи з будь-яким постачальником LLM, який підтримує API, сумісні з OpenAI. -- Якщо ви хочете оновити інструкції з еволюцією вашого проекту, просто повторно запустіть `ai:generate-instructions` та відповідайте на запити знову. +- Якщо ви хочете оновити ваші інструкції з еволюцією проекту, просто повторно запустіть `ai:generate-instructions` та відповідайте на запити знову. ## Див. також - [Flight Skeleton](https://github.com/flightphp/skeleton) – Офіційний стартер з інтеграцією ШІ -- [Runway CLI](/awesome-plugins/runway) – Більше про інструмент CLI, що живить ці команди +- [Runway CLI](/awesome-plugins/runway) – Більше про інструмент CLI, який живить ці команди ## Вирішення проблем - Якщо ви бачите "Missing .runway-creds.json", спочатку запустіть `php runway ai:init`. - Переконайтеся, що ваш API-ключ дійсний і має доступ до вибраної моделі. -- Якщо інструкції не оновлюються, перевірте дозволи на файли в каталозі вашого проекту. +- Якщо інструкції не оновлюються, перевірте дозволи на файли у вашому проектному каталозі. ## Журнал змін diff --git a/content/v3/uk/learn/requests.md b/content/v3/uk/learn/requests.md index 0aff89f5..d6b7b8a5 100644 --- a/content/v3/uk/learn/requests.md +++ b/content/v3/uk/learn/requests.md @@ -10,9 +10,9 @@ $request = Flight::request(); ## Розуміння -HTTP-запити є одним з ключових аспектів, які потрібно розуміти щодо життєвого циклу HTTP. Користувач виконує дію в веб-браузері або HTTP-клієнті, і вони надсилають серію заголовків, тіла, URL тощо до вашого проекту. Ви можете захоплювати ці заголовки (мова браузера, тип стиснення, який вони можуть обробляти, user agent тощо) і захоплювати тіло та URL, що надсилаються до вашої програми Flight. Ці запити є суттєвими для вашої програми, щоб зрозуміти, що робити далі. +HTTP-запити є одним з основних аспектів, які потрібно розуміти про життєвий цикл HTTP. Користувач виконує дію в веб-браузері або HTTP-клієнті, і вони надсилають серію заголовків, тіла, URL тощо до вашого проекту. Ви можете захоплювати ці заголовки (мова браузера, тип стиснення, який вони можуть обробляти, user agent тощо) і захоплювати тіло та URL, що надсилається до вашої програми Flight. Ці запити є суттєвими для вашої програми, щоб зрозуміти, що робити далі. -## Основне використання +## Базове використання PHP має кілька суперглобальних змінних, включаючи `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` та `$_COOKIE`. Flight абстрагує їх у зручні [Collections](/learn/collections). Ви можете отримати доступ до властивостей `query`, `data`, `cookies` та `files` як до масивів або об'єктів. @@ -107,7 +107,7 @@ Flight::route('POST /upload', function(){ }); ``` -Якщо у вас завантажено кілька файлів, ви можете перебирати їх: +Якщо у вас завантажено кілька файлів, ви можете перебрати їх: ```php Flight::route('POST /upload', function(){ @@ -119,11 +119,11 @@ Flight::route('POST /upload', function(){ }); ``` -> **Примітка щодо безпеки:** Завжди валідуйте та очищайте введення користувача, особливо при роботі з завантаженням файлів. Завжди валідуйте тип розширень, які ви дозволите завантажувати, але також валідуйте "магічні байти" файлу, щоб переконатися, що це дійсно тип файлу, який заявляє користувач. Є [статті](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [та](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [бібліотеки](https://github.com/RikudouSage/MimeTypeDetector), доступні для допомоги з цим. +> **Примітка щодо безпеки:** Завжди валідуйте та очищайте вхідні дані користувача, особливо при роботі з завантаженням файлів. Завжди валідуйте типи розширень, які ви дозволите завантажувати, але ви також повинні валідувати "магічні байти" файлу, щоб переконатися, що це дійсно тип файлу, який стверджує користувач. Є [статті](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [та](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [бібліотеки](https://github.com/RikudouSage/MimeTypeDetector), доступні для допомоги з цим. ### Тіло запиту -Щоб отримати сире тіло HTTP-запиту, наприклад, при роботі з POST/PUT запитами, +Щоб отримати сире тіло HTTP-запиту, наприклад, при роботі з POST/PUT-запитами, ви можете зробити: ```php @@ -135,7 +135,7 @@ Flight::route('POST /users/xml', function(){ ### JSON тіло -Якщо ви отримуєте запит з типом вмісту `application/json` та прикладом даних `{"id": 123}` +Якщо ви отримуєте запит з типом вмісту `application/json` і прикладом даних `{"id": 123}` воно буде доступне з властивості `data`: ```php @@ -169,7 +169,7 @@ $method = Flight::request()->getMethod(); ``` **Примітка:** Метод `getMethod()` спочатку витягує метод з `$_SERVER['REQUEST_METHOD']`, потім його можна перезаписати -`$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']`, якщо він існує, або `$_REQUEST['_method']`, якщо він існує. +за допомогою `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']`, якщо він існує, або `$_REQUEST['_method']`, якщо він існує. ## Властивості об'єкта запиту @@ -177,7 +177,7 @@ $method = Flight::request()->getMethod(); - **body** - Сире тіло HTTP-запиту - **url** - URL, що запитується -- **base** - Батьківська піддиректорія URL +- **base** - Батьківська підкаталог URL - **method** - Метод запиту (GET, POST, PUT, DELETE) - **referrer** - URL реферера - **ip** - IP-адреса клієнта @@ -187,18 +187,18 @@ $method = Flight::request()->getMethod(); - **type** - Тип вмісту - **length** - Довжина вмісту - **query** - Параметри рядка запиту -- **data** - Дані POST або JSON-даних +- **data** - Дані POST або JSON-дані - **cookies** - Дані cookie - **files** - Завантажені файли - **secure** - Чи є з'єднання безпечним - **accept** - Параметри HTTP accept -- **proxy_ip** - IP-адреса проксі клієнта. Сканує масив `$_SERVER` на наявність `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` в такому порядку. +- **proxy_ip** - IP-адреса проксі клієнта. Сканує масив `$_SERVER` на `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` в такому порядку. - **host** - Ім'я хоста запиту - **servername** - SERVER_NAME з `$_SERVER` -## Допоміжні методи URL +## Допоміжні методи -Є кілька допоміжних методів для збирання частин URL для вашої зручності. +Є кілька допоміжних методів для складання частин URL або роботи з певними заголовками. ### Повний URL @@ -219,15 +219,38 @@ $url = Flight::request()->getBaseUrl(); // Notice, no trailing slash. ``` -## Парсинг запитів +## Парсинг запиту -Ви можете передати URL до методу `parseQuery()`, щоб розпарсити рядок запиту в асоціативний масив: +Ви можете передати URL методу `parseQuery()`, щоб розпарсити рядок запиту в асоціативний масив: ```php $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` +## Переговори щодо типів прийнятого вмісту + +_v3.17.2_ + +Ви можете використовувати метод `negotiateContentType()`, щоб визначити найкращий тип вмісту для відповіді на основі заголовка `Accept`, надісланого клієнтом. + +```php + +// Example Accept header: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// The below defines what you support. +$availableTypes = ['application/json', 'application/xml']; +$typeToServe = Flight::request()->negotiateContentType($availableTypes); +if ($typeToServe === 'application/json') { + // Serve JSON response +} elseif ($typeToServe === 'application/xml') { + // Serve XML response +} else { + // Default to something else or throw an error +} +``` + +> **Примітка:** Якщо жоден з доступних типів не знайдено в заголовку `Accept`, метод поверне `null`. Якщо заголовок `Accept` не визначено, метод поверне перший тип у масиві `$availableTypes`. + ## Дивіться також - [Routing](/learn/routing) - Дивіться, як відображати маршрути на контролери та рендерити види. - [Responses](/learn/responses) - Як налаштовувати HTTP-відповіді. @@ -235,9 +258,10 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); - [Collections](/learn/collections) - Робота з колекціями даних. - [Uploaded File Handler](/learn/uploaded-file) - Обробка завантаження файлів. -## Вирішення проблем +## Усунення несправностей - `request()->ip` та `request()->proxy_ip` можуть відрізнятися, якщо ваш веб-сервер стоїть за проксі, балансувальником навантаження тощо. ## Журнал змін +- v3.17.2 - Додано negotiateContentType() - v3.12.0 - Додано можливість обробки завантаження файлів через об'єкт запиту. -- v1.0 - Початковий реліз. \ No newline at end of file +- v1.0 - Початкове випущення. \ No newline at end of file diff --git a/content/v3/uk/learn/responses.md b/content/v3/uk/learn/responses.md index 98f2eba2..fb7a0391 100644 --- a/content/v3/uk/learn/responses.md +++ b/content/v3/uk/learn/responses.md @@ -2,11 +2,11 @@ ## Огляд -Flight допомагає генерувати частину заголовків відповіді для вас, але ви контролюєте більшість того, що надсилаєте користувачеві. Більшість часу ви отримуєте доступ до об'єкта `response()` напряму, але Flight має деякі допоміжні методи для встановлення деяких заголовків відповіді для вас. +Flight допомагає генерувати частину заголовків відповіді для вас, але ви маєте більший контроль над тим, що ви надсилаєте назад користувачеві. Більшість часу ви звертатиметесь безпосередньо до об'єкта `response()`, але Flight має деякі допоміжні методи для встановлення деяких заголовків відповіді для вас. ## Розуміння -Після того, як користувач надсилає свій [запит](/learn/requests) до вашого додатка, вам потрібно генерувати правильну відповідь для них. Вони надіслали вам інформацію, таку як мова, яку вони віддають перевагу, чи можуть вони обробляти певні типи стиснення, їхній user agent тощо, і після обробки всього настав час надіслати їм правильну відповідь. Це може бути встановлення заголовків, вивід тіла HTML або JSON для них, або перенаправлення на сторінку. +Після того, як користувач надсилає свій [запит](/learn/requests) до вашого додатка, вам потрібно генерувати правильну відповідь для них. Вони надіслали вам інформацію, таку як мова, яку вони віддають перевагу, чи можуть вони обробляти певні типи стиснення, їхній агент користувача тощо, і після обробки всього настав час надіслати їм назад правильну відповідь. Це може бути встановлення заголовків, вивід тіла HTML або JSON для них або перенаправлення їх на сторінку. ## Основне використання @@ -33,7 +33,7 @@ Flight::route('/', function() { // Це надішле "Hello, World!" до браузера користувача Flight::route('/', function() { - // багатослівно, але іноді потрібно для виконання завдання + // детально, але іноді потрібно для виконання роботи Flight::response()->write("Hello, World!"); // якщо ви хочете отримати тіло, яке ви встановили на цьому етапі @@ -44,16 +44,16 @@ Flight::route('/', function() { ### JSON -Flight надає підтримку для надсилання JSON та JSONP відповідей. Щоб надіслати JSON відповідь, ви передаєте деякі дані для кодування в JSON: +Flight надає підтримку для надсилання JSON та JSONP відповідей. Щоб надіслати JSON відповідь, ви передаєте деякі дані для кодування JSON: ```php Flight::route('/@companyId/users', function(int $companyId) { - // якось витягніть ваших користувачів з бази даних, наприклад + // якось витягніть своїх користувачів з бази даних, наприклад $users = Flight::db()->fetchAll("SELECT id, first_name, last_name FROM users WHERE company_id = ?", [ $companyId ]); Flight::json($users); }); -// [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* більше користувачів */ ] +// [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* more users */ ] ``` > **Примітка:** За замовчуванням Flight надішле заголовок `Content-Type: application/json` з відповіддю. Він також використовуватиме прапорці `JSON_THROW_ON_ERROR` та `JSON_UNESCAPED_SLASHES` під час кодування JSON. @@ -66,9 +66,9 @@ Flight::route('/@companyId/users', function(int $companyId) { Flight::json(['id' => 123], 201); ``` -#### JSON з гарним виводом +#### JSON з красивим виводом -Ви також можете передати аргумент в останню позицію для увімкнення гарного виведення: +Ви також можете передати аргумент в останню позицію для увімкнення красивого виведення: ```php Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT); @@ -76,7 +76,7 @@ Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT); #### Зміна порядку аргументів JSON -`Flight::json()` — це дуже застарілий метод, але мета Flight — підтримувати зворотну сумісність для проєктів. Насправді це дуже просто, якщо ви хочете переробити порядок аргументів для використання простішого синтаксису, ви можете просто переналаштувати метод JSON [як будь-який інший метод Flight](/learn/extending): +`Flight::json()` є дуже застарілим методом, але мета Flight — підтримувати зворотну сумісність для проєктів. Насправді це дуже просто, якщо ви хочете переробити порядок аргументів для використання простішого синтаксису, ви можете просто переналаштувати метод JSON [як будь-який інший метод Flight](/learn/extending): ```php Flight::map('json', function($data, $code = 200, $options = 0) { @@ -89,11 +89,11 @@ Flight::map('json', function($data, $code = 200, $options = 0) { Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT); ``` -#### JSON і зупинка виконання +#### JSON та зупинка виконання _v3.10.0_ -Якщо ви хочете надіслати JSON відповідь і зупинити виконання, ви можете використовувати метод `jsonHalt()`. Це корисно для випадків, коли ви перевіряєте, можливо, якийсь тип авторизації, і якщо користувач не авторизований, ви можете надіслати JSON відповідь негайно, очистити існуючий вміст тіла та зупинити виконання. +Якщо ви хочете надіслати JSON відповідь і зупинити виконання, ви можете використовувати метод `jsonHalt()`. Це корисно для випадків, коли ви перевіряєте, можливо, якийсь тип авторизації, і якщо користувач не авторизований, ви можете негайно надіслати JSON відповідь, очистити існуючий вміст тіла та зупинити виконання. ```php Flight::route('/users', function() { @@ -108,7 +108,7 @@ Flight::route('/users', function() { }); ``` -До v3.10.0 ви б мусили робити щось на кшталт цього: +До v3.10.0 ви б мусили зробити щось на кшталт цього: ```php Flight::route('/users', function() { @@ -136,7 +136,7 @@ Flight::route('/', function() { }); ``` -Випадок використання вище, ймовірно, не є поширеним, однак він може бути більш поширеним, якщо це використовується в [middleware](/learn/middleware). +Випадок використання вище, ймовірно, не є поширеним, однак він міг би бути більш поширеним, якщо це використовувалося в [middleware](/learn/middleware). ### Виконання зворотного виклику на тілі відповіді @@ -155,7 +155,7 @@ Flight::response()->addResponseBodyCallback(function($body) { }); ``` -Ви можете додати кілька зворотних викликів, і вони виконуватимуться в порядку їх додавання. Оскільки це може приймати будь-який [викликаний](https://www.php.net/manual/en/language.types.callable.php), він може приймати масив класу `[ $class, 'method' ]`, замикання `$strReplace = function($body) { str_replace('hi', 'there', $body); };`, або ім'я функції `'minify'`, якщо у вас є функція для мініфікації вашого HTML коду, наприклад. +Ви можете додати кілька зворотних викликів, і вони виконуватимуться в порядку, в якому вони були додані. Оскільки це може приймати будь-який [викликаний](https://www.php.net/manual/en/language.types.callable.php), він може приймати масив класу `[ $class, 'method' ]`, замикання `$strReplace = function($body) { str_replace('hi', 'there', $body); };`, або ім'я функції `'minify'`, якщо у вас є функція для мініфікації вашого HTML коду, наприклад. **Примітка:** Зворотні виклики маршрутів не працюватимуть, якщо ви використовуєте опцію конфігурації `flight.v2.output_buffering`. @@ -219,7 +219,7 @@ Flight::route('/@id', function($id) { }); ``` -Якщо ви хочете отримати поточний код статусу, ви можете використовувати метод `status` без жодних аргументів: +Якщо ви хочете отримати поточний код статусу, ви можете використовувати метод `status` без будь-яких аргументів: ```php Flight::response()->status(); // 200 @@ -230,7 +230,7 @@ Flight::response()->status(); // 200 Ви можете встановити заголовок, такий як тип вмісту відповіді, використовуючи метод `header`: ```php -// Це надішле "Hello, World!" до браузера користувача у вигляді звичайного тексту +// Це надішле "Hello, World!" до браузера користувача як звичайний текст Flight::route('/', function() { Flight::response()->header('Content-Type', 'text/plain'); // або @@ -286,7 +286,7 @@ Flight::halt(200, 'Be right back...'); Flight::stop($httpStatusCode = null); ``` -> **Примітка:** `Flight::stop()` має деяку дивну поведінку, таку як вивід відповіді, але продовження виконання вашого скрипту, що може бути не тим, чого ви хочете. Ви можете використовувати `exit` або `return` після виклику `Flight::stop()`, щоб запобігти подальшому виконанню, але загалом рекомендується використовувати `Flight::halt()`. +> **Примітка:** `Flight::stop()` має деяку дивну поведінку, таку як вивід відповіді, але продовження виконання вашого скрипту, що може не бути тим, чого ви хочете. Ви можете використовувати `exit` або `return` після виклику `Flight::stop()` для запобігання подальшому виконанню, але загалом рекомендується використовувати `Flight::halt()`. Це збереже ключ і значення заголовка в об'єкті відповіді. Наприкінці циклу життя запиту він побудує заголовки та надішле відповідь. @@ -307,19 +307,19 @@ Flight::route('/', function() { ### JSONP -Для JSONP запитів ви можете опціонально передати ім'я параметра запиту, яке ви використовуєте для визначення вашої функції зворотного виклику: +Для JSONP запитів ви можете опціонально передати назву параметра запиту, який ви використовуєте для визначення вашої функції зворотного виклику: ```php Flight::jsonp(['id' => 123], 'q'); ``` -Отже, коли робите GET запит за допомогою `?q=my_func`, ви повинні отримати вивід: +Отже, коли робиться GET запит за допомогою `?q=my_func`, ви повинні отримати вивід: ```javascript my_func({"id":123}); ``` -Якщо ви не передасте ім'я параметра запиту, воно за замовчуванням буде `jsonp`. +Якщо ви не передасте назву параметра запиту, він за замовчуванням буде `jsonp`. > **Примітка:** Якщо ви все ще використовуєте JSONP запити в 2025 році та пізніше, приєднуйтеся до чату та розкажіть нам чому! Нам подобається чути хороші історії битв/жахів! @@ -343,15 +343,15 @@ Flight::response()->clearBody(); ### Кешування HTTP -Flight надає вбудовану підтримку для кешування на рівні HTTP. Якщо умова кешування виконана, Flight поверне HTTP `304 Not Modified` відповідь. Наступного разу, коли клієнт запитає той самий ресурс, йому буде запропоновано використовувати локально закешовану версію. +Flight надає вбудовану підтримку для кешування на рівні HTTP. Якщо умова кешування виконана, Flight поверне HTTP відповідь `304 Not Modified`. Наступного разу, коли клієнт запитує той самий ресурс, йому буде запропоновано використовувати локально кешовану версію. #### Кешування на рівні маршруту -Якщо ви хочете закешувати всю вашу відповідь, ви можете використовувати метод `cache()` і передати час для кешування. +Якщо ви хочете кешувати всю вашу відповідь, ви можете використовувати метод `cache()` і передати час для кешування. ```php -// Це закешує відповідь на 5 хвилин +// Це кешуватиме відповідь на 5 хвилин Flight::route('/news', function () { Flight::response()->cache(time() + 300); echo 'This content will be cached.'; @@ -387,7 +387,7 @@ Flight::route('/news', function () { }); ``` -Пам'ятайте, що виклик як `lastModified`, так і `etag` встановить і перевірить значення кешу. Якщо значення кешу однакове між запитами, Flight негайно надішле `HTTP 304` відповідь і зупинить обробку. +Пам'ятайте, що виклик як `lastModified`, так і `etag` обидва встановлять і перевірять значення кешу. Якщо значення кешу однакове між запитами, Flight негайно надішле відповідь `HTTP 304` і зупинить обробку. ### Завантаження файлу @@ -398,21 +398,24 @@ _v3.12.0_ ```php Flight::route('/download', function () { Flight::download('/path/to/file.txt'); + // Починаючи з v3.17.1 ви можете вказати власну назву файлу для завантаження + Flight::download('/path/to/file.txt', 'custom_name.txt'); }); ``` ## Дивіться також -- [Маршрутизація](/learn/routing) — Як зіставляти маршрути з контролерами та рендерити перегляди. -- [Запити](/learn/requests) — Розуміння, як обробляти вхідні запити. -- [Middleware](/learn/middleware) — Використання middleware з маршрутами для автентифікації, логування тощо. -- [Чому фреймворк?](/learn/why-frameworks) — Розуміння переваг використання фреймворку, як Flight. -- [Розширення](/learn/extending) — Як розширювати Flight власною функціональністю. +- [Маршрутизація](/learn/routing) - Як зіставляти маршрути з контролерами та рендерити перегляди. +- [Запити](/learn/requests) - Розуміння, як обробляти вхідні запити. +- [Middleware](/learn/middleware) - Використання middleware з маршрутами для автентифікації, логування тощо. +- [Чому фреймворк?](/learn/why-frameworks) - Розуміння переваг використання фреймворку, як Flight. +- [Розширення](/learn/extending) - Як розширювати Flight власною функціональністю. ## Вирішення проблем - Якщо у вас проблеми з перенаправленнями, які не працюють, переконайтеся, що ви додаєте `return;` до методу. -- `stop()` і `halt()` — це не одне й те саме. `halt()` зупинить виконання негайно, тоді як `stop()` дозволить виконанню продовжуватися. +- `stop()` і `halt()` — не те саме. `halt()` зупинить виконання негайно, тоді як `stop()` дозволить виконанню продовжуватися. ## Журнал змін -- v3.12.0 — Додано допоміжний метод downloadFile. -- v3.10.0 — Додано `jsonHalt`. -- v1.0 — Початковий реліз. \ No newline at end of file +- v3.17.1 - Додано `$fileName` до методу `downloadFile()`. +- v3.12.0 - Додано допоміжний метод downloadFile. +- v3.10.0 - Додано `jsonHalt`. +- v1.0 - Початковий реліз. \ No newline at end of file diff --git a/content/v3/uk/learn/routing.md b/content/v3/uk/learn/routing.md index 9494ab1d..bdc5e869 100644 --- a/content/v3/uk/learn/routing.md +++ b/content/v3/uk/learn/routing.md @@ -1,17 +1,17 @@ # Маршрутизація ## Огляд -Маршрутизація в Flight PHP відображає шаблони URL на функції зворотного виклику або методи класів, дозволяючи швидке та просте оброблення запитів. Вона розроблена для мінімального навантаження, дружнього до початківців використання та розширюваності без зовнішніх залежностей. +Маршрутизація в Flight PHP відображає шаблони URL на функції зворотного виклику або методи класів, що забезпечує швидку та просту обробку запитів. Вона розроблена для мінімального навантаження, зручного використання для початківців та розширюваності без зовнішніх залежностей. ## Розуміння -Маршрутизація є основним механізмом, який з'єднує HTTP-запити з логікою вашого додатка в Flight. Визначаючи маршрути, ви вказуєте, як різні URL запускають конкретний код, чи то через функції, методи класів, чи дії контролера. Система маршрутизації Flight є гнучкою, підтримує базові шаблони, іменовані параметри, регулярні вирази та розширені функції, такі як ін'єкція залежностей та ресурсна маршрутизація. Цей підхід тримає ваш код організованим і легким у підтримці, залишаючись швидким і простим для початківців та розширюваним для просунутих користувачів. +Маршрутизація є основним механізмом, який з'єднує HTTP-запити з логікою вашого додатка в Flight. Визначаючи маршрути, ви вказуєте, як різні URL запускають конкретний код, чи то через функції, методи класів, чи дії контролера. Система маршрутизації Flight гнучка, підтримує базові шаблони, іменовані параметри, регулярні вирази та розширені функції, такі як ін'єкція залежностей та ресурсна маршрутизація. Цей підхід тримає ваш код організованим та легким у підтримці, залишаючись швидким і простим для початківців та розширюваним для просунутих користувачів. -> **Примітка:** Хочете дізнатися більше про маршрутизацію? Перегляньте сторінку ["why a framework?"](/learn/why-frameworks) для більш детального пояснення. +> **Примітка:** Хочете дізнатися більше про маршрутизацію? Перегляньте сторінку ["why a framework?"](/learn/why-frameworks) для детальнішого пояснення. ## Базове використання ### Визначення простого маршруту -Базова маршрутизація в Flight виконується шляхом відповідності шаблону URL з функцією зворотного виклику або масивом класу та методу. +Базова маршрутизація в Flight виконується шляхом співставлення шаблону URL з функцією зворотного виклику або масивом класу та методу. ```php Flight::route('/', function(){ @@ -19,10 +19,10 @@ Flight::route('/', function(){ }); ``` -> Маршрути відповідають у порядку їх визначення. Перший маршрут, що відповідає запиту, буде викликаний. +> Маршрути співставляються в порядку їх визначення. Перший маршрут, що співпадає з запитом, буде викликаний. ### Використання функцій як зворотних викликів -Зворотний виклик може бути будь-яким об'єктом, який є викличним. Тому ви можете використовувати звичайну функцію: +Зворотний виклик може бути будь-яким об'єктом, який є викличним. Отже, ви можете використовувати звичайну функцію: ```php function hello() { @@ -32,7 +32,7 @@ function hello() { Flight::route('/', 'hello'); ``` -### Використання класів і методів як контролера +### Використання класів та методів як контролера Ви також можете використовувати метод (статичний чи ні) класу: ```php @@ -77,11 +77,11 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **Примітка:** За замовчуванням, коли контролер викликається в рамках, клас `flight\Engine` завжди інжектується, якщо ви не вказали через [контейнер ін'єкції залежностей](/learn/dependency-injection-container) +> **Примітка:** За замовчуванням, коли контролер викликається в рамках, клас `flight\Engine` завжди інжектується, якщо ви не вказуєте через [контейнер ін'єкції залежностей](/learn/dependency-injection-container) ### Маршрутизація, специфічна для методу -За замовчуванням шаблони маршрутів відповідають усім методам запитів. Ви можете відповідати на конкретні методи, розміщуючи ідентифікатор перед URL. +За замовчуванням шаблони маршрутів співставляються з усіма методами запитів. Ви можете реагувати на конкретні методи, розміщуючи ідентифікатор перед URL. ```php Flight::route('GET /', function () { @@ -108,9 +108,41 @@ Flight::route('GET|POST /', function () { }); ``` +### Спеціальна обробка запитів HEAD та OPTIONS + +Flight надає вбудовану обробку для HTTP-запитів `HEAD` та `OPTIONS`: + +#### Запити HEAD + +- **Запити HEAD** обробляються так само, як запити `GET`, але Flight автоматично видаляє тіло відповіді перед відправкою її клієнту. +- Це означає, що ви можете визначити маршрут для `GET`, і запити HEAD до того самого URL повернуть лише заголовки (без вмісту), як очікується стандартами HTTP. + +```php +Flight::route('GET /info', function() { + echo 'This is some info!'; +}); +// A HEAD request to /info will return the same headers, but no body. +``` + +#### Запити OPTIONS + +Запити `OPTIONS` автоматично обробляються Flight для будь-якого визначеного маршруту. +- Коли отримано запит OPTIONS, Flight відповідає статусом `204 No Content` та заголовком `Allow`, що перелічує всі підтримувані HTTP-методи для цього маршруту. +- Вам не потрібно визначати окремий маршрут для OPTIONS, якщо ви не хочете кастомну поведінку або модифікувати відповідь. + +```php +// For a route defined as: +Flight::route('GET|POST /users', function() { /* ... */ }); + +// An OPTIONS request to /users will respond with: +// +// Status: 204 No Content +// Allow: GET, POST, HEAD, OPTIONS +``` + ### Використання об'єкта Router -Додатково ви можете отримати об'єкт Router, який має деякі допоміжні методи для вашого використання: +Крім того, ви можете отримати об'єкт Router, який має деякі допоміжні методи для вашого використання: ```php @@ -160,7 +192,7 @@ Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { }); ``` -> **Примітка:** Відповідність групам regex `()` з позиційними параметрами не підтримується. Ex: `:'\(` +> **Примітка:** Співставлення груп regex `()` з позиційними параметрами не підтримується. Ex: `:'\(` #### Важливе застереження @@ -172,11 +204,11 @@ Flight::route('/@name/@id', function (string $id, string $name) { }); ``` -І якщо ви перейдете за таким URL: `/bob/123`, вивід буде `hello, 123 (bob)!`. +І якщо ви перейдете за наступним URL: `/bob/123`, вивід буде `hello, 123 (bob)!`. _Будьте обережні_ при налаштуванні ваших маршрутів та функцій зворотного виклику! ### Необов'язкові параметри -Ви можете вказувати іменовані параметри, які є необов'язковими для відповідності, обгортаючи сегменти в дужки. +Ви можете вказувати іменовані параметри, які є необов'язковими для співставлення, обгортаючи сегменти в дужки. ```php Flight::route( @@ -191,10 +223,10 @@ Flight::route( ); ``` -Будь-які необов'язкові параметри, які не відповідають, будуть передані як `NULL`. +Будь-які необов'язкові параметри, які не співпадають, будуть передані як `NULL`. -### Дика маршрутизація -Відповідність виконується лише на окремих сегментах URL. Якщо ви хочете відповідати кільком сегментам, ви можете використовувати дикий символ `*`. +### Дикий символ у маршрутизації +Співставлення виконується лише для окремих сегментів URL. Якщо ви хочете співставити кілька сегментів, ви можете використовувати дикий символ `*`. ```php Flight::route('/blog/*', function () { @@ -202,7 +234,7 @@ Flight::route('/blog/*', function () { }); ``` -Щоб маршрутизувати всі запити на один зворотний виклик, ви можете зробити: +Щоб маршрутизувати всі запити до одного зворотного виклику, ви можете зробити: ```php Flight::route('*', function () { @@ -212,7 +244,7 @@ Flight::route('*', function () { ### Обробник 404 Not Found -За замовчуванням, якщо URL не знайдено, Flight надішле відповідь `HTTP 404 Not Found`, яка є дуже простою та звичайною. +За замовчуванням, якщо URL не знайдено, Flight надішле просту та звичайну відповідь `HTTP 404 Not Found`. Якщо ви хочете мати більш кастомізовану відповідь 404, ви можете [відобразити](/learn/extending) свій власний метод `notFound`: ```php @@ -233,10 +265,39 @@ Flight::map('notFound', function() { }); ``` +### Обробник Method Not Found + +За замовчуванням, якщо URL знайдено, але метод не дозволено, Flight надішле просту та звичайну відповідь `HTTP 405 Method Not Allowed` (Ex: Method Not Allowed. Allowed Methods are: GET, POST). Він також включить заголовок `Allow` з дозволеними методами для цього URL. + +Якщо ви хочете мати більш кастомізовану відповідь 405, ви можете [відобразити](/learn/extending) свій власний метод `methodNotFound`: + +```php +use flight\net\Route; + +Flight::map('methodNotFound', function(Route $route) { + $url = Flight::request()->url; + $methods = implode(', ', $route->methods); + + // You could also use Flight::render() with a custom template. + $output = <<My Custom 405 Method Not Allowed +

The method you have requested for {$url} is not allowed.

+

Allowed Methods are: {$methods}

+ HTML; + + $this->response() + ->clearBody() + ->status(405) + ->setHeader('Allow', $methods) + ->write($output) + ->send(); +}); +``` + ## Розширене використання ### Ін'єкція залежностей у маршрутах -Якщо ви хочете використовувати ін'єкцію залежностей через контейнер (PSR-11, PHP-DI, Dice тощо), єдиний тип маршрутів, де це доступно, — це або безпосереднє створення об'єкта самостійно та використання контейнера для створення вашого об'єкта, або ви можете використовувати рядки для визначення класу та методу для виклику. Ви можете перейти на сторінку [Dependency Injection](/learn/dependency-injection-container) для отримання додаткової інформації. +Якщо ви хочете використовувати ін'єкцію залежностей через контейнер (PSR-11, PHP-DI, Dice тощо), єдиний тип маршрутів, де це доступно, — це безпосереднє створення об'єкта самостійно та використання контейнера для створення вашого об'єкта, або ви можете використовувати рядки для визначення класу та методу для виклику. Ви можете перейти на сторінку [Dependency Injection](/learn/dependency-injection-container) для отримання додаткової інформації. Ось швидкий приклад: @@ -292,7 +353,7 @@ Flight::start(); ### Передача виконання наступному маршруту Deprecated -Ви можете передати виконання наступному відповідному маршруту, повертаючи `true` з вашої функції зворотного виклику. +Ви можете передати виконання наступному співставленому маршруту, повертаючи `true` з вашої функції зворотного виклику. ```php Flight::route('/user/@name', function (string $name) { @@ -311,7 +372,7 @@ Flight::route('/user/*', function () { Тепер рекомендується використовувати [middleware](/learn/middleware) для обробки складних випадків, як цей. ### Псевдоніми маршрутів -Призначаючи псевдонім маршруту, ви можете пізніше динамічно викликати цей псевдонім у вашому додатку, щоб згенерувати його пізніше в коді (наприклад: посилання в HTML-шаблоні або генерація URL для перенаправлення). +Призначаючи псевдонім маршруту, ви можете пізніше динамічно викликати цей псевдонім у вашому додатку, щоб згенерувати його пізніше у вашому коді (наприклад: посилання в HTML-шаблоні або генерація URL для перенаправлення). ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); @@ -332,10 +393,10 @@ class UserController { ``` -Це особливо корисно, якщо ваш URL зміниться. У прикладі вище, припустимо, що користувачі були перенесені до `/admin/users/@id` замість. +Це особливо корисно, якщо ваш URL змінюється. У прикладі вище, припустимо, що users переміщено до `/admin/users/@id` замість. З псевдонімами на місці для маршруту, вам більше не потрібно шукати всі старі URL у вашому коді та змінювати їх, оскільки псевдонім тепер поверне `/admin/users/5`, як у прикладі вище. -Псевдоніми маршрутів також працюють у групах: +Псевдоніми маршрутів все ще працюють у групах: ```php Flight::group('/users', function() { @@ -346,10 +407,10 @@ Flight::group('/users', function() { ``` ### Перевірка інформації про маршрут -Якщо ви хочете перевірити інформацію про відповідний маршрут, є 2 способи це зробити: +Якщо ви хочете перевірити інформацію про співставлений маршрут, є 2 способи це зробити: 1. Ви можете використовувати властивість `executedRoute` на об'єкті `Flight::router()`. -2. Ви можете запитати, щоб об'єкт маршруту був переданий до вашого зворотного виклику, передаючи `true` як третій параметр у методі маршруту. Об'єкт маршруту завжди буде останнім параметром, переданим до вашої функції зворотного виклику. +2. Ви можете запросити об'єкт маршруту для передачі до вашого зворотного виклику, передаючи `true` як третій параметр у методі маршруту. Об'єкт маршруту завжди буде останнім параметром, переданим до вашої функції зворотного виклику. #### `executedRoute` ```php @@ -379,7 +440,7 @@ Flight::route('/', function() { }); ``` -> **Примітка:** Властивість `executedRoute` буде встановлена лише після виконання маршруту. Якщо ви спробуєте отримати доступ до неї до виконання маршруту, вона буде `NULL`. Ви також можете використовувати executedRoute у [middleware](/learn/middleware)! +> **Примітка:** Властивість `executedRoute` буде встановлена лише після виконання маршруту. Якщо ви спробуєте отримати до неї доступ до виконання маршруту, вона буде `NULL`. Ви також можете використовувати executedRoute у [middleware](/learn/middleware)! #### Передача `true` до визначення маршруту ```php @@ -488,7 +549,7 @@ Flight::group('/api/v1', function () { Дивіться більше деталей на сторінці [group middleware](/learn/middleware#grouping-middleware). ### Ресурсна маршрутизація -Ви можете створювати набір маршрутів для ресурсу, використовуючи метод `resource`. Це створить набір маршрутів для ресурсу, що відповідає RESTful конвенціям. +Ви можете створити набір маршрутів для ресурсу, використовуючи метод `resource`. Це створить набір маршрутів для ресурсу, що слідує конвенціям RESTful. Щоб створити ресурс, зробіть наступне: @@ -496,7 +557,7 @@ Flight::group('/api/v1', function () { Flight::resource('/users', UsersController::class); ``` -І те, що станеться в фоні, це створення наступних маршрутів: +І те, що станеться в тлі, — це створення наступних маршрутів: ```php [ @@ -545,15 +606,15 @@ class UsersController } ``` -> **Примітка**: Ви можете переглядати щойно додані маршрути з `runway`, запустивши `php runway routes`. +> **Примітка**: Ви можете переглянути новододаноти маршрути з `runway`, запустивши `php runway routes`. -#### Налаштування ресурсних маршрутів +#### Налаштування ресурсів маршрутів -Є кілька опцій для конфігурації ресурсних маршрутів. +Є кілька опцій для налаштування ресурсів маршрутів. ##### Базовий псевдонім -Ви можете конфігурувати `aliasBase`. За замовчуванням псевдонім — це остання частина вказаного URL. +Ви можете налаштувати `aliasBase`. За замовчуванням псевдонім — це остання частина вказаного URL. Наприклад, `/users/` призведе до `aliasBase` як `users`. Коли ці маршрути створюються, псевдоніми — `users.index`, `users.create` тощо. Якщо ви хочете змінити псевдонім, встановіть `aliasBase` на значення, яке ви хочете. @@ -564,7 +625,7 @@ Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); ##### Only та Except -Ви також можете вказувати, які маршрути ви хочете створити, використовуючи опції `only` та `except`. +Ви також можете вказати, які маршрути ви хочете створити, використовуючи опції `only` та `except`. ```php // Whitelist only these methods and blacklist the rest @@ -576,11 +637,11 @@ Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` -Це по суті опції білої та чорної списків, щоб ви могли вказувати, які маршрути ви хочете створити. +Це по суті опції білої та чорної списків, щоб ви могли вказати, які маршрути ви хочете створити. ##### Middleware -Ви також можете вказувати middleware, яке буде виконуватися на кожному з маршрутів, створених методом `resource`. +Ви також можете вказати middleware для виконання на кожному з маршрутів, створених методом `resource`. ```php Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]); @@ -588,15 +649,15 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid ### Потокові відповіді -Ви тепер можете потоково передавати відповіді клієнту, використовуючи `stream()` або `streamWithHeaders()`. -Це корисно для надсилання великих файлів, довготривалих процесів або генерації великих відповідей. -Потокова передача маршруту обробляється трохи інакше, ніж звичайний маршрут. +Ви тепер можете потокувати відповіді клієнту, використовуючи `stream()` або `streamWithHeaders()`. +Це корисно для відправки великих файлів, довготривалих процесів або генерації великих відповідей. +Потокування маршруту обробляється трохи інакше, ніж звичайний маршрут. > **Примітка:** Потокові відповіді доступні лише якщо у вас встановлено [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) на `false`. -#### Потік з ручними заголовками +#### Поток з ручними заголовками -Ви можете потоково передавати відповідь клієнту, використовуючи метод `stream()` на маршруті. Якщо ви +Ви можете потокувати відповідь клієнту, використовуючи метод `stream()` на маршруті. Якщо ви зробите це, ви мусите встановити всі заголовки вручну перед тим, як вивести щось клієнту. Це робиться з функцією php `header()` або методом `Flight::response()->setRealHeader()`. @@ -634,9 +695,9 @@ Flight::route('/@filename', function($filename) { })->stream(); ``` -#### Потік з заголовками +#### Поток з заголовками -Ви також можете використовувати метод `streamWithHeaders()` для встановлення заголовків перед початком потокової передачі. +Ви також можете використовувати метод `streamWithHeaders()` для встановлення заголовків перед початком потокування. ```php Flight::route('/stream-users', function() { @@ -672,24 +733,22 @@ Flight::route('/stream-users', function() { ## Дивіться також - [Middleware](/learn/middleware) - Використання middleware з маршрутами для аутентифікації, логування тощо. - [Dependency Injection](/learn/dependency-injection-container) - Спрощення створення та керування об'єктами в маршрутах. -- [Why a Framework?](/learn/why-frameworks) - Розуміння переваг використання фреймворку як Flight. -- [Extending](/learn/extending) - Як розширити Flight власною функціональністю, включаючи метод `notFound`. -- [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - Функція PHP для відповідності регулярним виразам. +- [Why a Framework?](/learn/why-frameworks) - Розуміння переваг використання фреймворку, як Flight. +- [Extending](/learn/extending) - Як розширити Flight своєю функціональністю, включаючи метод `notFound`. +- [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - Функція PHP для співставлення регулярних виразів. -## Вирішення проблем -- Параметри маршруту відповідають за порядком, а не за іменем. Переконайтеся, що порядок параметрів зворотного виклику відповідає визначенню маршруту. +## Усунення несправностей +- Параметри маршруту співставляються за порядком, а не за іменем. Переконайтеся, що порядок параметрів зворотного виклику відповідає визначенню маршруту. - Використання `Flight::get()` не визначає маршрут; використовуйте `Flight::route('GET /...')` для маршрутизації або контекст об'єкта Router у групах (наприклад, `$router->get(...)`). -- Властивість executedRoute встановлюється лише після виконання маршруту; вона NULL до виконання. -- Потокова передача вимагає відключення функціональності буферизації виводу Flight (`flight.v2.output_buffering = false`). -- Для ін'єкції залежностей лише певні визначення маршрутів підтримують інстанціацію на основі контейнера. +- Властивість executedRoute встановлюється лише після виконання маршруту; вона NULL перед виконанням. +- Потокування вимагає вимкнення функціональності буферизації виводу Flight (`flight.v2.output_buffering = false`). +- Для ін'єкції залежностей лише певні визначення маршрутів підтримують інстанціювання на основі контейнера. ### 404 Not Found або несподівана поведінка маршруту -Якщо ви бачите помилку 404 Not Found (але ви присягаєтеся своїм життям, що вона дійсно там і це не помилка друку), це насправді може бути проблема -з поверненням значення у вашому кінцевому пункті маршруту замість просто виведення його. Причина для цього навмисна, але може підкрастися до деяких розробників. +Якщо ви бачите помилку 404 Not Found (але ви присягаєтеся своїм життям, що вона дійсно там і це не помилка друку), це насправді може бути проблема з тим, що ви повертаєте значення в ендпоінті маршруту замість просто виведення його. Причина для цього навмисна, але може заскочити деяких розробників. ```php - Flight::route('/hello', function(){ // This might cause a 404 Not Found error return 'Hello World'; @@ -699,12 +758,11 @@ Flight::route('/hello', function(){ Flight::route('/hello', function(){ echo 'Hello World'; }); - ``` -Причина для цього полягає в спеціальному механізмі, вбудованому в роутер, який обробляє вивід повернення як сигнал "перейти до наступного маршруту". +Причина для цього полягає в спеціальному механізмі, вбудованому в роутер, який обробляє повернений вивід як сигнал "перейти до наступного маршруту". Ви можете побачити поведінку, документовану в розділі [Routing](/learn/routing#passing). ## Журнал змін -- v3: Додано ресурсну маршрутизацію, псевдоніми маршрутів, підтримку потокової передачі, групи маршрутів та підтримку middleware. +- v3: Додано ресурсну маршрутизацію, псевдоніми маршрутів та підтримку потокування, групи маршрутів та підтримку middleware. - v1: Більшість базових функцій доступні. \ No newline at end of file diff --git a/content/v3/zh/awesome-plugins/apm.md b/content/v3/zh/awesome-plugins/apm.md index 233ae077..344bf19c 100644 --- a/content/v3/zh/awesome-plugins/apm.md +++ b/content/v3/zh/awesome-plugins/apm.md @@ -1,12 +1,14 @@ # FlightPHP APM 文档 -欢迎使用 FlightPHP APM——您应用的个人性能教练!本指南是您设置、使用和掌握 Application Performance Monitoring (APM) 与 FlightPHP 的路线图。不管您是在追踪缓慢的请求,还是只想沉迷于延迟图表,我们都已覆盖。让我们让您的应用更快,让用户更开心,并让调试会话变得轻松! +欢迎来到 FlightPHP APM——您应用的个人性能教练!本指南是您设置、使用和掌握使用 FlightPHP 的应用性能监控 (APM) 的路线图。无论您是在追查慢请求,还是只是想对延迟图表着迷,我们都会为您提供支持。让我们让您的应用更快,让您的用户更快乐,让您的调试会话变得轻松! + +查看 Flight Docs 站点的仪表板[演示](https://flightphp-docs-apm.sky-9.com/apm/dashboard)。 ![FlightPHP APM](/images/apm.png) -## APM 为什么重要 +## 为什么 APM 重要 -想象一下:您的应用就像一家忙碌的餐厅。没有追踪订单花费时间或厨房哪里堵塞的方法,您就只能猜测为什么客户不满意地离开。APM 就像您的副厨——它监视每个步骤,从传入请求到数据库查询,并标记任何减缓速度的东西。缓慢的页面会失去用户(研究显示,如果网站加载超过 3 秒,53% 的用户会跳出!),APM 帮助您在问题发生前捕获这些问题。它是主动的安心——更少的“为什么这坏了?”时刻,多一些“看看这运行得多流畅!”的胜利。 +想象一下:您的应用就像一家繁忙的餐厅。没有一种方法来跟踪订单需要多长时间或厨房在哪里卡住,您只能猜测为什么客户离开时心情不好。APM 是您的副厨师——它监视每一个步骤,从传入请求到数据库查询,并标记任何减慢您速度的东西。慢页面会丢失用户(研究表明,如果网站加载超过 3 秒,53% 的用户会跳出!),APM 帮助您在问题刺痛之前抓住它们。它是主动的安心——更少的“为什么这个坏了?”时刻,更多的“看这个运行得多顺畅!”胜利。 ## 安装 @@ -17,25 +19,25 @@ composer require flightphp/apm ``` 您需要: -- **PHP 7.4+**:保持与 LTS Linux 发行版兼容,同时支持现代 PHP。 +- **PHP 7.4+**:保持我们与 LTS Linux 发行版兼容,同时支持现代 PHP。 - **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**:我们正在提升的轻量级框架。 ## 支持的数据库 -FlightPHP APM 当前支持以下数据库用于存储指标: +FlightPHP APM 当前支持以下数据库来存储指标: -- **SQLite3**:简单、基于文件的,非常适合本地开发或小型应用。默认选项。 -- **MySQL/MariaDB**:适合大型项目或生产环境,需要稳健、可扩展的存储。 +- **SQLite3**:简单、基于文件,非常适合本地开发或小型应用。大多数设置中的默认选项。 +- **MySQL/MariaDB**:适合大型项目或生产环境,您需要健壮、可扩展的存储。 -您可以在配置步骤中选择数据库类型(见下文)。确保您的 PHP 环境安装了必要的扩展(如 `pdo_sqlite` 或 `pdo_mysql`)。 +您可以在配置步骤(见下文)中选择您的数据库类型。请确保您的 PHP 环境安装了必要的扩展(例如,`pdo_sqlite` 或 `pdo_mysql`)。 -## 入门 +## 快速开始 -以下是通往 APM 精彩的逐步指南: +以下是通往 APM 卓越的逐步指南: ### 1. 注册 APM -将以下代码放入您的 `index.php` 或 `services.php` 文件中以开始追踪: +将此代码放入您的 `index.php` 或 `services.php` 文件中以开始跟踪: ```php use flight\apm\logger\LoggerFactory; @@ -46,18 +48,18 @@ $Apm = new Apm($ApmLogger); $Apm->bindEventsToFlightInstance($app); // 如果您正在添加数据库连接 -// 必须是 PdoWrapper 或 PdoQueryCapture 来自 Tracy 扩展 -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True 要求启用 APM 中的追踪。 +// 必须是来自 Tracy Extensions 的 PdoWrapper 或 PdoQueryCapture +$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- 需要 true 以在 APM 中启用跟踪。 $Apm->addPdoConnection($pdo); ``` **这里发生了什么?** -- `LoggerFactory::create()` 获取您的配置(很快就会详细说明)并设置一个记录器——默认是 SQLite。 -- `Apm` 是主角——它监听 Flight 的事件(请求、路由、错误等)并收集指标。 -- `bindEventsToFlightInstance($app)` 将其绑定到您的 Flight 应用。 +- `LoggerFactory::create()` 获取您的配置(稍后详述)并设置一个日志记录器——默认是 SQLite。 +- `Apm` 是明星——它监听 Flight 的事件(请求、路由、错误等)并收集指标。 +- `bindEventsToFlightInstance($app)` 将其全部绑定到您的 Flight 应用。 **专业提示:采样** -如果您的应用很繁忙,记录*每个*请求可能会过载。使用采样率(0.0 到 1.0): +如果您的应用很繁忙,记录*每个*请求可能会过载。用采样率(0.0 到 1.0): ```php $Apm = new Apm($ApmLogger, 0.1); // 记录 10% 的请求 @@ -67,16 +69,16 @@ $Apm = new Apm($ApmLogger, 0.1); // 记录 10% 的请求 ### 2. 配置它 -运行以下命令来创建您的 `.runway-config.json`: +运行此命令来创建您的 `.runway-config.json`: ```bash php vendor/bin/runway apm:init ``` -**这做了什么?** -- 启动一个向导,询问原始指标来自哪里(来源)和处理后的数据去哪里(目的地)。 -- 默认是 SQLite——例如,`sqlite:/tmp/apm_metrics.sqlite` 用于来源,另一个用于目的地。 -- 您将得到像这样的配置: +**这是做什么?** +- 启动一个向导,询问原始指标来自哪里(源)和处理后的数据去哪里(目标)。 +- 默认是 SQLite——例如,源是 `sqlite:/tmp/apm_metrics.sqlite`,目标是另一个。 +- 您将得到类似这样的配置: ```json { "apm": { @@ -88,32 +90,32 @@ php vendor/bin/runway apm:init } ``` -> 这个过程还会询问您是否要运行此设置的迁移。如果这是您第一次设置,答案是肯定的。 +> 此过程还会询问您是否要为此设置运行迁移。如果您是第一次设置,答案是是的。 **为什么有两个位置?** -原始指标堆积很快(想想未过滤的日志)。工作人员将它们处理成结构化的目的地,用于仪表板。保持整洁! +原始指标堆积很快(想想未过滤的日志)。工作进程将它们处理成仪表板用的结构化目标。保持一切整洁! -### 3. 使用工作人员处理指标 +### 3. 使用 Worker 处理指标 -工作人员将原始指标转换为仪表板就绪数据。运行一次: +Worker 将原始指标转换为仪表板就绪数据。运行一次: ```bash php vendor/bin/runway apm:worker ``` **它在做什么?** -- 从您的来源读取(例如,`apm_metrics.sqlite`)。 -- 处理最多 100 个指标(默认批次大小)到您的目的地。 -- 在完成或没有指标剩余时停止。 +- 从您的源读取(例如,`apm_metrics.sqlite`)。 +- 处理最多 100 个指标(默认批次大小)到您的目标。 +- 完成后停止,或如果没有剩余指标。 -**保持运行** -对于实时应用,您希望连续处理。以下是您的选项: +**保持它运行** +对于实时应用,您需要连续处理。以下是您的选项: - **守护进程模式**: ```bash php vendor/bin/runway apm:worker --daemon ``` - 永久运行,处理指标。适合开发或小型设置。 + 永远运行,处理指标如它们到来。适合开发或小型设置。 - **Crontab**: 将此添加到您的 crontab(`crontab -e`): @@ -123,11 +125,11 @@ php vendor/bin/runway apm:worker 每分钟触发——适合生产。 - **Tmux/Screen**: - 启动一个可分离的会话: + 启动一个可分离会话: ```bash tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon - # Ctrl+B,然后 D 来分离;`tmux attach -t apm-worker` 来重新连接 + # Ctrl+B,然后 D 分离;`tmux attach -t apm-worker` 重新连接 ``` 即使您注销,也保持运行。 @@ -139,61 +141,61 @@ php vendor/bin/runway apm:worker - `--max_messages 1000`:处理 1000 个指标后停止。 - `--timeout 300`:5 分钟后退出。 -**为什么费事?** -没有工作人员,您的仪表板是空的。它是原始日志和可操作洞察之间的桥梁。 +**为什么费心?** +没有 Worker,您的仪表板是空的。它是原始日志和可操作洞察之间的桥梁。 ### 4. 启动仪表板 -查看您的应用的生命体征: +查看您应用的生命体征: ```bash php vendor/bin/runway apm:dashboard ``` **这是什么?** -- 在 `http://localhost:8001/apm/dashboard` 上启动一个 PHP 服务器。 -- 显示请求日志、缓慢路由、错误率等。 +- 在 `http://localhost:8001/apm/dashboard` 启动一个 PHP 服务器。 +- 显示请求日志、慢路由、错误率等。 **自定义它**: ```bash php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php ``` -- `--host 0.0.0.0`:从任何 IP 访问(方便远程查看)。 +- `--host 0.0.0.0`:从任何 IP 访问(远程查看方便)。 - `--port 8080`:如果 8001 被占用,使用不同端口。 -- `--php-path`:如果 PHP 不在 PATH 中,指向它。 +- `--php-path`:如果不在您的 PATH 中,指向 PHP。 -在浏览器中访问 URL 进行探索! +在浏览器中访问 URL 并探索! #### 生产模式 -对于生产环境,您可能需要尝试一些技术来运行仪表板,因为可能有防火墙和其他安全措施。以下是一些选项: +对于生产,您可能需要尝试一些技巧来运行仪表板,因为可能有防火墙和其他安全措施。以下是几个选项: -- **使用反向代理**:设置 Nginx 或 Apache 来转发请求到仪表板。 -- **SSH 隧道**:如果您能 SSH 到服务器,使用 `ssh -L 8080:localhost:8001 youruser@yourserver` 将仪表板隧道到您的本地机器。 +- **使用反向代理**:设置 Nginx 或 Apache 将请求转发到仪表板。 +- **SSH 隧道**:如果您可以 SSH 到服务器,使用 `ssh -L 8080:localhost:8001 youruser@yourserver` 将仪表板隧道到您的本地机器。 - **VPN**:如果您的服务器在 VPN 后面,连接到它并直接访问仪表板。 - **配置防火墙**:为您的 IP 或服务器网络打开端口 8001(或您设置的任何端口)。 -- **配置 Apache/Nginx**:如果您在应用前面有一个 web 服务器,您可以配置它到一个域或子域。如果您这样做,将文档根设置为 `/path/to/your/project/vendor/flightphp/apm/dashboard`。 +- **配置 Apache/Nginx**:如果您的应用前面有 Web 服务器,您可以配置它到域名或子域名。如果您这样做,您将文档根目录设置为 `/path/to/your/project/vendor/flightphp/apm/dashboard` #### 想要不同的仪表板? -如果您想的话,可以构建自己的仪表板!查看 `vendor/flightphp/apm/src/apm/presenter` 目录,获取呈现数据供您自己的仪表板的想法! +如果您愿意,您可以构建自己的仪表板!查看 vendor/flightphp/apm/src/apm/presenter 目录以获取如何为自己的仪表板呈现数据的想法! ## 仪表板功能 仪表板是您的 APM 总部——以下是您将看到的内容: -- **请求日志**:每个请求,包括时间戳、URL、响应代码和总时间。点击“详情”查看中间件、查询和错误。 -- **最慢请求**:占用时间最多的前 5 个请求(例如,“/api/heavy” 耗时 2.5 秒)。 -- **最慢路由**:按平均时间排序的前 5 个路由——非常适合发现模式。 -- **错误率**:请求失败的百分比(例如,2.3% 的 500 错误)。 +- **请求日志**:每个请求带有时间戳、URL、响应代码和总时间。点击“Details”查看中间件、查询和错误。 +- **最慢请求**:占用时间最多的前 5 个请求(例如,“/api/heavy” 2.5 秒)。 +- **最慢路由**:按平均时间的前 5 个路由——非常适合发现模式。 +- **错误率**:失败请求的百分比(例如,2.3% 500 错误)。 - **延迟百分位**:95th (p95) 和 99th (p99) 响应时间——了解您的最坏情况。 -- **响应代码图表**:可视化 200s、404s、500s 随时间变化。 -- **长时间查询/中间件**:前 5 个缓慢数据库调用和中间件层。 -- **缓存命中/未命中**:您的缓存节省时间的频率。 +- **响应代码图表**:随时间可视化 200、404、500 等。 +- **长查询/中间件**:前 5 个慢数据库调用和中间件层。 +- **缓存命中/未命中**:您的缓存拯救局面的频率。 **额外功能**: -- 按“最近一小时”、“最近一天”或“最近一周”过滤。 -- 切换暗模式,用于深夜会话。 +- 按“Last Hour”、“Last Day”或“Last Week”过滤。 +- 为那些深夜会话切换暗黑模式。 **示例**: 对 `/users` 的请求可能显示: @@ -204,7 +206,7 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l ## 添加自定义事件 -追踪任何内容——如 API 调用或支付过程: +跟踪任何东西——如 API 调用或支付过程: ```php use flight\apm\CustomEvent; @@ -217,7 +219,7 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ``` **它在哪里显示?** -在仪表板的请求详情下“自定义事件”——可展开并带有漂亮的 JSON 格式。 +在仪表板的请求详细信息下“Custom Events”——带有漂亮的 JSON 格式,可展开。 **用例**: ```php @@ -229,16 +231,16 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -现在您会看到那个 API 是否拖累您的应用! +现在您将看到那个 API 是否拖慢了您的应用! ## 数据库监控 -像这样追踪 PDO 查询: +像这样跟踪 PDO 查询: ```php use flight\database\PdoWrapper; -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True 要求启用 APM 中的追踪。 +$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- 需要 true 以在 APM 中启用跟踪。 $Apm->addPdoConnection($pdo); ``` @@ -248,23 +250,23 @@ $Apm->addPdoConnection($pdo); - 行数(例如,42) **注意**: -- **可选**:如果您不需要 DB 追踪,可以跳过。 +- **可选**:如果您不需要 DB 跟踪,请跳过。 - **仅 PdoWrapper**:核心 PDO 尚未钩住——敬请期待! -- **性能警告**:在数据库密集型站点上记录每个查询可能会减慢速度。使用采样(`$Apm = new Apm($ApmLogger, 0.1)`)来减轻负载。 +- **性能警告**:在 DB 密集型站点记录每个查询可能会减慢速度。使用采样(`$Apm = new Apm($ApmLogger, 0.1)`)来减轻负载。 **示例输出**: - 查询:`SELECT name FROM products WHERE price > 100` - 时间:0.023s -- 行数:15 +- 行:15 -## 工作人员选项 +## Worker 选项 -调整工作人员以符合您的喜好: +根据您的喜好调整 Worker: - `--timeout 300`:5 分钟后停止——适合测试。 -- `--max_messages 500`:限制为 500 个指标——保持有限。 +- `--max_messages 500`:上限 500 个指标——保持有限。 - `--batch_size 200`:一次处理 200 个——平衡速度和内存。 -- `--daemon`:永不停止运行——适合实时监控。 +- `--daemon`:不间断运行——适合实时监控。 **示例**: ```bash @@ -272,17 +274,17 @@ php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ``` 运行一小时,一次处理 100 个指标。 -## 请求 ID 在应用中 +## 应用中的请求 ID -每个请求都有一个唯一的请求 ID 用于追踪。您可以在应用中使用此 ID 来关联日志和指标。例如,您可以将请求 ID 添加到一个错误页面: +每个请求都有一个唯一的请求 ID 用于跟踪。您可以在应用中使用此 ID 来关联日志和指标。例如,您可以将请求 ID 添加到错误页面: ```php Flight::map('error', function($message) { - // 获取请求 ID 从响应头 X-Flight-Request-Id + // 从响应头 X-Flight-Request-Id 获取请求 ID $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); // 此外,您可以从 Flight 变量中获取它 - // 这个方法在 Swoole 或其他异步平台中可能无法正常工作。 + // 此方法在 swoole 或其他异步平台中效果不佳。 // $requestId = Flight::get('apm.request_id'); echo "Error: $message (Request ID: $requestId)"; @@ -291,45 +293,45 @@ Flight::map('error', function($message) { ## 升级 -如果您正在升级到 APM 的新版本,数据库迁移可能需要运行。您可以通过运行以下命令来执行: +如果您正在升级到 APM 的较新版本,有可能需要运行数据库迁移。您可以通过运行以下命令来完成: ```bash php vendor/bin/runway apm:migrate ``` -这将运行任何需要的迁移,以将数据库模式更新到最新版本。 +这将运行任何必要的迁移,以将数据库模式更新到最新版本。 -**注意:** 如果您的 APM 数据库很大,这些迁移可能需要一些时间。您可能希望在非高峰时段运行此命令。 +**注意:** 如果您的 APM 数据库大小很大,这些迁移可能需要一些时间运行。您可能希望在非高峰时段运行此命令。 ## 清除旧数据 -为了保持数据库整洁,您可以清除旧数据。这在运行繁忙的应用并希望保持数据库大小可管理时特别有用。 -您可以通过运行以下命令来执行: +为了保持您的数据库整洁,您可以清除旧数据。这特别有用,如果您正在运行一个繁忙的应用并希望保持数据库大小可管理。 +您可以通过运行以下命令来完成: ```bash php vendor/bin/runway apm:purge ``` -这将从数据库中删除所有超过 30 天的数据。您可以通过将不同值传递给 `--days` 选项来调整天数: +这将从数据库中移除所有超过 30 天的数据。您可以通过将不同值传递给 `--days` 选项来调整天数: ```bash php vendor/bin/runway apm:purge --days 7 ``` -这将从数据库中删除所有超过 7 天的数据。 +这将从数据库中移除所有超过 7 天的数据。 ## 故障排除 -遇到问题?试试这些: +卡住了?试试这些: -- **仪表板无数据?** - - 工作人员运行了吗?检查 `ps aux | grep apm:worker`。 - - 配置路径匹配吗?验证 `.runway-config.json` 中的 DSN 指向真实文件。 - - 手动运行 `php vendor/bin/runway apm:worker` 来处理待处理的指标。 +- **没有仪表板数据?** + - Worker 运行了吗?检查 `ps aux | grep apm:worker`。 + - 配置路径匹配吗?验证 `.runway-config.json` DSN 指向真实文件。 + - 手动运行 `php vendor/bin/runway apm:worker` 来处理待处理指标。 -- **工作人员错误?** - - 查看您的 SQLite 文件(例如,`sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`)。 - - 检查 PHP 日志中的堆栈跟踪。 +- **Worker 错误?** + - 窥视您的 SQLite 文件(例如,`sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`)。 + - 检查 PHP 日志以获取堆栈跟踪。 - **仪表板无法启动?** - - 端口 8001 被占用吗?使用 `--port 8080`。 + - 端口 8001 被占用?使用 `--port 8080`。 - PHP 未找到?使用 `--php-path /usr/bin/php`。 - 防火墙阻塞?打开端口或使用 `--host localhost`。 @@ -337,9 +339,9 @@ php vendor/bin/runway apm:purge --days 7 - 降低采样率:`$Apm = new Apm($ApmLogger, 0.05)` (5%)。 - 减少批次大小:`--batch_size 20`。 -- **未追踪异常/错误?** - - 如果您启用了 [Tracy](https://tracy.nette.org/) 项目,它将覆盖 Flight 的错误处理。您需要禁用 Tracy,然后确保 `Flight::set('flight.handle_errors', true);` 已设置。 +- **未跟踪异常/错误?** + - 如果您为项目启用了 [Tracy](https://tracy.nette.org/),它将覆盖 Flight 的错误处理。您需要禁用 Tracy,然后确保 `Flight::set('flight.handle_errors', true);` 已设置。 -- **未追踪数据库查询?** - - 确保您正在使用 `PdoWrapper` 进行数据库连接。 - - 确保在构造函数中的最后一个参数是 `true`。 \ No newline at end of file +- **未跟踪数据库查询?** + - 确保您使用 `PdoWrapper` 进行数据库连接。 + - 确保构造函数中的最后一个参数为 `true`。 \ No newline at end of file diff --git a/content/v3/zh/learn/ai.md b/content/v3/zh/learn/ai.md index 77376951..c0abc140 100644 --- a/content/v3/zh/learn/ai.md +++ b/content/v3/zh/learn/ai.md @@ -2,20 +2,20 @@ ## 概述 -Flight 让您轻松使用 AI 驱动的工具和现代开发者工作流程来增强您的 PHP 项目。凭借内置命令连接到 LLM(大型语言模型)提供商并生成项目特定的 AI 编码指令,Flight 帮助您和您的团队充分利用像 GitHub Copilot、Cursor 和 Windsurf 这样的 AI 助手。 +Flight 让您轻松为 PHP 项目注入 AI 驱动的工具和现代开发者工作流程。通过内置命令连接 LLM(大型语言模型)提供商并生成项目特定的 AI 编码指令,Flight 帮助您和您的团队充分利用 GitHub Copilot、Cursor 和 Windsurf 等 AI 助手。 ## 理解 AI 编码助手在理解您项目的上下文、约定和目标时最为有用。Flight 的 AI 助手让您能够: - 将您的项目连接到流行的 LLM 提供商(OpenAI、Grok、Claude 等) -- 生成和更新项目特定的 AI 工具指令,以便每个人都能获得一致、相关的帮助 +- 生成和更新项目特定的 AI 工具指令,确保每个人获得一致、相关的帮助 - 保持团队一致性和生产力,减少解释上下文的时间 这些功能内置于 Flight 核心 CLI 和官方 [flightphp/skeleton](https://github.com/flightphp/skeleton) 启动项目中。 ## 基本用法 -### 1. 设置 LLM 凭据 +### 设置 LLM 凭据 `ai:init` 命令将引导您将项目连接到 LLM 提供商。 @@ -28,7 +28,7 @@ php runway ai:init - 输入您的 API 密钥 - 设置基础 URL 和模型名称 -这会在您的项目根目录创建一个 `.runway-creds.json` 文件(并确保它在您的 `.gitignore` 中)。 +这将在您的项目根目录创建一个 `.runway-creds.json` 文件(并确保它在您的 `.gitignore` 中)。 **示例:** ``` @@ -36,19 +36,19 @@ php runway ai:init 您想使用哪个 LLM API?[1] openai, [2] grok, [3] claude: 1 输入 LLM API 的基础 URL [https://api.openai.com]: 输入您的 openai API 密钥: sk-... -输入您想使用的模型名称(例如 gpt-4, claude-3-opus 等)[gpt-4o]: +输入您想使用的模型名称(例如 gpt-4、claude-3-opus 等)[gpt-4o]: 凭据已保存到 .runway-creds.json ``` -### 2. 生成项目特定的 AI 指令 +### 生成项目特定的 AI 指令 -`ai:generate-instructions` 命令帮助您创建或更新针对 AI 编码助手的指令,根据您的项目量身定制。 +`ai:generate-instructions` 命令帮助您创建或更新针对项目的 AI 编码助手的指令。 ```bash php runway ai:generate-instructions ``` -您将回答一些关于您项目的问题(描述、数据库、模板、安全、团队规模等)。Flight 使用您的 LLM 提供商生成指令,然后将它们写入: +您将回答一些关于项目的问题(描述、数据库、模板、安全、团队规模等)。Flight 使用您的 LLM 提供商生成指令,然后将它们写入: - `.github/copilot-instructions.md`(用于 GitHub Copilot) - `.cursor/rules/project-overview.mdc`(用于 Cursor) - `.windsurfrules`(用于 Windsurf) @@ -63,13 +63,13 @@ php runway ai:generate-instructions AI 指令更新成功。 ``` -现在,您的 AI 工具将基于您项目的实际需求提供更智能、更相关的建议。 +现在,您的 AI 工具将基于项目实际需求提供更智能、更相关的建议。 ## 高级用法 -- 您可以使用命令选项自定义凭据或指令文件的位置(请参阅每个命令的 `--help`)。 -- AI 助手设计用于与支持 OpenAI 兼容 API 的任何 LLM 提供商合作。 -- 如果您想随着项目的发展更新指令,只需重新运行 `ai:generate-instructions` 并再次回答提示。 +- 您可以使用命令选项自定义凭据或指令文件的位置(查看每个命令的 `--help`)。 +- AI 助手设计用于与支持 OpenAI 兼容 API 的任何 LLM 提供商配合工作。 +- 如果您想随着项目演进而更新指令,只需重新运行 `ai:generate-instructions` 并再次回答提示。 ## 另请参阅 diff --git a/content/v3/zh/learn/requests.md b/content/v3/zh/learn/requests.md index 540aabfc..948cd115 100644 --- a/content/v3/zh/learn/requests.md +++ b/content/v3/zh/learn/requests.md @@ -2,7 +2,7 @@ ## 概述 -Flight 将 HTTP 请求封装到一个单一对象中,可以通过以下方式访问: +Flight 将 HTTP 请求封装到一个对象中,可以通过以下方式访问: ```php $request = Flight::request(); @@ -10,13 +10,13 @@ $request = Flight::request(); ## 理解 -HTTP 请求是理解 HTTP 生命周期的核心方面之一。用户在 Web 浏览器或 HTTP 客户端上执行一个操作,他们会向您的项目发送一系列头部、主体、URL 等。您可以捕获这些头部(浏览器的语言、他们能处理的压缩类型、用户代理等)并捕获发送到您的 Flight 应用程序的主体和 URL。这些请求对于您的应用程序了解下一步该做什么至关重要。 +HTTP 请求是理解 HTTP 生命周期的核心方面之一。用户在 Web 浏览器或 HTTP 客户端上执行操作,他们会向您的项目发送一系列头部、主体、URL 等。您可以捕获这些头部(浏览器的语言、他们能处理的压缩类型、用户代理等),并捕获发送到您的 Flight 应用程序的主体和 URL。这些请求对于您的应用程序了解下一步该做什么至关重要。 ## 基本用法 PHP 有几个超级全局变量,包括 `$_GET`、`$_POST`、`$_REQUEST`、`$_SERVER`、`$_FILES` 和 `$_COOKIE`。Flight 将这些抽象为方便的 [Collections](/learn/collections)。您可以像数组或对象一样访问 `query`、`data`、`cookies` 和 `files` 属性。 -> **注意:** 强烈不鼓励在您的项目中使用这些超级全局变量,应通过 `request()` 对象引用。 +> **注意:** 强烈不鼓励在您的项目中使用这些超级全局变量,应该通过 `request()` 对象来引用它们。 > **注意:** `$_ENV` 没有可用的抽象。 @@ -60,7 +60,7 @@ Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; // 或 $savedLogin = Flight::request()->cookies->myLoginCookie; - // 检查是否真正保存,如果是则自动登录 + // 检查是否真的保存了,如果是则自动登录 if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -84,7 +84,7 @@ $host = Flight::request()->getVar('HTTP_HOST'); 您可以通过 `files` 属性访问上传的文件: ```php -// 直接访问 $_FILES 属性。有关推荐方法,请参阅下文 +// 直接访问 $_FILES 属性。有关推荐方法,请参阅下方 $uploadedFile = Flight::request()->files['myFile']; // 或 $uploadedFile = Flight::request()->files->myFile; @@ -96,11 +96,11 @@ $uploadedFile = Flight::request()->files->myFile; _v3.12.0_ -您可以使用框架的一些辅助方法处理文件上传。基本上,它归结为从请求中拉取文件数据,并将其移动到新位置。 +您可以使用框架的一些辅助方法来处理文件上传。它基本上归结为从请求中拉取文件数据,并将其移动到新位置。 ```php Flight::route('POST /upload', function(){ - // 如果您有一个输入字段如 + // 如果您有一个像 这样的输入字段 $uploadedFileData = Flight::request()->getUploadedFiles(); $uploadedFile = $uploadedFileData['myFile']; $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); @@ -111,7 +111,7 @@ Flight::route('POST /upload', function(){ ```php Flight::route('POST /upload', function(){ - // 如果您有一个输入字段如 + // 如果您有一个像 这样的输入字段 $uploadedFiles = Flight::request()->getUploadedFiles()['myFiles']; foreach ($uploadedFiles as $uploadedFile) { $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); @@ -119,11 +119,11 @@ Flight::route('POST /upload', function(){ }); ``` -> **安全注意:** 始终验证和清理用户输入,尤其是在处理文件上传时。始终验证您允许上传的扩展类型,但您还应该验证文件的“魔术字节”以确保它是用户声称的文件类型。有 [文章](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [和](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [库](https://github.com/RikudouSage/MimeTypeDetector) 可帮助处理此问题。 +> **安全注意:** 始终验证和清理用户输入,尤其是在处理文件上传时。始终验证您允许上传的扩展类型,但您还应该验证文件的“魔术字节”以确保它是用户声称的文件类型。有 [文章](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [和](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [库](https://github.com/RikudouSage/MimeTypeDetector) 可帮助您完成此操作。 ### 请求主体 -要获取原始 HTTP 请求主体,例如在处理 POST/PUT 请求时,您可以这样做: +要获取原始 HTTP 请求主体,例如在处理 POST/PUT 请求时,可以这样做: ```php Flight::route('POST /users/xml', function(){ @@ -193,9 +193,9 @@ $method = Flight::request()->getMethod(); - **host** - 请求主机名 - **servername** - 来自 `$_SERVER` 的 SERVER_NAME -## URL 辅助方法 +## 辅助方法 -有一些辅助方法可以方便地组合 URL 的部分。 +有一些辅助方法可以拼凑 URL 的部分,或处理某些头部。 ### 完整 URL @@ -219,13 +219,36 @@ $url = Flight::request()->getBaseUrl(); ## 查询解析 -您可以将 URL 传递给 `parseQuery()` 方法来解析查询字符串为关联数组: +您可以将 URL 传递给 `parseQuery()` 方法,将查询字符串解析为关联数组: ```php $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` +## 协商内容接受类型 + +_v3.17.2_ + +您可以使用 `negotiateContentType()` 方法,根据客户端发送的 `Accept` 头部确定最佳响应内容类型。 + +```php + +// 示例 Accept 头部:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// 下方定义您支持的内容。 +$availableTypes = ['application/json', 'application/xml']; +$typeToServe = Flight::request()->negotiateContentType($availableTypes); +if ($typeToServe === 'application/json') { + // 提供 JSON 响应 +} elseif ($typeToServe === 'application/xml') { + // 提供 XML 响应 +} else { + // 默认使用其他内容或抛出错误 +} +``` + +> **注意:** 如果在 `Accept` 头部中找不到任何可用类型,该方法将返回 `null`。如果没有定义 `Accept` 头部,该方法将返回 `$availableTypes` 数组中的第一个类型。 + ## 另请参阅 - [Routing](/learn/routing) - 了解如何将路由映射到控制器并渲染视图。 - [Responses](/learn/responses) - 如何自定义 HTTP 响应。 @@ -237,5 +260,6 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); - 如果您的 Web 服务器位于代理、负载均衡器等后面,`request()->ip` 和 `request()->proxy_ip` 可能不同。 ## 更新日志 +- v3.17.2 - 添加了 negotiateContentType() - v3.12.0 - 添加了通过请求对象处理文件上传的能力。 - v1.0 - 初始发布。 \ No newline at end of file diff --git a/content/v3/zh/learn/responses.md b/content/v3/zh/learn/responses.md index f04077b0..3c6cc695 100644 --- a/content/v3/zh/learn/responses.md +++ b/content/v3/zh/learn/responses.md @@ -2,17 +2,17 @@ ## 概述 -Flight 会为您生成部分响应头,但您对发送回用户的内容拥有大部分控制权。大多数情况下,您将直接访问 `response()` 对象,但 Flight 提供了一些辅助方法来为您设置部分响应头。 +Flight 会帮助您生成部分响应头部,但您对发送回用户的内容拥有大部分控制权。大多数时候,您会直接访问 `response()` 对象,但 Flight 提供了一些辅助方法来为您设置部分响应头部。 ## 理解 -在用户向您的应用程序发送 [request](/learn/requests) 请求后,您需要为他们生成适当的响应。他们发送给您的信息包括他们偏好的语言、是否支持某些类型的压缩、他们的用户代理等,在处理完一切后,是时候向他们发送适当的响应了。这可以是设置头、输出 HTML 或 JSON 主体,或者将他们重定向到某个页面。 +在用户向您的应用程序发送 [request](/learn/requests) 请求后,您需要为他们生成适当的响应。他们发送给您诸如他们偏好的语言、是否能处理某些类型的压缩、他们的用户代理等信息,在处理完一切后,是时候发送回适当的响应了。这可以是设置头部、输出 HTML 或 JSON 主体内容,或将他们重定向到某个页面。 ## 基本用法 ### 发送响应主体 -Flight 使用 `ob_start()` 来缓冲输出。这意味着您可以使用 `echo` 或 `print` 向用户发送响应,Flight 会捕获它并连同适当的头发送回用户。 +Flight 使用 `ob_start()` 来缓冲输出。这意味着您可以使用 `echo` 或 `print` 向用户发送响应,Flight 会捕获它并使用适当的头部发送回用户。 ```php // 这将向用户的浏览器发送 "Hello, World!" @@ -34,19 +34,19 @@ Flight::route('/', function() { // 冗长,但有时在需要时能完成任务 Flight::response()->write("Hello, World!"); - // 如果您想在此时检索已设置的主体 - // 您可以这样做 + // 如果您想在此时检索已设置的主体内容 + // 您可以这样操作 $body = Flight::response()->getBody(); }); ``` ### JSON -Flight 提供支持发送 JSON 和 JSONP 响应。要发送 JSON 响应,您需要传递一些要进行 JSON 编码的数据: +Flight 提供对发送 JSON 和 JSONP 响应的支持。要发送 JSON 响应,您需要传递一些要进行 JSON 编码的数据: ```php Flight::route('/@companyId/users', function(int $companyId) { - // 例如从数据库中拉取您的用户 + // 例如,从数据库中提取用户 $users = Flight::db()->fetchAll("SELECT id, first_name, last_name FROM users WHERE company_id = ?", [ $companyId ]); Flight::json($users); @@ -54,7 +54,7 @@ Flight::route('/@companyId/users', function(int $companyId) { // [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* 更多用户 */ ] ``` -> **注意:** 默认情况下,Flight 会发送 `Content-Type: application/json` 头与响应一起。它还会使用标志 `JSON_THROW_ON_ERROR` 和 `JSON_UNESCAPED_SLASHES` 来编码 JSON。 +> **注意:** 默认情况下,Flight 会发送 `Content-Type: application/json` 头部与响应一起。它还会使用标志 `JSON_THROW_ON_ERROR` 和 `JSON_UNESCAPED_SLASHES` 来编码 JSON。 #### 带状态码的 JSON @@ -75,16 +75,16 @@ Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT); #### 更改 JSON 参数顺序 `Flight::json()` 是一个非常旧的方法,但 Flight 的目标是维护项目的向后兼容性。 -如果您想重新排序参数以使用更简单的语法,您可以像[任何其他 Flight 方法](/learn/extending)一样重新映射 JSON 方法: +实际上,如果您想重新排列参数顺序以使用更简单的语法,您可以像 [任何其他 Flight 方法](/learn/extending) 一样重新映射 JSON 方法: ```php Flight::map('json', function($data, $code = 200, $options = 0) { - // 现在在使用 json() 方法时,您不必 `true, 'utf-8'` 了! + // 现在在使用 json() 方法时,您不必再使用 `true, 'utf-8'`! Flight::_json($data, $code, true, 'utf-8', $options); } -// 现在它可以这样使用 +// 现在可以这样使用 Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT); ``` @@ -98,10 +98,10 @@ _v3.10.0_ ```php Flight::route('/users', function() { $authorized = someAuthorizationCheck(); - // 检查用户是否授权 + // 检查用户是否已授权 if($authorized === false) { Flight::jsonHalt(['error' => 'Unauthorized'], 401); - // 这里不需要 exit; + // 这里不需要 exit。 } // 继续执行路由的其余部分 @@ -113,7 +113,7 @@ Flight::route('/users', function() { ```php Flight::route('/users', function() { $authorized = someAuthorizationCheck(); - // 检查用户是否授权 + // 检查用户是否已授权 if($authorized === false) { Flight::halt(401, json_encode(['error' => 'Unauthorized'])); } @@ -155,7 +155,7 @@ Flight::response()->addResponseBodyCallback(function($body) { }); ``` -您可以添加多个回调,它们将按添加顺序运行。因为这可以接受任何 [callable](https://www.php.net/manual/en/language.types.callable.php),它可以接受类数组 `[ $class, 'method' ]`、闭包 `$strReplace = function($body) { str_replace('hi', 'there', $body); };`,或函数名 `'minify'`,例如如果您有一个函数来压缩您的 HTML 代码。 +您可以添加多个回调,它们将按添加顺序运行。因为这可以接受任何 [callable](https://www.php.net/manual/en/language.types.callable.php),它可以接受类数组 `[ $class, 'method' ]`、闭包 `$strReplace = function($body) { str_replace('hi', 'there', $body); };`,或函数名 `'minify'`,例如如果您有一个函数来压缩 HTML 代码。 **注意:** 如果您使用 `flight.v2.output_buffering` 配置选项,路由回调将不起作用。 @@ -225,9 +225,9 @@ Flight::route('/@id', function($id) { Flight::response()->status(); // 200 ``` -### 设置响应头 +### 设置响应头部 -您可以使用 `header` 方法设置响应内容的类型等头: +您可以使用 `header` 方法设置诸如响应内容类型的头部: ```php // 这将以纯文本形式向用户的浏览器发送 "Hello, World!" @@ -280,7 +280,7 @@ Flight::halt(); Flight::halt(200, 'Be right back...'); ``` -调用 `halt` 将丢弃直到该点的任何响应内容并停止所有执行。 +调用 `halt` 将丢弃到该点的任何响应内容并停止所有执行。 如果您想停止框架并输出当前响应,请使用 `stop` 方法: ```php @@ -289,14 +289,13 @@ Flight::stop($httpStatusCode = null); > **注意:** `Flight::stop()` 有一些奇怪的行为,例如它会输出响应但继续执行您的脚本,这可能不是您想要的。您可以在调用 `Flight::stop()` 后使用 `exit` 或 `return` 来防止进一步执行,但一般推荐使用 `Flight::halt()`。 -这将保存头键和值到响应对象。在请求生命周期结束时, -它将构建头并发送响应。 +这将保存头部键和值到响应对象。在请求生命周期结束时,它将构建头部并发送响应。 ## 高级用法 -### 立即发送头 +### 立即发送头部 -有时您需要对头进行自定义操作,并在您正在处理的代码行上发送头。 +有时您需要对头部进行自定义操作,并在您正在处理的代码行上发送头部。 如果您正在设置 [streamed route](/learn/routing),这就是您需要的。通过 `response()->setRealHeader()` 可以实现。 ```php @@ -324,11 +323,11 @@ my_func({"id":123}); 如果您不传递查询参数名称,它将默认使用 `jsonp`。 -> **注意:** 如果您在 2025 年及以后仍在使用 JSONP 请求,请加入聊天告诉我们原因!我们喜欢听一些好的战斗/恐怖故事! +> **注意:** 如果您在 2025 年及以后仍然使用 JSONP 请求,请加入聊天并告诉我们原因!我们喜欢听一些好的战斗/恐怖故事! ### 清空响应数据 -您可以使用 `clear()` 方法清空响应主体和头。这将清除分配给响应的任何头、清空响应主体,并将状态码设置为 `200`。 +您可以使用 `clear()` 方法清空响应主体和头部。这将清除分配给响应的任何头部、清空响应主体,并将状态码设置为 `200`。 ```php Flight::response()->clear(); @@ -339,21 +338,19 @@ Flight::response()->clear(); 如果您只想清空响应主体,您可以使用 `clearBody()` 方法: ```php -// 这将保留在 response() 对象上设置的任何头。 +// 这仍然会保留在 response() 对象上设置的任何头部。 Flight::response()->clearBody(); ``` ### HTTP 缓存 -Flight 提供内置支持 HTTP 级别的缓存。如果满足缓存条件, -Flight 将返回 HTTP `304 Not Modified` 响应。下次客户端请求相同资源时,他们将被提示使用本地缓存版本。 +Flight 提供内置支持 HTTP 级别的缓存。如果满足缓存条件,Flight 将返回 HTTP `304 Not Modified` 响应。下次客户端请求相同资源时,他们将被提示使用本地缓存版本。 #### 路由级别缓存 如果您想缓存整个响应,您可以使用 `cache()` 方法并传递缓存时间。 ```php - // 这将缓存响应 5 分钟 Flight::route('/news', function () { Flight::response()->cache(time() + 300); @@ -369,9 +366,7 @@ Flight::route('/news', function () { ### Last-Modified -您可以使用 `lastModified` 方法并传递 UNIX 时间戳来设置页面最后修改的日期 -和时间。客户端将继续使用他们的缓存,直到 -最后修改值更改。 +您可以使用 `lastModified` 方法并传递 UNIX 时间戳来设置页面最后修改的日期和时间。客户端将持续使用他们的缓存,直到最后修改值更改。 ```php Flight::route('/news', function () { @@ -391,9 +386,7 @@ Flight::route('/news', function () { }); ``` -请记住,调用 `lastModified` 或 `etag` 都会设置并检查 -缓存值。如果请求之间的缓存值相同,Flight 将立即 -发送 `HTTP 304` 响应并停止处理。 +请记住,调用 `lastModified` 或 `etag` 都会设置和检查缓存值。如果请求之间的缓存值相同,Flight 将立即发送 `HTTP 304` 响应并停止处理。 ### 下载文件 @@ -404,6 +397,8 @@ _v3.12.0_ ```php Flight::route('/download', function () { Flight::download('/path/to/file.txt'); + // 从 v3.17.1 开始,您可以为下载指定自定义文件名 + Flight::download('/path/to/file.txt', 'custom_name.txt'); }); ``` @@ -416,9 +411,10 @@ Flight::route('/download', function () { ## 故障排除 - 如果重定向不起作用,请确保在方法中添加 `return;`。 -- `stop()` 和 `halt()` 不是一回事。`halt()` 将立即停止执行,而 `stop()` 将允许执行继续。 +- `stop()` 和 `halt()` 不是同一件事。`halt()` 将立即停止执行,而 `stop()` 将允许执行继续。 ## 更新日志 +- v3.17.1 - 在 `downloadFile()` 方法中添加了 `$fileName`。 - v3.12.0 - 添加了 downloadFile 辅助方法。 - v3.10.0 - 添加了 `jsonHalt`。 - v1.0 - 初始发布。 \ No newline at end of file diff --git a/content/v3/zh/learn/routing.md b/content/v3/zh/learn/routing.md index 54b123b2..a98efc9d 100644 --- a/content/v3/zh/learn/routing.md +++ b/content/v3/zh/learn/routing.md @@ -4,9 +4,9 @@ Flight PHP 中的路由将 URL 模式映射到回调函数或类方法,从而实现快速且简单的请求处理。它设计用于最小开销、适合初学者的使用方式,并且无需外部依赖即可扩展。 ## 理解 -路由是 Flight 中连接 HTTP 请求与应用程序逻辑的核心机制。通过定义路由,您可以指定不同的 URL 如何触发特定代码,无论是通过函数、类方法还是控制器动作。Flight 的路由系统灵活,支持基本模式、命名参数、正则表达式,以及高级功能如依赖注入和资源路由。这种方法使您的代码保持有序且易于维护,同时对初学者快速简单,对高级用户可扩展。 +路由是 Flight 中连接 HTTP 请求与应用程序逻辑的核心机制。通过定义路由,您可以指定不同 URL 如何触发特定代码,无论是通过函数、类方法还是控制器动作。Flight 的路由系统灵活,支持基本模式、命名参数、正则表达式,以及依赖注入和资源路由等高级功能。这种方法使您的代码保持组织性和易维护性,同时对初学者快速简单,对高级用户可扩展。 -> **注意:** 想要更多了解路由?请查看 ["为什么使用框架?"](/learn/why-frameworks) 页面以获取更深入的解释。 +> **注意:** 想了解更多关于路由的信息?请查看 ["为什么使用框架?"](/learn/why-frameworks) 页面,以获取更深入的解释。 ## 基本用法 @@ -22,7 +22,7 @@ Flight::route('/', function(){ > 路由按照定义顺序匹配。第一个匹配请求的路由将被调用。 ### 使用函数作为回调 -回调可以是任何可调用的对象。因此,您可以使用常规函数: +回调可以是任何可调用的对象。因此,您可以使用普通函数: ```php function hello() { @@ -77,11 +77,11 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **注意:** 默认情况下,当框架内调用控制器时,`flight\Engine` 类总是被注入,除非您通过 [依赖注入容器](/learn/dependency-injection-container) 指定。 +> **注意:** 默认情况下,当框架内调用控制器时,总是注入 `flight\Engine` 类,除非您通过 [依赖注入容器](/learn/dependency-injection-container) 指定。 ### 方法特定路由 -默认情况下,路由模式与所有请求方法匹配。您可以通过在 URL 前放置标识符来响应特定方法。 +默认情况下,路由模式会匹配所有请求方法。您可以通过在 URL 前放置标识符来响应特定方法。 ```php Flight::route('GET /', function () { @@ -108,6 +108,38 @@ Flight::route('GET|POST /', function () { }); ``` +### HEAD 和 OPTIONS 请求的特殊处理 + +Flight 为 `HEAD` 和 `OPTIONS` HTTP 请求提供内置处理: + +#### HEAD 请求 + +- **HEAD 请求** 被视为与 `GET` 请求相同,但 Flight 在发送给客户端之前自动移除响应体。 +- 这意味着您可以为 `GET` 定义路由,HEAD 请求到同一 URL 将仅返回标头(无内容),符合 HTTP 标准。 + +```php +Flight::route('GET /info', function() { + echo 'This is some info!'; +}); +// HEAD 请求到 /info 将返回相同的标头,但无体。 +``` + +#### OPTIONS 请求 + +`OPTIONS` 请求由 Flight 为任何定义的路由自动处理。 +- 当收到 OPTIONS 请求时,Flight 以 `204 No Content` 状态响应,并包含 `Allow` 标头,列出该路由支持的所有 HTTP 方法。 +- 除非您想要自定义行为或修改响应,否则无需为 OPTIONS 定义单独路由。 + +```php +// 对于定义为: +Flight::route('GET|POST /users', function() { /* ... */ }); + +// OPTIONS 请求到 /users 将响应: +// +// Status: 204 No Content +// Allow: GET, POST, HEAD, OPTIONS +``` + ### 使用路由器对象 此外,您可以获取路由器对象,它提供了一些辅助方法供您使用: @@ -143,7 +175,7 @@ Flight::route('/user/[0-9]+', function () { 虽然此方法可用,但推荐使用命名参数,或带有正则表达式的命名参数,因为它们更易读且易于维护。 ### 命名参数 -您可以在路由中指定命名参数,这些参数将被传递到您的回调函数中。**这更多是为了路由的可读性。请参阅下面的重要注意事项部分。** +您可以在路由中指定命名参数,这些参数将传递给您的回调函数。**这主要是为了路由的可读性。请参阅下面关于重要注意事项的部分。** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -151,7 +183,7 @@ Flight::route('/@name/@id', function (string $name, string $id) { }); ``` -您也可以使用 `:` 分隔符将正则表达式与命名参数结合: +您也可以使用 `:` 分隔符为命名参数包含正则表达式: ```php Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { @@ -160,11 +192,11 @@ Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { }); ``` -> **注意:** 不支持使用位置参数匹配正则表达式组 `()`。例如:`:'\(` +> **注意:** 不支持使用位置参数匹配正则组 `()`。例如:`:'\(` #### 重要注意事项 -在上面的示例中,看起来 `@name` 直接绑定到变量 `$name`,但实际上并非如此。回调函数中参数的顺序决定了传递给它的内容。如果您在回调函数中切换参数顺序,变量也会相应切换。以下是一个示例: +在上面的示例中,`@name` 似乎直接绑定到变量 `$name`,但事实并非如此。回调函数中参数的顺序决定了传递给它的内容。如果您在回调函数中切换参数顺序,变量也会切换。下面是一个示例: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -176,7 +208,7 @@ Flight::route('/@name/@id', function (string $id, string $name) { _请小心_ 设置路由和回调函数时! ### 可选参数 -您可以通过用括号包围段来指定可选的命名参数,用于匹配。 +您可以通过将段括在括号中来指定可选的命名参数,用于匹配。 ```php Flight::route( @@ -191,10 +223,10 @@ Flight::route( ); ``` -未匹配的任何可选参数将被作为 `NULL` 传递。 +未匹配的任何可选参数将作为 `NULL` 传递。 ### 通配符路由 -匹配仅针对单个 URL 段进行。如果您想匹配多个段,可以使用 `*` 通配符。 +匹配仅在单个 URL 段上进行。如果您想匹配多个段,可以使用 `*` 通配符。 ```php Flight::route('/blog/*', function () { @@ -212,13 +244,14 @@ Flight::route('*', function () { ### 404 未找到处理程序 -默认情况下,如果找不到 URL,Flight 将发送一个非常简单且朴素的 `HTTP 404 Not Found` 响应。如果您想要更自定义的 404 响应,您可以 [映射](/learn/extending) 自己的 `notFound` 方法: +默认情况下,如果找不到 URL,Flight 将发送非常简单且朴素的 `HTTP 404 Not Found` 响应。 +如果您想要更自定义的 404 响应,您可以 [映射](/learn/extending) 自己的 `notFound` 方法: ```php Flight::map('notFound', function() { $url = Flight::request()->url; - // 您也可以使用 Flight::render() 和自定义模板。 + // 您也可以使用 Flight::render() 与自定义模板。 $output = <<My Custom 404 Not Found

The page you have requested {$url} could not be found.

@@ -232,12 +265,41 @@ Flight::map('notFound', function() { }); ``` +### 方法未找到处理程序 + +默认情况下,如果找到 URL 但方法不允许,Flight 将发送非常简单且朴素的 `HTTP 405 Method Not Allowed` 响应(例如:Method Not Allowed. Allowed Methods are: GET, POST)。它还将包含 `Allow` 标头,带有该 URL 的允许方法。 + +如果您想要更自定义的 405 响应,您可以 [映射](/learn/extending) 自己的 `methodNotFound` 方法: + +```php +use flight\net\Route; + +Flight::map('methodNotFound', function(Route $route) { + $url = Flight::request()->url; + $methods = implode(', ', $route->methods); + + // 您也可以使用 Flight::render() 与自定义模板。 + $output = <<My Custom 405 Method Not Allowed +

The method you have requested for {$url} is not allowed.

+

Allowed Methods are: {$methods}

+ HTML; + + $this->response() + ->clearBody() + ->status(405) + ->setHeader('Allow', $methods) + ->write($output) + ->send(); +}); +``` + ## 高级用法 ### 路由中的依赖注入 -如果您想通过容器(PSR-11、PHP-DI、Dice 等)使用依赖注入,仅在直接创建对象并使用容器创建对象,或使用字符串定义类和要调用的方法时可用。您可以前往 [依赖注入](/learn/dependency-injection-container) 页面获取更多信息。 +如果您想通过容器使用依赖注入(PSR-11、PHP-DI、Dice 等),唯一可用的路由类型是自己直接创建对象并使用容器创建对象,或者使用字符串定义类和要调用的方法。您可以前往 [依赖注入](/learn/dependency-injection-container) 页面获取更多信息。 -以下是一个快速示例: +这是一个快速示例: ```php @@ -260,7 +322,7 @@ class Greeting // index.php -// 使用所需的参数设置容器 +// 使用您需要的任何参数设置容器 // 请参阅依赖注入页面以获取有关 PSR-11 的更多信息 $dice = new \Dice\Dice(); @@ -289,9 +351,9 @@ Flight::route('/hello/@id', 'Greeting::hello'); Flight::start(); ``` -### 将执行传递到下一个路由 +### 将执行传递给下一个路由 已弃用 -您可以通过从回调函数返回 `true` 将执行传递到下一个匹配的路由。 +您可以通过从回调函数返回 `true` 将执行传递给下一个匹配的路由。 ```php Flight::route('/user/@name', function (string $name) { @@ -331,8 +393,8 @@ class UserController { ``` -这在 URL 发生变化时特别有用。在上面的示例中,假设用户已移动到 `/admin/users/@id`。 -使用路由别名,您无需在代码中查找所有旧 URL 并更改它们,因为别名现在将返回 `/admin/users/5`,如上面的示例。 +这在 URL 发生变化时特别有用。在上面的示例中,假设用户已移动到 `/admin/users/@id` 而不是 `/users/@id`。 +有了路由别名,您不再需要在代码中查找所有旧 URL 并更改它们,因为别名现在将返回 `/admin/users/5`,如上面的示例。 路由别名在组中仍然有效: @@ -348,14 +410,14 @@ Flight::group('/users', function() { 如果您想检查匹配的路由信息,有两种方式可以做到: 1. 您可以使用 `Flight::router()` 对象上的 `executedRoute` 属性。 -2. 您可以通过在路由方法中将第三个参数传递为 `true` 来请求将路由对象传递到您的回调。路由对象将始终作为传递给回调函数的最后一个参数。 +2. 您可以通过在路由方法中将第三个参数传递为 `true` 来请求将路由对象传递给您的回调。路由对象将始终作为传递给回调函数的最后一个参数。 #### `executedRoute` ```php Flight::route('/', function() { $route = Flight::router()->executedRoute; // 使用 $route 执行某些操作 - // 与之匹配的 HTTP 方法数组 + // 匹配的 HTTP 方法数组 $route->methods; // 命名参数数组 @@ -367,7 +429,7 @@ Flight::route('/', function() { // 包含 URL 模式中任何 '*' 的内容 $route->splat; - // 显示 URL 路径……如果您真的需要它 + // 显示 URL 路径...如果您真的需要它 $route->pattern; // 显示分配给此的中间件 @@ -383,7 +445,7 @@ Flight::route('/', function() { #### 在路由定义中传递 `true` ```php Flight::route('/', function(\flight\net\Route $route) { - // 与之匹配的 HTTP 方法数组 + // 匹配的 HTTP 方法数组 $route->methods; // 命名参数数组 @@ -395,7 +457,7 @@ Flight::route('/', function(\flight\net\Route $route) { // 包含 URL 模式中任何 '*' 的内容 $route->splat; - // 显示 URL 路径……如果您真的需要它 + // 显示 URL 路径...如果您真的需要它 $route->pattern; // 显示分配给此的中间件 @@ -422,7 +484,7 @@ Flight::group('/api/v1', function () { }); ``` -您甚至可以嵌套组: +您甚至可以嵌套组的组: ```php Flight::group('/api', function () { @@ -452,7 +514,7 @@ Flight::group('/api', function () { #### 使用对象上下文的分组 -您仍然可以使用以下方式与 `Engine` 对象一起使用路由分组: +您仍然可以使用以下方式与 `Engine` 对象进行路由分组: ```php $app = Flight::app(); @@ -481,10 +543,10 @@ Flight::group('/api/v1', function () { Flight::route('/users', function () { // 匹配 /api/v1/users }); -}, [ MyAuthMiddleware::class ]); // 或 [ new MyAuthMiddleware() ] 如果您想使用实例 +}, [ MyAuthMiddleware::class ]); // 或者 [ new MyAuthMiddleware() ] 如果您想使用实例 ``` -请参阅 [组中间件](/learn/middleware#grouping-middleware) 页面以获取更多细节。 +请参阅 [组中间件](/learn/middleware#grouping-middleware) 页面的更多详细信息。 ### 资源路由 您可以使用 `resource` 方法为资源创建一组路由。这将为遵循 RESTful 约定的资源创建一组路由。 @@ -552,9 +614,9 @@ class UsersController ##### 别名基 -您可以配置 `aliasBase`。默认情况下,别名是指定 URL 的最后部分。 -例如 `/users/` 将导致 `aliasBase` 为 `users`。创建这些路由时, -别名将是 `users.index`、`users.create` 等。如果您想更改别名,请将 `aliasBase` +您可以配置 `aliasBase`。默认情况下,别名是指定 URL 的最后一部分。 +例如 `/users/` 将导致 `aliasBase` 为 `users`。当这些路由创建时, +别名是 `users.index`、`users.create` 等。如果您想更改别名,请将 `aliasBase` 设置为您想要的值。 ```php @@ -566,12 +628,12 @@ Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); 您也可以使用 `only` 和 `except` 选项指定要创建哪些路由。 ```php -// 只白名单这些方法,黑名单其余 +// 只允许这些方法并黑名单其余 Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' ] ]); ``` ```php -// 只黑名单这些方法,白名单其余 +// 只黑名单这些方法并白名单其余 Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` @@ -587,13 +649,13 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid ### 流式响应 -您现在可以使用 `stream()` 或 `streamWithHeaders()` 向客户端流式传输响应。 -这对于发送大文件、长时间运行的过程或生成大响应很有用。 +您现在可以使用 `stream()` 或 `streamWithHeaders()` 向客户端流式传输响应。 +这对于发送大文件、长时间运行的进程或生成大响应很有用。 流式传输路由的处理方式与常规路由略有不同。 > **注意:** 仅当您将 [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) 设置为 `false` 时,才支持流式响应。 -#### 手动标头流式传输 +#### 手动标头的流式传输 您可以通过在路由上使用 `stream()` 方法向客户端流式传输响应。如果您 这样做,您必须在向客户端输出任何内容之前手动设置所有标头。 @@ -609,8 +671,8 @@ Flight::route('/@filename', function($filename) { // 如果您在路由执行后有额外的标头要设置 // 您必须在回显任何内容之前定义它们。 - // 它们必须全部是 header() 函数的原始调用或 - // 调用 Flight::response()->setRealHeader() + // 它们必须全部是 header() 函数的原始调用或 + // Flight::response()->setRealHeader() 的调用 header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); // 或 $response->setRealHeader('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); @@ -643,7 +705,7 @@ Flight::route('/stream-users', function() { // 您可以在这里添加任何额外的标头 // 您只需使用 header() 或 Flight::response()->setRealHeader() - // 无论您如何拉取数据,仅作为示例... + // 无论您如何拉取数据,只是一个示例... $users_stmt = Flight::db()->query("SELECT id, first_name, last_name FROM users"); echo '{'; @@ -654,7 +716,7 @@ Flight::route('/stream-users', function() { echo ','; } - // 这是在向客户端发送数据时必需的 + // 这对于将数据发送到客户端是必需的 ob_flush(); } echo '}'; @@ -663,31 +725,30 @@ Flight::route('/stream-users', function() { })->streamWithHeaders([ 'Content-Type' => 'application/json', 'Content-Disposition' => 'attachment; filename="users.json"', - // 可选状态码,默认 200 + // 可选状态代码,默认 200 'status' => 200 ]); ``` ## 另请参阅 -- [中间件](/learn/middleware) - 使用中间件进行路由的认证、日志记录等。 +- [中间件](/learn/middleware) - 使用中间件与路由进行身份验证、日志记录等。 - [依赖注入](/learn/dependency-injection-container) - 简化路由中的对象创建和管理。 - [为什么使用框架?](/learn/why-frameworks) - 理解使用像 Flight 这样的框架的好处。 - [扩展](/learn/extending) - 如何使用自己的功能扩展 Flight,包括 `notFound` 方法。 -- [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - PHP 用于正则表达式匹配的函数。 +- [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - PHP 正则表达式匹配函数。 ## 故障排除 - 路由参数按顺序匹配,而不是按名称。确保回调参数顺序与路由定义匹配。 - 使用 `Flight::get()` 不会定义路由;对于路由,请使用 `Flight::route('GET /...')` 或组中的路由器对象上下文(例如 `$router->get(...)`)。 -- executedRoute 属性仅在路由执行后设置;在执行前它是 NULL。 -- 流式传输需要禁用遗留的 Flight 输出缓冲功能(`flight.v2.output_buffering = false`)。 -- 对于依赖注入,仅某些路由定义支持基于容器的实例化。 +- executedRoute 属性仅在路由执行后设置;执行前为 NULL。 +- 流式传输需要禁用遗留 Flight 输出缓冲功能(`flight.v2.output_buffering = false`)。 +- 对于依赖注入,只有某些路由定义支持基于容器的实例化。 ### 404 未找到或意外路由行为 -如果您看到 404 未找到错误(但您发誓它确实存在,并且不是拼写错误),这实际上可能是因为您在路由端点中返回了一个值而不是简单地回显它。这个原因是有意的,但可能会让一些开发者措手不及。 +如果您看到 404 未找到错误(但您发誓它确实存在,并且不是拼写错误),这实际上可能是因为您在路由端点中返回值而不是只是回显它。这种情况是有意的,但可能会偷偷影响一些开发者。 ```php - Flight::route('/hello', function(){ // 这可能会导致 404 未找到错误 return 'Hello World'; @@ -697,12 +758,11 @@ Flight::route('/hello', function(){ Flight::route('/hello', function(){ echo 'Hello World'; }); - ``` -这个原因是因为路由器中内置了一个特殊机制,将返回输出处理为“转到下一个路由”的信号。 +原因是因为路由器中内置了一个特殊机制,将返回输出处理为“转到下一个路由”的信号。 您可以在 [路由](/learn/routing#passing) 部分查看该行为的文档。 ## 更新日志 - v3:添加了资源路由、路由别名和流式传输支持、路由组和中间件支持。 -- v1:绝大多数基本功能可用。 \ No newline at end of file +- v1:大多数基本功能可用。 \ No newline at end of file From 7ebf727d10440aa9a39e1ab75323df73fb683d48 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Sat, 4 Oct 2025 15:59:54 +0100 Subject: [PATCH 08/36] correction on OPTIONS behavior --- content/v3/en/learn/routing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/v3/en/learn/routing.md b/content/v3/en/learn/routing.md index a6ad594a..458e91ea 100644 --- a/content/v3/en/learn/routing.md +++ b/content/v3/en/learn/routing.md @@ -129,7 +129,7 @@ Flight::route('GET /info', function() { `OPTIONS` requests are automatically handled by Flight for any defined route. - When an OPTIONS request is received, Flight responds with a `204 No Content` status and an `Allow` header listing all supported HTTP methods for that route. -- You do not need to define a separate route for OPTIONS unless you want custom behavior or to modify the response. +- You do not need to define a separate route for OPTIONS. ```php // For a route defined as: From cd623271f4b602cdf9bb7f89185084d4560929aa Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Sat, 4 Oct 2025 16:49:48 +0100 Subject: [PATCH 09/36] updated image size for twitter --- public/images/flight-logo-black-bg.png | Bin 40486 -> 37779 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/public/images/flight-logo-black-bg.png b/public/images/flight-logo-black-bg.png index 5124d9ed3f8e2e46166b012123dc08e13fd5fcdb..a3d298a5050d63e39e2ef38fcd83fdc9ed197760 100644 GIT binary patch literal 37779 zcmeEt^;?utw>AvjLr4lUbR*r}B1j`4Ap#=O-5oS{KrIqfl7yVma?M->e=-}3akGR_iK)DD)j*?%)%nerH<{8EQ>;@N zwHurpehijn@m5&T;+te)BQIJeMzjw%PUx{qNBN9&&4lSKP-rSKv-%7{-+)fD}40NZhx+RJw!5*-Q) zxY6`I>?B(r&3l&b@d0X%{G>@=`j_>HY!aKU%5~KU!vARX=~zMFe?E5=QZOVAyq}kf zN%2;Sxy)Wit0ic2+DAT-#LVuTJLX?L3G*~Dxl7P|Fg^SU-sLkP!W*h!h*bOWYk8#@ zZW)P^CjzxlV*8OG4Eb;)>zdBq-I?mO7d0OjosQQzC(i97jjHVGD5XCg$x%?~jC!Q7HJX=;14!<8ZW_gT~R=)50lQA)wbTm{Xt>N;Y7(5X8$ig!Ga3KfYyD+3ihlZLi`NjL+ z+ldM0J3hG! zOP7z<*h}_1#kouxti7vy7jmC|P$YR`^72oSf!yjq>e!F-wF%PzPA1h9mZqzJ>|+r! zn1>Jxk?XTvcD5HK7PhdzCC2PIIp};poFp+rxh_y?Tb^nO<-6@M7)rumn*3O+8d-KnVL?{UTwNe`3vTH=Nb<4q3|} z%EmP4U}s)J*7t1cO+G;+bQ!s)Lp?)O!D8sk+@vJ@c%;NwY^)#{`Yam>%e*W;*t11C zmxML(enk_%**Pgm{Mt6gRHQE(&VArp-EuHt81IQu!NhWSwGt;~p@%AgrWAL#NW>V? zkwCAM$1S56rjOBg4~mZ7B%m>>CrzmI23H^X&i~b`CG+#WxqN~IC=te!=9>y~VaGt% zYTnLpJXrMRrnObu(-s+IB6;!KlQAugT$R(Jo+Q?vJ&BAzl|ON1_`-h%jWREbLv^J* z53(kk{30$^Kd7$`vn`ADevsniqpq|WPn^GFyV$GWmk&Y5Q-iV5uF`@6GX#Y=ZC!@f zj?vy;-~UdWHV7RJL6G$aGj^m03g-C)Bvp?UIa?D(v%{X*k9&f1af83Rc^$3DIQ64#*epmXI zaD`p32pWQ}kSggatIXj@usiiLg2kw+XyjJE&h=Z0uoDrd$I}*Bg>Rkl;| zXFF5!T`?4vf04-8CmT&_9A%0Oek!V_@+w?5!DXX&^VQM@D`6BbA@s4^3Db;%qtX0t zzkFCmK!rWB#ou+m-(4P4ukPW%x_rX;>?8DaTPU75#;tya--d*)>2jUwp3#^>NGsgtC$7?W{I^f8&SO<3Wj&1P{q?x=*(5V z^I9nH6H(X7H~C)5&o>N3gI4B4jTa`CP#SB_k|6tygqKnu+UkbUhO!{%g-LsdR324i zkj$nlKUJ~T(Her$p#&=?OB1xi{=V+!`}c?L52kxw9QaCPySr|f7kXySX z{jSI#!7z!kIa~%(${&uv5OW$A^NJpul!HMfiG_>#bK6!g>}+q2*{^L$k%Vj#-`3V; zt&i1tRr=`*y~_X&d^J2Fx>g)-MUBsuzL(BhRYZkZzjE}7g%o~&7O*^Pe_lqL0d;}1 zjFp<2uKdi;f1bg_r2fVB$`zUuo7EfGBFpD@Ffx<)L3QQ({e^&*6MF-6(nlT%^BoAD9}qFVLKnmFY(c zHR%&X-E79{iJly<|0esY6erk76^e?d_L-m1xZa(ok*Z|qmV9C(;LFw=TwV-08Cm8d zO7y)}o=RWoW_HUC&Nw8?eb#!gc zj7Yngs?_;p&u_-{Rn{XpwY%Qp;>e`)pnVEFJfwJvtx2P|+t=$rv$c3yIm>-&+SVv~ zJ~+#}U|&3RwA7GW2uBXz)+>V z|9BzAJboSil^0%?8}=G46ytLp7VTA_k@o%F?V6*USiF#f$;elw+^=B~Y5&IGA+!sg zr_STaLOyPd6-2g$;ZV(C@TbR73aFgL5?u!+`lX=esitb-dxUEeKGx>h5mAU*9ql|B z%n;KGgp+&h&5BG+;2dp75_flgk?>gqfN0VrFjp;2FNwoI>*I^H{!gE@o3MB=xk~7j z-Y5E>=C=qS4+>x^3g>mxbGh$K(gM8V;4OrSrQa1x#qQIt3aM62`e{E|)_Sr9FINV* zsL-goq|o4JmlOqoaMJSO=GV9`pEwy2YMOw%%K{R{8X+#@I@Oo;?!Qm6r)Xxdp$)7y ze?YhJ{!w+uRDCRrk%|k&`9xBTfUe(w8$lJ|mph z`q1QEKg3I;$|C(_kH-^nl)jyXUYvUT`=bd8yyqm_s1FPUR!L0FmItWGM@P z3IGkSpJ1 zTXNc6LJPk1k{4!`poke3120;p+ZaA^87E3OlfceUbOk}Hcu|K}V@@sQKYNlrO+ydK z1@)GrmL^C-6N-vi#{5{+wb1jZH`jceZGo2-jEs*7tYh{9--BZ5*O5Slp-8||3_@$A znS#pY_4QK#aLL@#mfb_iyGuwQq;p#CP^so~nD-rv_=oum2b!eox-+RMem40!KQ04m zPK!m%L}Fa$`Y|N+Z?VzF_IKuA4pp`+Y zz?iFZ`!I4h{$oP?#H+_UG$Mk^sZlPq(r&EHO#Nuy9>!;(A zwxnww)y(3OA$2!6NNR7;}fL zVjK-)-$%}OuCPUmiAEpP&Iq-qADCi)S@<9IGAG+(1l&K*5KWVOsg$h{Xx5s*|CaYZ zKTbIq6>C*PQyxP-Q<5`HzPzXOMQKR`>*ji#)E%_{(-Sh6^?`)Dn{rm2!g%ZXhSbDe zI^s~?QgGJRQdY8%N4OOHoRXln*nc)g5WoaMy~sV_#l%-3Ln>gKq3^wGPiiaY?yPtU!PEW{sR{oY*td1hwodqTpBbP*SpsWSqp z8~C$QFrtP*XD`$%{ygG$u~m?1vA(i70#nVzKZ3I9usoTrb|~-_Gpe$E71*nkgag&j z%)N*L`|f!`vKUi!8|psADoksF=sW>6w)2;cUIf z{>?Ufi#e54v&a5WfC=pWe!D4-+T?z|vHob`Le-pV(%p7%zLB{Z@YZH_7*F$Y!HwSz zLDTufEfqANccL?=NiO1y&ay8_aqtP{Z>1P=TKvbJHH=nc`D$w&ZjTmkPXCP?Sphxl zE<{?f|08G2UOTunEDFP0V{iU*Xfy#gPCT9mW(hp674v3V8yz|j3CqLTa`^;P<<_jN z!2(moMnc9mI=d%NWqpy!h{Vfk-d|pQl5WE%bmpiaTx)5gj_w0pI0~@gp8fWw@moI3 zpqXli-ctMQgN6Hry8>LyAUmpw;3oD}H8>j+`fhdQtRP8VF+?1VgtwOOWI7n7(L{`YW_Z75IQDt926O42uf~L>~BsMB(ph4kfp2Bg}jSSI@nLxfg=ve4b?Yo@q<}% zTEgSNmOyxG2qXWO1PLGaiMHly7LBaHgk3qf`BJmvQd@wf<6ePzXH<^Ef~0d`DmEYu zOxMrBDQbVyQlQY_Ht50|X&s2TZ527?%m&_ic8ps zE!r+Z++Ypn4lE!qXo>zwC4n)kf3a9^M{b#xV6%z$T#jT;vd7p?%$AGjqmf#M#pSAA z#(Z3laork?e8jGY=%&%0A(7v~lWc%u>!U8A#7JTyuzdG7GKczG-2!e1Kcuz#(uduSusCTm>^tY`EZw^d$R45k|l z8h(3OJBo7c0N;B>M)62MKZ;OxM`gajtMg=QZ1o1Ny+|`&VaYDijhIaHSjYglLPKiy z?086uj9Sc{*RKXSs0tU8G@ZO_Jnz{XQFAn8{Y?&|Dpf1a_`Dh?`usmz)0Nv5s%-9; z#CPiHN?*jiEDRtyN%{Kq?!}1rG_(bT-DnUv=!P0hk{Yo0;quzjn0loqYG?D}=d&&Z zel+rQclIoAw`Oa9K0CO#wavuxB8S3I&`*TeB;UiNxImXH$KCH{85$v^_E_6bs?|7ln6*+(* zS)G5e_Q_Nps5q+)1m+GV{+E`Q{v(8wU83Kfe(>0|wWkSApVDS1v&FeZb(3$@NeNCt2<rz)nagnTa?%RLW?#v-V>t%m{w2_*G7$@mIiFdd>S z1%}D0lCFGyruq`PF?7!XkT(k-d5;xPrO+;25b@;K2K(1+8cO(NSV=DWGR^+C7T*Q{ z$xzLdU1nyfZOb8}K-1otZ#2TC79IH7iJYDZbk-lLzVIKywv*h&%P8G{z*y95^7ZOB zAr?6MohI}_Z7Vbd(i(hl!2NZ3r6=JlZ+-t4f;WLv+@hTr>+aOz7nNJ>_$)CN(z9k2 zZ_@;e)iP0xkbW3oV${fFcc2nJO>%n)R1QT;Kv>xC3CgpBfm&8a>LDlpO)HPX&lr>T zPd7c4T>8`Pzs0L>#&f+o&UVFesSB9fC{ybJ0%W096mVRG7t0j_a>@8WQK))~*Vlg= z<=BjWKQfdRM!r zUzD1t{Il20G^w^XR@A4)oK2FItM5hBvmPP~ReBw-M^f-vc{4~J__vD_=`N$>y$6JD zoK5m*W9W%u4C4LRTp!FV_We=<7(svCRYPlJ80Di$*Ynfqk4L^~Gfx<?kxG(kNE#d>b(gC^}U9`vx=ZPg!JH*AQpZ4}WhQ z`TkA)WbTXz*_^G79>7dPGN;&X#G?{Sk;Fp|8X+peNC52VEoY?C|A<^`X}_azNJ#mW zGi5lkgqFHu)0{V{d7+4soD(eBR*A0=(?h-+sy)pM3KJ9pOhR$EY&s^B>`I$ynVHPm zjA5g9<>pLv=9U~2P4Kt%+v{_mMYx!87D@Sw(s}c3y&>@lK)0O;X=u2%gLTV+IsG!emiHy$>v~uArX}^hKDRUv=E|lED7^td1FShm; zTD>B)^uZvYaV=JZJpxw_8cD<$b*jAM&EV=Mm2eZapWTLW&U$lwHz5nBdc=Lc*QwKD z78?n#uBStna;ZYu!Cq%-oe&b7Dv=bxB2(t8_|<*$#*t$tG;?))5z0{TuQ z5L%<(eDPBJ2p7M!(7IG=TZYXx`V5_7)N$TR@0IR3Gu_+|X4D^D?rqH1xgGCo6^JeW z`Ieb0rcdvo2;7UDAk(I4%bM-A!0z z1frNZVA&NP7f|(!DjgPN{28xg;3Dt-ayUx_W0ZIS+CdDiVZ7;~#EHiuvP(L1rf-|I z^gszPdSoTBNqx7Zq~zA{{|**B&mdBI|CkU!tc)9*>M6l0_EtI@X;fsw0w6SL_MgRP z8&=vRlMC55*j=0U-1FH^YV1bOUrzxEJx0Y_JC2%yf|k$w`-7~>5i*KwUo%(l@q#U% z29?eV&@@N+ju_$0&S)}LCzoSXRAKLvP1dISJD;(F*2AoH%*L;tEs7KqPjFMh%R=L& z$Ii6X89zW!hB}81ALT&k=$|Gs(1D>loz@#dnBWOgYGel|*wL2(a`WMF0JFDX5PV|$ec)ag*o`;M)d$zqR4#vFkV-tdphcFMg zT>F$yklBGkx9eEfrq;=jvd`nREFYH{hbAh%Xc}}THxt(%@bxjaF2OhL zf{!`$`QOC8H4L^(kPL;OaiC!wq6&BT-yABITaVCL{@w-$s0fUcRU{E(#urEqfAFbA zwS0w6L$Rf+fH5TBozemeI95GVW4J%qQQ*TIDb;1rUq z2*i=sB)=-gCb|fSqX|s{35)F!ECn%J{+hYC1ddPzqL9+e8B(97_xYaOp-d7=Nc2*B z1O*`slgV{=TFo$S8qb1pmh>kS+M}1X4+$~V43DgRv)PC!{}$`?UiKSD1sNs>Z-|U* z@Hvf26|izx-cyTlN#5VMl-o}6ilB~|f>(?5vgbh-!6xG>a;sN<_j-ghru}h-BIr9Y z(FF2ZpdrwLF}pXuzvMCR`!m1dwoQI@Z;t+#5fROv0Og;|R(L^qzj1 zwz}5aLWc$aDnb}bbg&P}U|9V<1Z78q4lf~SR7-XTf4)G(Wj#I)xHk`0S-H=-eY432 zMtywd7bPz%($O5SGo;a!X{BizU^c$Z7_G0T9oCp=+QVFe_`r%BZg?m z`t;3yuCDJ4C-z%P$vav3?evJim2EKR*H~R;_b{gPl91ENlETNig3W;zI$j}R!J|nR zh7pP;kA}W0V{JAqR?=MazIMZs+eZe1HsJkkzM*!q+M#)%o(*}g3GvLWBG4uh;&{;jwL;tsV0g>(R& z`WK8DOOjFupNCG;EOfNgG$3yor6h5x!jc$V=EPLI$#Kc^mo}`T2YhGd@n*>9)+b4z zS<(WZD*m7LIZ_s&gncnM&R?5o>+0QauoouzUZph<2c!`SmbwL*`8&j}qb_C{$MOH4w1YCR= z^$yH!Whx{7fR%fWR5}LqlP8xbXb60WrlV#QT*FQY?=~MnPB-y^hNf$^!?bW2=G;Z>(B^UQZl)q+ZRe1k+ zO2NV+R1ZTj5O*EuU5%u$vZg`crrKgE^^#b<$^Nr^T--Dd1L=8h`^=bz$RhIvTb%% z7Y-n2nbYW8YFEk~OA)#i481`4T+|&yK~KHy3VDrYaREGmt;79AQIu!+>Q)i38MP(^e~75RyNsb-a&O39Ldl0w66tZ_ z(fYX9#Rn*J$hGL-U?5bIh zmg?tjAU7bE1MsBeTv~}qBO53f)3C>ZW|r-FKIhSRC1G(Ef2qML zDQJ5!$(TzYlaYqubk`ujr=$^F;k2U2^SVp*t(z+1xv0lp?jMe2nVY-o{fg?|37;|G z;>r(wY0P~Z5lI^vx(PYAwCJK`gKBia7yCbzBA$KXszdEUW92=N5QmE%Jf78_CGaJ9 zC!?zoIGI8z@ICtO_WE7*Svyt9vri?XtcXdfiy;DPQF*IgRbG$1mj+iWc#|8z5@)SU zP!u7TlyhI{hN)kkUL%m67*)L-_#$Bhm|N?~Qan5taIc)VWBI_tL3`xgFL`qy*KG1; zrpoS!CSnKg>IJ3~+lA_)e;`I5QNmI?Eja0DKR| zsR-dz39t^eN!V76={fAVQY<8ad0^N67qb>dp4|fNG^Kj(0MyYcj{TSA=3$nlk)z{) zBtD?|{&^^>tM$)ksv*~GywEark2fsw89-$#YguUvi`KGU4BD8hbupT)anin<2lvz> z^$9PzJGgJ*a5h_W&&N8>pyL}yUH;nAmKH~nfPptIR7U`W?L*OH&0p4Inxa6bHC0vN=6;L{Xx_ zzJNW@+mK`OAe{LOT~l;&{Cj#bAq+7r?a5*IOZjd_o4c^+b@zJ}pU)q;jM>8RsjYTq zJyGa-fd4}nhW#kE+k#zFX%@Q*yb75vXnqZ! zu70*d@VPFbw#AJy2bm5sv70i`Y2b9WL$O5@wu8p5LW7?+Y$pvYMtM)q6lDN{&+NW_ zabNAxH2G}{U*G)m?W^Z@adnIxYziNN>9A`;C1?u=N_{DiMZzRrwaKU6I?_!B)K6?D zF6M*NGwj5GP^U0k*r1OCZ&Ch>c&(*-A}S3Ow?{dv6n`6L!3LzPolr5Cpa?O(r6$FC z>YRhSj@#i|v*8{e7HQm&LdOSP231E0Xrl>w^@uv4Sv2{IjO0EgejS3YiOpl#M^f5> z@p$$DQ9KiN)6&z9?GhjOF;zQOA7l{<9crm80LJ-rRm4Ddg=K#XeoLntBb!YbCIP`G zwSOIVHP2FJ@n-E`1$CcpH`m|gzsPHmuEbEuGFQniK>%&GmjitS=UEwUa76(+-ajg* zxrZzj$5+}xB$Mlu)1{~F71;6iz~P7k*t_vXGk|+y4_=dH&RbBj&P**J^A(d$CJV^` zv5jaj&ulVMdF-ZLOW$CBLzQ^avrI>I)IqGCGEaRZ1SJ9#8wv|((0nX*7UCLi&eSHN z5lFsR-c3UcW;qlv#WBehly7a|d-fW7E#q?MI;;;+OdG$MT@024VZGA6G`R4;iBje| z_g%KMAG&4lCb&daPz0(&q1!U*%R5s)lLr6Q!Uir{vZU(|FIM8BgV9WhN}KOM07rg2 zc<)*$64_E4L`6RCCj*TYJk&Bh3H&q9mRaa8L9IT$t3u++2c6ZtE%b2o>pW_q%kKD( z>I(q%#qX$Rla}DxfO%V9hn*h)3tMpzi?+25xW~B?#atTh0swA}MeGuCzn8Jfl@21a z_{aiiLs#GHkVs&WMjoy(D|<*U+p*W~=IxamQog;1Fyon!SV_2Ev1^Wu9R5)f^~)=%&NagDNu%t1Fyx346oxNa2s9C5E#mj zfY!tBM~NVF-5hRBxoE)yD$z*A<2G##dPz^mBo@t_&_usr`rlbHAss-pib)3_BkaLx zjHQaOo|y;ClsT3GV&IEZEk;~o=@e9iRlz9Rktq`%TckVNTr-qFU+-#MWLWt<;rNk@ z?~B!jZ@`g6ySb((e}yj3QwHB1D~L;AfiN*w+fJ$6fIFM7j&c|b5=@Z*G*Qk-QVwqX zPTM#CjKr;Z6#;V9;^ zzCfy0kXJlgjHy71fXEZFD0!{K3dPv^?9cnJmW|6K zAWH#G9=l5~$mXi&QZqZqh8AKh)0;N=8dimkW&@5FIaZ*aCTV*FH4}JQ{Q2(a2OgCq z>3*_rRD+7ybHG2?0_ZX_9F2d?avE zjS35_EkjfSJ7P1v_6O#YiN1_NKKbIO6(0Re_>Vswk;Hiz4R5Zm@;3odBvKOkb4v$t zKU`Lz-w2L3qX)HPKAaU~_<4|!flA!7Y+#hw2Qu~<43T$pOeNbXcRXz)$i0?<%xl>|+bs}4@;x+Jfgn7lb%y03fh(X8 zA2dlY;Mf+!sN=M0aes%BW7_Qhm>Alj5qKfE4Jg`*_ zt^yU}?T1lComYE2G0c%0s^#SBBSCn;un7jJc7k9!$mtCG<10HNzp3q}c}54YDCg0- zp9$~`rx?XY>u83a5+2RE4E1i%YQ>?A0CVxB`D(nd^J<|m&^die(TTuxBM!qM`&&^A zROLRRSLRaOk81(hp6=`hDOB}C8DYdQ8EBMDz=(rq(5W5{itYDc2IDWfhEjO~DOEm4 zK5}hB38n`BI?>a%xDCAS&fjU(9Uy83dTT*o=U|P~ihRjSkxB=u_6$+iO%^i!!@~i- zp`MCDFa|4prMPc}IXG0)C48P=i@<{jctB_zJ_lk-LL`nihCVIN zZRwPn7+XoX;&zAqAcRc*w z!9fce%eoiO5EkjS*~M-e6eipa5>}_mzF8c3Ab6tE(Y^jVO+n|6nFvnHTe#uf$(VX1 z5YImdoLmTzR$V-vt#dPK8Y1LucHPPW$&9g*ZuNW*5$hHK4v?qg8aa$&F>Olk`N&zX z{N?6tvnkm`Lwvj1$OQPQJS zlOnuOIM=@#ZrVh$XAfiV_z)X-!Vs# za@YoU8ILMWg3_ z1Xp=W648vKLg|(kxF{;{x(oL$WSIm+)hBMvagIE=Bw@J*un{5T=ZKVF7XLJ0MGEvoTkOW zdk6teSMS65s@%~-o{tC>eg@&#x~j1x95t%or{^o(aUX8eMNK@oXkcP@>N#KVX z*|J`#f;v2>sTb&U@AUta7@cQ7#1ICOCaF1gbcLUGV&tcvZ;c5JZY+j}(tZ}O(W(9= zD9)rJt_`w-6Flpv+#f;QC!;5UKBB^Iv7yMMQE?ET&MCxJ320htMUO3@n)q*oGz6pS z&K#O9yG}~PW6qMs=ClOhC>mY_=EZO47Jfu^q14G5K7}fkM2-a1&V*c&jJZ!y; zy(gz!aDy$BxH1 zXv2Ae0QPn?n=V`0{G(;s9>lEhhCq<;Pg4qk=&C2Iv@rf?|79OuE}FT+nO!8YU<7HLeu6TUk6dn?U*obNe6x3 zrQ>su+)_b-X#d1toD_6f$6d3`gpOs1x>fO`paumMy#Ny3+G%eZ96l%oCgt8-x1j7W zNy_=9AI0ET9Ab{$&>z3FN;J6eb zMqUKtksjbL6Z;})_uZ9x1k1iIAwgob){~s2U%CTkiK|y(Gk)#tj?h*qDeIvYv@K-O z{hm~1m-D>IZpQsR3-uqgtL=yW@pDj=?AiC$S!fci_h^WvKu;ar^>-o*QJ@vlQNJ&O z1fwKl-1#%TI*%>Vc}cM-z5ZM1U7t*8T?Y3ncSxF>>@vMIDrQdl!=Av~Sq_5=NAoBlCWLV6G6V7giipd?mQ8r1pyy|6FIte0a2LkOTi zMT69r{`KJ%_8`#FMsh&4Ojku(^L(BW3FJZ7N6@cmR{o=MW^>7^0QApGZFKxA$beyt zGUrzlBHnR&ka)w82RGl>PKpz{-ejvh7#)b^ux z%g*C5rKItA0@cOMcby5MHtnFzftDvdxVVJ7|E_#_FxaL`B z1KmKdTs@7&WEBPv!U48e4u?0gR3dJqsvf}+iH)a!jku7t3=NM6m)XI_3<+R08uLho z4W2x#?ye!7EmJ?=tfE2nvi2^qHoYp2!b5p;ey2$hKKN`+_s_pR1kvSX$PoB#33h;k z(!Kg>I7y6^-9+U!De1?${45Q!`j=k*r%#lE+Eq^(niZg9&jmCMFIy@;nN7M zY!Q-XRadNB2LQFncJ%6B#GMbmL}KoP*eYWpvpVgAm8|lS<85svS4$3xds_bIt6Q|+ z#ViVAm*)n*tjmjH@fEoz%T1e`oSjxJ>=&9iH;jC*wn!iH7YH&_U!Hk|@B*D;!*L?y zU=zv#Zw)LJu91Qz^?huWJWZz0^buDq2Y{V+)Vc&YoCW&J4RDVdkJbR)d8FDwYAnJ5 z$81Nd*9xVf%qd`66>Z$MP_$PC~TPof@9&yDL zQkc>J3N6PBsr=_=?J>>y@bfC0_D2@P8s1y%;-~b#}%DihVy(0astD9oYCh9Tx z*j%*(Y4)dN@@&-MLx_#9&g*bK%EP{kjtg~`DsF3{G{!cA zMXu|c*+UAMd($$M6;#yQh9%I&WyU_NvQ`nnpEMT@eaJ*5tC{+W+G6AQx>!?g=(jGj zBOaBAvrhWhpIv;?=pNNA5}4!5?Xdy}jYxv(pZXc14$&Qv|QcGHIROavUFJxX|~imtn?*rG75s-*t(X zmR>!CO8UpjrHs>XPXRo zOBe9NtZEm8>~jAWeH(IfY<_tSTqQHAwaY4Z~nx*IC*ux|K{?S`=61a6rQnyg-$nIO-J^P zt689dDJcNswZX)(?EqyR1#G0~RXGqqrWn|*K1@EEeP=fKx@{HJ^2NvqeXyRdv^@Q= z{*S+DCR7bs0k~D;WuZ*>oq`b55Hu9dMAaRzeJOQ)PZxk9_F}RQ9a~?xeMkZtzBXQL z^g^dl!(>|!*mxT+G8)DneA&lz1$CEG*zqH2!cK|rH2pe$EQHj`>HL9HT>eUIkBC$D zu`-Q}iHZO4QTGspTzYGt&QE`&Z;vVZivQ`y^*Pzdr8K9H{25-fDe+@rN9nb${t1`>PTKuH;Wcq z*u#;PJx9h(^~`dJVvvfi3Pd4}E!GBTQr4S+apJc6=K)Od08F> zRF)dli^Z%*FsPq|_sK!8CGN5WSQL0z{!oL37njE(U4k9fJj|tG86p_@K{&?C&*n{c zj6j-V&v+Nl)MeK6Zla_&8i~fS5{!pZ%MeV$%dpduv7lpu3YzB`yG~O2H*nt43jQ^J zU}EayQj%DLn-N$8_54nk>zi zHqj^8lLs=TOuq=JKh2cP*c{IO`mjS)ee`Cs|ewaGp(Jdzc)jXk&Us!c{aB_Fa+>j4bdklFgG?+i2~7LBUO5tylG5lXGTfO_AqR^-=ZIpF z4o2Y!CM4`Y!OQkcmkKbMZq9kJ0_63h_82tYc`A2A2V898*Ou7(LZ1NgvfEH~|11lM zSy!;mrc-1+7Z3KnN>#7Vs8wNAqz}_S;>*+{4tZK}ZeRQ$Y||i5h4xzP!=Sq?kWN0o zJU9Afo&9SH)+*%yV%5vr<3E1*VVc;k4`xtl;50t0Du4`7&pf?$mLXDVoEb5!ruuai z#@@bT<1w1fq1l}_ypdV=Sh+80=*H5Ud3I5)?CqGM2=zx)e3oR{_2q)h=h47SQW2{I zjIifk&U(>2LN$C&<`>oc^>Z|V!@_57ZMA3U^0?c;V6*c<)HI#`oss-BDjWu6;W|?K zc3WzaU4lkZ>6_SpQEi~l?iptQkn)? zx&iMtq{_7G1=#3A)+Yyxhm&rv-oEmFfxyTbKoNF^g*0h3NPZ(5+NuVDoH~ZSUxU@x!YC?sQ)hn(T6*GnJ z&HHUR1BGoQo@I&}gC)f%UK;sR|BIy*5K&0EIPBKujdI`q%Q;qGh&$_<(F4lS7$*kV zU+rZTJ(PN`J|Y?fv2Et|22%MfnONf=HmBe5@cyY%#6kGK9^SJMj=N*?n>^WCCED-J=YdDV=YRb{Ou-w%TX|D~?F^4o!2y>*`%s0b? zGtrF3`1|HQ3puP$_)uCVa~HvzUWp+Gd(Q*X*vtQ91Vtrx7GDcW-lG9ez5sH59gS2p z4jES;FKdn1qE!@v{tH!4Fufq~TpvAn=38?I*f+OU11YrE-)~}}GgyCG>E#T+X;~&P zM9$aB2!Hx-1|})kR$5-(!zha2Wyk~BVMbg}TkN3+qgW9+CToq4JuLQRrVS#i;2f{^ zezjO=0raagiB)^q_c>V8wg^Zzw*7QityCKK0qliT;C`93JaFbl)iu{HTYQ$I5d9H| zvdjLB_>yAU`Kkhb!tcBEB;e&<_qV!L)jqClHD0fQgA0}iShx7Y{Bi#TF8{ywzVa{X z?F)Bk1ZfFTLM%W+B?W;2L69!#7HK4uZcr%+rI9WP>244dq$C|0q`N!sn)CbIzvABW z<{Ui?Gqb-t)_!V{S(y)4A+KQH^IO$hJHZ83GO~ zxO?2wAaD-`7G#*I!$V|g-#d5^oKS2o_2J>9noflT#*_w{YY$>Yz57XDPSb*zg1=`P z+bYKGU~T!WO2JUmrwofBi=8|QA30~BE9Tj#Yl{q;#ms-wv!(Rie4BPg=Sqb48yT1Q zntbdva-5Op>LI1zX9sj)_fJvQ)6>|0d{>>TbyS7qy;3TS`Oo z!7wd8ainbXj{~6ozI z2q0i8ysTQ*MrYg173YQ`U!|@oOyR}XzZ3{V*Su`{4QD<$XX#z18`ko+nmh{x8(2WF=$q75>op0@g`of zQ{?aIUxr^``))ULWb}32D=K<87D&>C^W$M5EOpI;c;;H~KaCcq5^QVdn#}2KSD28L zONTcE9ml;INSgbyDc1RzmW?%$|NiZ8 zXuV zYIjH;{?e$hs*V-*sL9+kkBn}XlXkdAp%M;M^UUt%tc|Z|KrYqy_B*2P<09{`o!{dZ z0g6${)zkg;WZiMUcN0q_r@nlTwbGOFN%d*Rz{4c~E&+pi-2YACK5$Ydnp-PqjWxz+ zB(+smQ8@zR2CqAtNUvk@_g!4~>0*udP2K~MweAEVQCp8Bqi=_^DPw&ALZov!+Yx*7 z?x5`}gf`=6HqFO<066ATbTiwVR(k=1x zdJ9tipdi|{-OXoKk`hG9@yq(fMnAo%cG@eNjLrh@CnI<+?SS zm>BKIf%{An#*JAd4vO2@A)mEWoaHqbDCa+MrQwbdlJ4;`?(cUzC`6aQqPa97x{4id zQZZz-@rg{h6R_Mj4Mof)(eko5VUn`%cv%>?bvOQSYdvT_i$q#+xBf8eihb0NH^tEu zh({6o*{*~DJ5SLKJ{QjXX;>F#TE_)sImMFjd*STm3tJW zW4+s92hdahl5#_Sexqyp;Q_9&{x|0rC5&FkWIX9OICiq;`PB+^SR^6~nT9GA z$!3-&>qRot$AdYkNMVVnPLj-W#yU0tE;CR|cE5cTt$NmaKgP3)v32NVMA3L3EzP!n zXbpZvb{8Sl@1Q%74$^;6C^Od#-{2~Pa2M}qB|hd#%)tLheb1kr(5 zWOQ`aBM9EwE$~Nn+%mPjUqWcwlRycOGA73g&VyYzsfSH!o{T$9zX>q(P*VmRX=E(T z(w4qtqOY&v>oo%m!eH|#FKX--C??ljNsJxX2epoc&NcCv)t|peO7tlfooeu~5@EZ( z*#~Ad+=N+5%mLd^&$c>P6(5TjwMs2tliV|~#K63v8kJ*iBRb1JxP7vJ19JmQ?)`Uv z&$Z$<+0BpG`+v~V&K`lr%Zu9OiQ;Q}E-6!3gb!=I1D>7;D;AJT0j(hSZj+wF)Lj?(iN!UV^pIO|R*zf?d1jdO2W*};BbGl*sOP(V#&5rpw0eN-?ZvqvSc{O6 z7bll8@NFQ;>#w@NoO0uCOpRd<_a5j0>2JnF_5>P)9j<#~dm?OG;D&~-qF7(Ms$XEp z6=gq@%;;lPrL$m#$vvXw3eX{}aH)9>4CGtH}``ORFINTm!n<;GsM$%MR{i zPUb_dE7AqMX9xQz{jb85(LN<%pwtO=nlv~1y0CcaGy5B!cV^D}h!?;cE0tUD^c5Lm zX?GWjj<8DKP@FNiyF_^Nv2oFX#M2W$a0@J>whbP=zVBm39Zpv|P*0_q3)P-Qv30ZU`l_`&Fcyu1blV?I56|NUnYna01 zonpws(zY2G*5B2Xa3y=zNT82qsFVp4W}#-25mXn%NGFbzOwAdVHZTCeg`qi7)qO@r zoKAx-#~n)9w&z7HZ+NG&d?uFBjNj%j5rgwG=cnd-5#-tlI}ackJp<|aJ}ud5@-PK1Dvx;>E~>y7jHW5h8*2~W}Z z2M^|BzS!#Nu%c1|Z27G?v5}}ZKC7J6oO;*D$Uc`$b^K1jX1E)KLvT%T=LBw`#KUpS z@~u>u*bxQ}eB{DchgrqkZCzcaRchX`pcT67V?Sq{hKmf1U{Yr(_`FW}j!l*av=tmg z&Z68mFi5`jsQENmLb*x#A=L0|q8cffPqXv65Z!aXDdal1S8#;G)?)aFxbhKY(=w^1tP#T}!ti@?@c|3n z>xPwtQ&!G{vuRS83>5VY=wJYVtn#ZI*W;I4DzU|L!PIq|T3w!nJ&w;N2`wXmCrNvC zbQR3sFo_|K=$M42otBbkSouLG_7(B~lkWJAV~C8o``BJ5fK5_D;+Ti>`e%m;-e!5k zyvs9xVy+sJBK@}0PI)Y)dYqY8L%D}?n;-wobwtSksPIA)=c?~-=j7B)zhT03%+|ym z+1TDH;xAoa`SkzJMKpm!|LIOD1^<#kgJeno34cUW#KeoYxYNI|wXN^_2rQw&de}_a z@lr>Ks@nHfhQ^dBKEO>%`jDHARE}T_?O$;!+>Dd%qWWQpl>O|5<^Mv(2hp_yuvm51 zxWEXp3y4dNfWgjkYB3GpMvb1UTN*cFiwC>_1=p-om>M90%gPJb27-k$YliKtt{-F(l~o{7Z`*en{{v#4 zjGyHcqFdEKI7Z8JH6{a8+UX+rO(B`rqiXIJ4H;uqTv}f{hhIrglF);b{kIEvan1^8 zHW7>`W!5Bo+I5Wy9Kr^2nxLvts&%y1em*lhTYsn)kS^&3tA!r4iiG{Rdyw;0v@Ui< zUY+!vS|Evd8sNqcZl`5osRVQ>B=G+(L^ zv5)-zwUe3h*^>QnnU7L0i#ktry!l!kbic-sjKXwV&GxoEQ^3d6D}5UVv5X0=7Jt73 zQZj=*&;+%$`N(SX5FsJ1pax%h9Q`3S|IjgkuO)DqStNJ$6o2^bJn7=chz(BH@-|r6 zi|28bN!*STi>Qw1%s0Z~yZ_)c|D9rn6d9_%sIn|w?TRc>Z>P*!m?MTSJ~b7WBgTFN zI$#H~h-jM`x#)Bn+%@+$MVk6%u=ohYGa!f2YD}u`e$&oyPd#7Jdrwds8h^a9zwC$; z{C2NbHd%P$3#!E}_j$-l8W8qOpjyl#QNZk+K+7QtQ2;pl_2U;(%6{cN7jgUzf~LrR z>mNSEasxGMMsS+EM9XfCyJD4&E4D^@mHq~oAn%7o3~QF*2~Py49H^nlB_G( z9eK+x{iXMGHy)=`t@qNOY^8L$P24{Gw1+M`*?EE?LMRLy?Prw1luHulvs@y zS$5lT)9(zuX~AZAAH^j+ZS?`S56Z+i;qPAPFvr-3hH3hRXyJ)A-N1S4up$ZNCTIb@ zJfk`Fg)_%~2|2ZeCU%68S%!cMe`M}Ema1YChZc`nEH<>+^77o62;aY#V|L6mR=Abj?9*lIqGr=D_`NFnF7+lBhmzwzxKr30Zji*j z^i`Iq-B~Sc?D(QM*e-$})#DAKIWk}yRbAbe=yE~*3L=T5=!+W~hlRSe@<9JT=&0O3 z-E8d4dh1l3kl0-9-|YeNq)5{by)Ew_i{01C!xJ3E#*Zx0l`bsWS{^BldH0#I87qq{ z{qh-4ES>jqgFM!2WOmd?nNJpcH^q0}@e86avpv~GH<-;^df96u>3-tS>fOrDXSHsc zAtgF+?D*b%DE^ z^7!$8>8B&SMt+A^KN0j&e`^W4>7fp!exJS7g(Aq4$jJJ1Wg4de@y^iYb8}7%q{8rB zPJ?SJkH`1Rht{KI-tl5`PiH?+?{t3sZeh~3Wn)otWqR1J|1;7>^ZEOyx!}DOhBR;)w)cFrPz|?iN=}YaArh02*kiIqduc&?ht!2J`t5a(l+& zUjDBIpy+1&ND@^1gK$Nm?8eY)OCu$|i!YT;<(qwlp3CGDn|2Xa5#nd>^Pz(XHQz2g zSpmqtnmM!thn_4i)|lPQ9zp=R)@XrD{K<7zvIPbfXdUlfQ+nIp(lugV&sy!v7tP~?rAiz~ z&^O)D1Do$a8%uK?$$T>aZbsR(QS>fiY`O&q-S-JNhOd9-N`x;*6V^1*IfteT8nDHc&M~;` zNRNkJudlP59&S3ZN1k>*5#RP%eHBPAAq0qaGu!)WzEU4Lv7 zkVMNfIQE)^f!?DRJu?xS;05# z#|M42$;bdbtov1ZhNK{-rYqlTsk)9f=+?W2&_FoWj&*7qVI0*!hC;G@8TjW_ziTvC zcwmss&W7=ID2qiJ97}_$<@Lc>&xRf#s@Gue-d^Q-n9~5Nsw|Ru{pn5rTc6DY4zc$< zAu90i&N-6G`ri+U=z4nbr}1AOU47{vCuJ3WH+Vh%c;Rb#WU%~Rk@e)7zIh4(qsAk3 zxcB0Ye)=%J>tZV}WstHr;1}rzms?qebnMShYlr+OJkX5z@!p$S)RIw_BwBEB{e6KM zJFUJy(GAv4%HBJpQPnxzD zEw>jOcK`wc5ndPjmbWm&aEf(pV+5PIn{G_s%*0H1b(MaP8k-B2C<~OSnYzv?<_yXH z!$Od6KuHdiZ$$|f2D=w~>Pzn?N=!llBJSR|SYIdB$DCq?-HmQ_sNDjwU}?ze5Lzy8 ze(fVa$@oK6-$@d>i-QJlGfFBN(C|i4d~@(_zt7|p`(dU>;NyGlFBEAneKAb$xz#Z~ z1#e2>`crM9tOsyjH=AzzJRxWP-8(Nn_W)`I5XxP6yB-3AF?z4|L;oMp_q*tBykB^` z=cPeJ6%u=6mQzELvD4THdB3B=P`eJqB3>R0nR%?bXXA0{tEfUtkp+LBLqTa4rJ=OE z5rz~i>g#(@iGZHF)hH4_9Gxcd{=eKQSL5YUUuR04;kpImYNUz@*n+_i|u&`1UwvTaNO32>GbT&$kbm<0PvGcv`nZBLywvu@G*bbbwbTwmqA{?PT! z+MU(_2WB!xs8x$UtWu`o)37=0WqVC-w2l}MJSai1J^|JDa?2U@(OK#vs*p^9udkHe zhW@!}b^Db{su<4vUE8C&7CMRhOEyS$Zk?pHhOJPzu%xA@d(`wTLYdpc-KV6t$mtx$ zxNGMnKBnC}U{#0c%p2P{Xc5rW^UUSyT8Un z zTD%6Z5Syvd5ut0Gp2yHh(iIziuZudJjN{qx_b-OpCpC#ma3_fi-oNCLK6=N?J4J%Y z%=~H$ptEPm13)EYUVqK42}D%K@Dl{7hO_=PHVs8Lu!Hx3h5Y9+AES?7W^xAP8?}Gr z9bio3b6n#eyLteagpXkAsm zHCi?;zw`ICV2&T?%3OHflN2bx=Iq2SulKlqRnO-Oab&FFQi@2*o%uwk$w#hi{J32l z+bH2GFf2;b){@XaW%fL3<`N|w@C^vq_=O^Z2t%^e)Kq(;(-!X#!49IAK8MT;+OhG+ z7=ENx+HsFb#3)5U7-2l{v3bfV5h29$l;%h%@7`O7e(C+7kXb*thj6c{}0w{?~YA-U2AWFK#C`&f!eNd>IZ zs*P5?VDMEXTRaEJ1Sj0xGIN!cG zyUIU86hlUT#{m{fCBS%MT4(~|Bhs6rfHZnBOHS^t!GyH+6FZJFFCrCHp}$oOnflfr z#ncZllDWiZ40jBE(ETD}a-g^;OA4@P$YFKvIxEKGhqiz`%YJ~2TpvqO9i=?KSb5S6 z;Pj@Rd4+ypN~nKmS7ZE}TpF9^su)P#?t}B5QP1P0+$+v_7f{xi{kBXMZ+l<HQOL8u~res8?pz?{Trw8O!&86lkWPRZ^|IY~_9y zsp(GJ^p?CPT;?`mt@8D321Tix5O)MNarC(E4Up!&6UA2K3#`!?_9iF)TI=L-BX@x% zVCz!f%?Y#cRpO=B8O83iHf6I|X4Te=NM3E`p~(KU*P}UsiV<`COsB;Rcx}o|ZYA79 zW$olV@y2;lzcRv~8?t_ml@7dg(dRl*iFT_lSastpT%7&)NG|cTrr^}R$D<*6^;9!5 znoPA8x$X?UmD-G^Pko!-W6P- zhkfNS`bjSB6C~xM-yv_ybK1@i_2Wr4PGwCL=#9p;i+IiL9T?v-t5Rnil%3)k{(45| zb1k-}7kJbvK_@yX!Ed5GxxJy$j-|wB?!8zP?2awYG-OwZLe`=7Qw^c!&VH1QCnxQr ziYj`z)ck{pk9&V5R)@E**OgsRa11Urn`^YwdgB-Y!m3b3%%6B@$oHgF1@DB%Griyn z^ry03VV-qDq$TG8;NrqVUy$6IR~lmfC#r{>h5e~7$0t;QX&n}0ltAvZJVl+K2L658 zOno}%Ki8fnd%99?(q~WJ4XF5zr`!>>a5LL+Wv$c_o0rD}96oxM3(h%P7Y(NygnLOh zg9xhMzQsG8)DhLK^G&27NT4{~Bg(yBB@r0{6)9BfH3cjxOq*iV zgykJ?`qDn|A^Y}C6X*?yZt_1&+tbZxsKO+bYg4@_kfC)H$DjzE6S+L*-FiEiuiXYu zg>rZG<@6X_p)JRcq&Z{l&V!9ah6u8yRF>KLa@E+YqN7f&$EdVjLmXow2MX_BE=$!4 z8EO|9_@Jz%%mqdrEXEE*Ii>c$Ix^M1TVCl5oqHXlOKYL6oH?8Qw+PAJ$6mhX3B`Vwxf>Z=8HS~1l!8ZCCV~`@(*c8*U>Dh`chs2cObd*+T^)k2!luuB+gLm zKKelu;C!~-H)O#)Z8o}xTe#8Wz$zvXC*tLK@xwJO<}{z1j`B7hnR`3L2Z!?ixurb% z&j!Fvv)XWi*g^51g^6GF`%NQPxcUPftwBXbzDwc6KI6wGtY0)8f(!*&d-qw&g8|Kn zejio8A-Jq;Vqn{*#A1qkObL;uw+gvhniot} zFT{j>)LG;1VZ!Omy6}p5pY;`QkAnq?kq>T4%R+2{YWB1{?f0yFG}a|wi1FL-aAVpDDPBvX zAjC6bnUig(17Xe;ufn>EAOgb8rHZw^K&M*zB6*;W_)dZ4H_sQ#48Z;FkE;9wJdKvmJmiIRJv38#e7p} zGl8x-ajb*6`f%%wK^pCIIrXW!k;W&y{%OaezjrjRk$B){U!Y?=8g4=WLj;y3GKE9Y zbC4zHLJ`9%qqf;lku|j@1VfVC0g-mUGDe@it94Y$ObKF!NVTeN83{VN)15qNp_O0q z2l4_Q^hB7z&{JAzAN+`<0)I`mo18;;mrG@Rv~rcs74;?+(IK&37f#ZbePV+6Cwc=# zq7Ih3eme_1dt7F4NiCD4U%uu{l-^G=G|v{5lV1SfkT11d@I*R`I!9HgVX_C6zCYJ_ zVy^Z~lsd0`z?;AwP|GghF{HbXc!;e83m}yAtir9&LZ3f5c)QrJvUVmV3~4!~-HAbi zR7(5wo;DGdN;H3orAqp?>Ol|Qr&UhSNb$1wnufX4NmHn;g&ovOriJpX_|WoTR~heo zrwNM$+cWv%1Vz2$m!;>EELpZ2*`X>j04PoN4R7%@ooWiK+6`x1<4GrdnZk6CQ7{)mc+S%i-yukTea6e+f6oaX%sge8-lpBU}m zy)<}%uzxr~!QQpma7zC`YfzWKQZZ6K!!-fRkAx@}4C4w0&HlJmLI=aM4Ri`}1l&kY z<`a6w+*caS{vVeT-^zC@_E7SAG??ji=sNKb-Z=`N4JG6VQQ`6H>wS|m>Tek%SsNHg z?!IIgVNp2v{=+m@Uw{SP+!q;+ZQ))WCHY%9>H&Wb*7e;So>?S$UsBbx@_7M}?UVS7 zFu&gI3i3eZbi}ab;}}R*SI;lS*F336x;4zEgm)L8BhqMt*4Fg&ZrLc}lF+ZobWWUe zbKT0`d%+%yN8ELM?8bQYBvCg<`DbqrHI+xhr|Vq5D&xyrez)UuNGNj+qGfwfivLt< zRP&>=soQ?enWB)PMW3n7>Vf)0CzTPFjTsKk$BvN?7X43LJ_JNju`JVjXZO0#w7!_+ z+(>bH|LzPjh&c@HBXm#3rY;tQZauY4{mfdEW zPmF_FdzM~*{I9F6D}c^`X5E3@q*s4V~h^3VL);bb1es()b=J_4bv#mf@^L1iWl* z#3`(rA-FGc?W9?CtGVoL>ud{&$Q~6YhYG%K->0h%p@cOTd2o>wBa6SY;P;edT7X{apg#lG4)pAG;|_r_wpHp1CUDDs-Ly;WX&yQCUFj#twbj zhkOX7aO{7Pv%ULm6my82U9axW;O@rA?kna+C9SAY|N85wU!p@K+@q&YwPbn{97?_*TH_9mrV7KPA5rH-h6>(D_H zE=`8)>}gfPaIjpviYPQ@uyoP7QeR_t1vBTr&a?Me=KN_>B*WL3bA*cWru3zERiqV4 zR7eZG2PAS8V!1NN6SdYLn{WKLJiW4tI7T~^tBZF`H6==_tE*F!sdFS7>&gsR)j1wz zwc^UDq(VJUy7X>7T@%tu)!E{gma#oY%FIh+7AipFmF|fyKXvur3`R2b1H97Wc(eau zdrIw{+>hn}&o$7i?6a0zq7L?BU8lFVTGs2MI}4T;IpS30hxo;pgTcyWe})(QIhjl1 z%LqX28|!n&Jk@mJFf`T*{_Bmp9I+W!E}8LP?EC1Tb07}iX({CBUY011ehs>$Fc-5? zREVr92Fh?AW4@oEwgX-h_u6OF{?~niD$bHzWDSX zMec9|OVi>RqE&BVQbDpOp!#mS+){liI7~rc`HsHIuQCJAt>%g=#kLdmr*5bJ{23y0 zDH0uX03ci-vXI4wKwarP-Epj(P(b;GCtL6s@g<3nJ<#`{_cVYLRKCGg7$U$Cw2mn& zL{Vj*nx_?b8d{=m2c-HID>tWkMwcVycq~NnQf7bOPc8%7mE^hW5DxP<0j1!*{W+Zv z3t;B0jCw%Qh%g^6O5NX_;@nzQBE2Rq@bAfD!mPI28#!OKZb>F=hMn0kw;hqq2Du=F zcr6czsLCP3z$NEvpxD&glP5y^gDSfE(q@B1J4qM@^b3gGfW#_NM6Aj0%vJrH2lFhwqV1&27|* zzv)kp{{z75dK|Tq0Zg^AS(wf*hNqwLz8POy_szguPm+T?tAg5%lPce^b0}b6F?hz( zEZe8y2zN) zv4i}>$`HDXlDhuHom+lk=Ve?G#8e#aop0**d3{OVF9ZlO#y4CyK{3w%k&oLcTXplj zmc<l*fobWjQPGk=_I#q@QZvojH5m z$nwNr;GNz*FHm1seLU#Wa5xzhIrj7Xu8^(4FxL;qRzwC^hEnC$hSZAlTyUf~!9m=q ze-yI&QRFURcZ^1rZE6VZ{(IC6S6uepBG2Xt(6bhB-nC$*LKXNsKJ{I~OpmV6dY|*R z2Zud{N7r?{YMYFGkEi+xr;Qo2xlowUK@}=Uh*_F0c##V!coqB}vhWxNooCa6ISAGd zkNUEo#d;=j%P?u0{4?{H5wwH;h!v|c+lj(ckq$cxUu|j{u4Sa&_B?@A>^xyvMw!Qs zWHi%yxb)kiL@~5%;a{2csbW74!>KuAn%2%eLLm8xKh!Em_eCO@$|ad0 za5{uX&&};(DUA>69fs<{+@w^Q zI4n_f2V;J82~;FRGs@i^GMx314}$|Va!e!?g7HXt~cXs1lRnuk&ecqfZ1-JrF?T~rJ?pTqhMfp^R#?*DX}A!;Yd z|Aa&(Zd740mVhQ@wVxlV~nQ9I2vQ_eb8ia^$Yo|#U$>~GU zsZ*#Ob{vsEQruF0x^U-cxZ00{ElsiD4~cYR&02}fGm%2fqh>#U=P8@7e3HB=TuSEt zMaI9C9l_9B-4I!2MlDUzy}wIR`~wIpE#y1_{bNk%J3IPB72dshKPcq}Ov z0nZZ`IH3-9I=NoOvwyx?R+_?F5hgr(_maBiG?7#Y(MK@~#^OA_!yk9c56(|k=^Up# z*gb>_d~ak%m~WE>Yrm=fxzQ++;MmM%@|3~?RR+o8b9f0V-+`Ma^Qdo-+^hd88)=kI zr;1Z0db;^E?C#{B2!_NN^56OwJJhx7724=}0lhG2@lTIt)5(QjlP=E}2{O7q2I1NO z(yi_Ri4w!Y?<76nxlEjFs;AOzil%JT6gESwD&}gryNU&NCGRSOqLMyYRH5QblcFv= z>#8Cwdl^O9yUI@m%=_owUpb1*Li@>UAt+#$HT>`4AjD*3p$|Cd@Itdo{1&o7*#v9V znd!O)4P`|&hW9ZbsiFwrSWsGqm2rK;dkvgyn8hM9S$2;^@>`&Gea;v7njJU>Y~?&Y z!bSepT`t;&^8@Y9c4mvkByFx+PPQcQgW$3}@GKa-iY;}gEt13I$E^o>9MB}O2@i86 z&{vt>TRcU#F`8Z5*~ckWtXZDqZx>?z;?LK^Ty)8_9Q63ycHFLQ1n%Q+oTet8MjC$8 zLS_?{S}^RHLKB7pn`XltoD&C>t|{MmFZaxg3F)D+OQFnv9@{;&$Lls;mg&!hHi&Ls zji>s}8t_u?;{(Vmt~lMWd_9zx{O|m16(f#bmKmvp%2L;J`8iU4occ2Fw9ah}HKPf| z(yO6@aQc}$J5QM!mweWyoBhzDRXC%v_cZxz4MNqiuQlM?fnRz$=v5jjLNk}8a{&K>Ps!^+JjiKxC;`G7p z6D?<5ik%cV?ted!b`U-D$oE ztGiqj=0#Dt&1DgE0b`4N%R*V;aoQEBId>n+K_^fDGVN^opzG|zUUO}|$oXCb%Etya zk>h0j)w)C?2XE+I#HrDHp#a$v`3lLCJ|wfBqT{2l0-h>kheJMLh(&6BN0DS;p94v z)=ktF0{yu!;a=$o{*CVzLj$wISps1!ic?U-p*A!y{IymwbC}XRV+h1luZ@CZsY>e) zD9PC_V|q+bo7WLrA~Cv-IqJ^zRNW!Y0LkdW?^KumsVx1k&SkfbLldPl&b0rLBWx82)1W7!i*;5@N_4HJrsgCuK7z4cLU%CrJ_sT9 zOWZcC$zJ|3r!2EfAwx9PgKYN$m3x2yE}1(5ac3bHcIp^ye`3w(uU~KUAw`M!l|?BL zP5G1crTLPu5kw39rKpL6D24-y3`jrsy_ao5`7zeDrJFJsd7gp>5UQ>fQ9ejhEgnS(^2y8?^;f4-gsU&~{7< zHXt#fMNsK1&tW0>r3NLIB-71PU~?+fwy9rVyt1-#Vmlzm=XU-b1MvneVS^2ZcJz4g zc^M=I>bWT)5C^+Lh>=3j4mlo-@O%dgsvg4{pccRO-Eh3ihQJDAIkeKy+w(2HQRHHq z%EtdD!W&D1JK!M|q$X6ONfy*538G&Q4yy03JE>BW-U8`>&4BQJwv&mAjR=pGhnp5U zxSEogbh7On-agim7{SkmNs5qCf>^0EG#m|~3)fd%Ah*mKExTT=Btb|iVlyJb)9l~k zX@aa0z9QU6KtEEc)98ReV%|nzcwfsf^c%`kC)rPckkjJ2x~C``Iz;$1J`%zBv&`nw zcBusy@Io|}um-1Y<$u4_7X3@7!4^Tajbh!ZTCW%rYy1V-eZ%k|pNViH7>}|4exyc_ zCc=-5YMLg#{+6uw6DY>bZWUJDnld`4al3{098aWB8rO0EmjWqSmo( z;CVAXyz)2S^sWp&!?vZ!@f?MAt>Z-DMg8bHF-`9jt7APnKR_HPi#9VYZkAeg)Z z3J-gmwr4o=#lsLsMMM{G`UmdMw=QdgdTeUf)$VWFY>cbFsK-RK&c*g;Dhw~4Fd-OU zG7m{x+fo8ZA2?LI*CffaOUIe-s_Zc#~m%oA@r3Go*90qi6`SVbjIVD|0W0)HHGAq`g6GLHuf^c3BbY@5Tna%Vdq^;Yfe4_) zz(=$qf6fEcTU>78kj#gCs7FY}Ry0|E>MYv+4f8^>!~$BK$2&)a?k$!zHZidIl;n?v{qA#hIND*IZb}DOS$Qaf!M-=?{%|T zf?C&@L}>6Yh<0Z>w+AJppW)n>jV0|vRazc~PuR7s!@dkaCrtQTJw32uh0yOs6aUx~ zrR#L^*Un-ft6ML>ZR+BnGN9oC?(I7@menP0ha}MvTxmkkv_kd77bYfdriTVVJn@?KGHOF&aH%B%k#P?OcQ}4DV=vpLf@MGWfS=OZhXW?cu$40=$^dyDBy&q3o0@b z9J=)7pffpfl6l0v|;ZCQSUg^0VWXJelGNHIvm(Xpa*7Ym`xfPwE_1|}hP zo94~Mf;NbuGJ|TV5_UeOTofgT&amrYPX#TH1%Lg0`1?}I2a|7Ii4fj{&k>l6>t?ym zu=MlI2UhbTdAEV?5W1vSNHVM&!Il?zQV#XtTY7g0J(z-ndt;9lfyfC%U?a8q7@Hv! z{aAPyU925U`&onj!CI-Y0%V?!`$Ou2^_9Ai1PZ;9dKkb%8%b z1+5Pl?3PmDmi!t4#-xn_HI{KxCSBdyApMD9wm zfPBN@0Q| z!m3un5XkIHg7Bt*xvu<6j&H(PQ#Bv~JDL(7@0dd`1Vr6#SiM-S+NQAYIC9%_0>Yyq$}bP!!yyg0J0X~zX=L# zqCgnfspq~8pa6WtSMZKs;sH6n5pBAd=#;eCrWUM4`4zU(U3gi>*> z2)2UShN}oO2yT_B#pt{^ZAujBe%nzlB>smu@DCOll>*O1oDVHwUIDcma;gD;Q;seIey#&n%3wVvJU3K|K!lsY%DTfw8An3XD-u3E z3*iH0&>!pERD}YYHQu|2UT?$k2fA0|pUtdgl>vIg>AV=Mn7z{b=KZOHB zpftXDSj=r)1Yjx0o4!KkMD+Rryvzy}gNbM|M2`c1?l)FBjLfj;S2mC(WHHgtS41Fv8TReN)&Y_0fp|-zAGOcVh z3W#*HqDB|yEkaTPzI-ZV8?%JF22txd_u&%JUUS+)cc0-zT0mZJp7!1Ybau=>xGDBu zBM_uyu;{PM)~ptkqhXrES&PMVP@Xp2l)+GD!eL-=-||uagNZ5vP$!LqP z>o@#>Qp{$`<4_m<1Yd&Vhaz|36-)_xoB?FM;(Hgt}?3y1K>W^v~L~(LOTD zsNd;$U`Lk@Xx`s~iD!;okJ_plctlPiW~g2_5l;JB^s;o9gqg_=SD9k2o}+rsws;}8 z(C*krw+mh|(mfs2Vm-!d^YIFLbfaKl;eRl($iBF(mm9J)yiEo>os(=~p+>RM1(V1CD6=Ij=c+!LK;Jb`kGKsKmtTPO$XvFN6GDJNZ`5Ro zl_0g}2~8jrwqSQBgxy_Csd@*vidpDf0A+w$>z!R>c{Q-R03P3a5%nbsK;i!#{8}XUOLWHZqPV^q# z`14WY0Tk1vPzSrJG^Y;+!J6s|G!YFuzDuLbWJG=&4{=*bZ)}Z5k zi|SKoi7Ig}F!U0T!SySY|Lt7>VlHJyU?9Rn(LY=O4G7ihoVR23@~UY-+7q(EBM=kR z4fV_FNj`%y6wQCrB^BH*&kz5b8a=QJ<0sVUQ$pA371TPMfe<%j0fbxV5l=49?`}F{ z(0DnXSCEt#|Ne4z__#IiH3ot)5&cATQpGN*RcHsHcC!Kqnas-retA9w$lFz(?vF*X zC@kVhRR6ctzekUgt#+m7JmnWjOE3_SdF5w)&+C2z<{aI|iDXzN<@0lM!>|+o_o1$! zXZkc`gLGd#Q({oI*GwF0o5c=!H5jbG`uc^(1U&(3}A<0x1{ zV=(R0h~aTdN&W{D3!|tp7=^mx_k&>UInoM;j67$5DXb5_3f6$R_WeJ&{8D{zKG*GV zx)8`AWl=;5ZU7axTgEpCxti>^-DxJv!%&kx4_8?p@L zrhOcQ6axsv8hi7$S8!3UF#73M zV1tD~nESwI7vl$RcNgok$zSLq4{|g`gGD8eHb8!0=2z=Y7sFTI!GAYQ;tpn+o6y22gfJ z4GPK5c7EPVg^$qX5iB8xzM;^sz8Bgn`k~j@stg_i(FltX0mUJAARoq6_zz?UtO58p pDJ}e7_$T$&|NrCvgQF3DiTBdv9pM;?@;7=GypWI=FAy{E{XesFIp+WX literal 40486 zcmdSBgx z?|=CA7;6B>f~zRV1i&~YiDD^>S*L(Vq)uPZs)Xv)Fgs{K!xyJ zQe4gL%jT@>YgLU4gx$?Pbh6e5_h&qJij)c3>!oH46S<6cgpu2S$jmlqSE*0e4^C-U zjbT&c-v3C8T;6$g6@7AaWELCkY5QQ_>t^>^ci+JmCR(N6!mCf+933&qk;QRuf8mJF zA^B0E2T-9~TIu_v{O_B@ET#W_D*z!7h46oWQNOeq{to;?#3I!E?_Y}hwIE{t?|U4Y z`v3cfcTh1|ZvRpMRrCK(e;BRzJ%rmEzzU0qh$t)LjOnI|?!w1NY|$Sucj8Kv&m9gA z4Ghi4NJ5z&Tc*2jf_{~ptb;=-OAMv$R_fvt^=k%57Mg@u8ssVRK5wf$|( zMS>MvRD>PYPK_(lG@Yql(A(2vJ5&2ov-V}a+PcZ^NB{pl?2$&N^^ttNCLbg;oVA&{ zil88rMEQ=zJ=PCmRJdPKZeK-3HqLc+oqCp)X#+qPzAGSqk6 z(8xK`nxdm$dV33>D=U*B{kJrE5t)PL1?oj#ggyCUx{)bnW@g9c$uJagyledFiXWR?}gSi!Nev4Mes zVPRpRp_~!YB_$=k7sp$(4X*A&UmIo6#OIH;XRXfmm)k<_byB;%eaji&+fL0jG6h$- zHT+pzjVV?!mpf6OhK9z`(UC9N#?Y|Un2Qk~BSIQ310N$+E?YUDhbb1Wrpp*EDo2@t z_Ccsz_Mo{Mb@XX!0A`fkiU$g^IFECzc9A+$Y?6bVs&n_ULy*Ma!0n4Fwr9y9QJyYF zmR2IYv{+G7Lqp@u?ThU}sD2p=ay8=)S;11!Mr1y4a7*!bXiBUqddB4}y1vPde@cN5Uee5;{udr% zy7Kh_TC7~=OL*t7b}mj%ld^=QZ|^0}^!l>g<8n-g(gw}XuTw7&qh+(y3rx5Yl^O8S z*O3t$#gsKP=<|w;i}Ujr4p2ysj*cAaUe5*cIw2#rOig)oeS9>W>seP<$9u+peKO~3 zH&go$zKr+nQlSfCq0&5hWU#;Vd?NdFuak0kXee8S(S43khZIIP`pa^k<&^t2#9 z|HR~EQc^jbi3EAN6vgoo9ZBk!b8RC?iSloBb&oF34$$sVe0SR`&&bHg$w5_gx=L0 zXT>a89)ubj|12*pEv;DO7Z8A_G&P~=$bVd2%|}N^x3>6<;Su^itc0Me?alFYm0ADS zsxn@@wqWd(CwAA({z#=0^i}rh{W0`Pej!0r^DL~acn|)qVluTQ5ZCx^^=_-RZ|agp{;POi;*3u(m4y#CJ0%AX&e zC$_WoF55G8PbrrR3JQ|zM53W?@*O@E5O7)>XqlazZEtVy=m>7nPoogbQibi=+S=OI zX0$o+Hi}ZT-sxX1Y}e}gseM&QVIW zwX!Ox$Wlrb(XAbjDN^5Hp+V+N4GEDkG(;R@y{fjGEAzf^In_a^lC?@|p~gj5V;cSQ zmD_wEZF|;Ul;7N8M*I(ffzRMDkdu>t`9jW%Sv_SI zpYH4U>V%}Vp=n3$Nz9ZA=%snOBVqvhWCdU*`- zzJz&E?tk;_T17~JuHCYII{6g+g z*7;m{JbMO@;2G>*&y(%t`FVY7Yb*`rDo6ByncBBT2P>?oujD^=FV#7&vb?Sxn3~eo zGvc?Ozqq{g@-_)cW8XhI(ygFF-e5U9LqWqKZx+BDp(EMGB1}=-`SasqccHD`b!YqU zUqeevjBf}@Plp>|!=VREOgonHYdy5g-gUdodzlHPpu+RyE3DUscP4J4JO%8PZ?Bje zoc?9Zt*7?!jT*V2pVyR@a!{rQCFDS3(5bN%bXvpB(Msd{HE&vqjw}J!Pp|le-{a8S z)6=@*nR) zFjQ$V%+VJ>B`Ynx0zHeP53$N7m@Cl4+IprygI!4}s#v!{TT9ErwGj>3-_XP)HYVn3 zF-jEnc|lH&w3$02eh-}9t4np~oj}&XMV=YX zRf_ra=}n_ocHnDR%dp5uuDl^RqbZ(}W0y5tV?SBip|K(zR4igY3&L2rDmaC0AyN8C z*;|~vyv|NeJWrm~l$BN2xX#;eT3cK9{hE-LmWFLe9X&EKqNc7sHsY06SmOwmkTWndBf_2ESy(Xe z6J&*_vA9F2e=5w9RvjUczO=FuPRffh%t9T_@c8i&JpBYyix( zKS^~S9l3S_NRigY?sM^ZPRLzTt{?lbf^o7M#SB4zKiHRftg%JIz1O)2y*4T2irXHxO z4#WB287068*_f=z4GVh#Xf5w03I4-AeJDO~`>V-zjs6!u($yn+mpgv`%qS`2CvS*l z*6?t5ze7SGy}rJlqnI+b9{C_(>H&4Mrluyp^@Or~#qL=^c=#doO2edV)<-ej4K7=o zqXk4g{OAG5$jCE|-e_HUSlBDvn$~=t|Aw+L34hV!qHC@OP!+!A|6(&;y|S|MRitPc zhlZKC00nae3fk;$JjKfDYTG)-5Di@n^wCgf=T{mUHKqz(Z6W%mIn$wj2)>7-vC<~X zo>XtKaD!0@LnTSMjJt-iUtApii_j%RAL0~9X*BIiIzRVd71@a-<+VIoA59T#FyiDW z{VL?{us!4M9ffGw^j^|XU47;KeHxBFs7ETQ!}`vn)N@`3ec#;={N8;lEQD@{@}LL7 z;FUf$DNk2_|GhYM)R*KC32&CqqT zA^!35@)Dp85(yb{)o0UfjE!|UM{T6SV(oWw*{GLbtvv%g~10*t~zB zv%I>BCd7hFLW+kMGctnzAoR5D-fE*uL`8+8y!;^)4o=dxR9}&adgl$O`B^Ie!byfZ z!$|@~R_vOtT$Z|C9=@fL#pEF^N~7`x;F@5XUr>N~FUl{KTHEr^cXvE`MFfJau4o!W ze*`riB;?v=(x(ozg~e&dfnrqef`h5i_ji`%pw+gu(NI$(W~Nk7N9UE=FWwWqq>7b; zospfrob?>x_dP~N#>wyQnCJYsStyA9AHRMLc6M%GcA%ji6Y)OBA7-(M`XOv~wr`S_ zadmYvr&0X+4nZG>KT9c;P&YT?W zNrfg0)!yBPKSs z_ugL=IKdQf_n$t6m*=j@U<6S=eHzriiWF+vB}S+Tca=80(CU&Wygpr%T5}SfDH8>F zM!)9OE^I(X#{4I?GpC2i>gwvz(b1CB_f2*WR{M8m>M%`k(T5Nzq5xGN@9sA9U`BNU z(F+=lB_w2fjlLVc1pu`=#ur8Z7T9f$QFyN9Is>dAetmlcSmPs?=_- zF@o%gx63?Fki_%n&s`ih-f^97jF$`#b1S3zQ*B8~NdX=r7{*^-UQSO>2VmI2^CFqY zpw-RyW=Bj43WoN@85LS#Gj+7Abv2`qF|MT@>mQQ`60tr;Z#7=}#9h)HSsAD<=K@{neNVWO+g*%WbAz z$~3WPlNONF^??j%l)NbzE#-cM94wdp4cNK4`Nv)Y%POe+z$_ExbKsxd@?$lIr6f_H znkxCHr}Q`>&u}HvKNhH2Dv$?BTwC_Oo=W@PQ~D~@-Ph-RxQ2Pr9nYdw?r~)Kd5-`? z3L5*y`0fw1AtX`JCIaR-qoluE(>2%E*8~Kwp>#ZVg1sp`J2-e>mIqnf!SUd$s4ot! zb^(F|_Sl^74QtHvd^Ha2H|b-DxBAYAC2s%~{MWg->-HVEy(}$o&2(ibE%|C0YD{ox zE6EOZ5^V9^%NPpohc``eR@(uLu^5T+#b+xQC$UvkLeLD=3wT4Z(!2SCB(xg6>Pkx3 zT|^Ino_&alx^WV|kO7jQTjzk%ldZuNYYDjQ9)*w?9&$kC;+F6;w9!{iPFRJ-mE4Xi zztW%iSN(!E*70vRS6s@90Cp|AUL!s_az}?fjX?p>_ReJoGE!2WqmOD#Hs-k9#(+8= z0RW+n&H+V0(h!K_EfhKPWsH?Oq8A~2mL$siBpN$iNTPdmlvhLqXXI_}4af(4c7Gh! z2GXOrEmM>D-x^9t2%Wb*aM_$Fvzrt7EDjYbhE5?oDyq}z)pIEnqTjj}Hc-3@G>~+T zsc_ND%gf>7SmEOS+vGaXtI&w?5G7QX%}xDy^kAWbBpwlloq74p`l4?DqZilJO%Y=# z1X(0rE*sI`4~}GE$ds5xP}_oZIPv|54^7O>LS9}bB_%=8NEN` z->})$IU-Qq&srZodweK2{rHDm znt%nT>m1PnTbkLVOiY$P5HLd}EPXK;d_VMO1Q})s4$2t)8I)arfAO@8Dr&!|o&|?G z06y4v?*>obb(Sttrxf-1(!Yv{?ED}U7JhvE2@emC*LUCXfq}Fg&g%O>`}R&wC`G)8 zT^M~X_d36PfvtVoF7uRJQC^)KX{Km#cK0dx1pU+}cPXC4; zi-?E--TL+oBa>4sI3M1)yZd>9y2j(jk3oSetsk2D_No9uU4x%|`}~MZL2rcc&exV9 z=!BSKAl!$FXmR8&+3*gell`#cVWJ&(P% z5OG2(j5={}(6+q0f$Beg5%=9Qq}$1RyjVA$O_$5`SHenRV-qkVF|jn$0=f|jP;a(o z>H^yq^y4$?>pdpRp=>TsWSdW)pX@X_uHyKq(o#ovjk~_Rn90R*Lw#X1U2T&h=xSOq zsflbC0U{pgVco`1OJTnvJ0sp{s;{qyHK)P_xg;(=9{Q4}=SB95_;3p0da0Hl-*Z5g zRAnJ#=HVIXwIV&Y{imm@p%EV&>kVkFL|5O&CI#9~WBuQQGw8*dY8tk-DW(8v-S?MP z*m1~&+;(T`9O2-jdvScc^Vgm~Kc5kvrQM(JckgN;6)+b~PE8>;-8ottTy))O{63%F z*Jg~08PewNuJA%pv4h&7z>n&^8q@N@*{fHhCMI@zKRk4`&x3otb1gPUy6(n9FMCtN zR+4SE)ZN_;cv(u=at-tK>(>qr<+{4MWiMKm8!^$*PY;(?`UlJ_K_hBtXh@gOQe)C6 z+HdZ@Mjo|C6sXw^r@8Cchc$j5=`_|KM=S8}};g|k`eJ!OA|LWhre>XP5UV1&F!pCSgECVirv0-H;`rTKreQ^{6 zIRLP6Qqnzmt0qI2!%O#D?@Il^hwVb1yK=TFI4IcET!Mc1Nf>@>LOi=9!J zn3xsS)g5fTAaF$|CXRMB1mx#i0DC`Qm!pdT8SPF7Q6+riE ziNxSy;2~wDrY0X=UtjLkfSzhUOF#;;fS-m2SK{T~VpB_pwNz z;H%_U!a)ETue^MJwxI_!BDGhqUa2>Fo)klYIIh6^tKHMp#lX#Nbh^8sEn{wOu32t; zR|pd^?Nx#L`PrF4z3$@imLPzLh)oHq2ce*fArEb^KYmQ$7B33u9h+>-_1_SR0&cz< zpGnVW`1yXM1jgoC)GVq-J2vbM8HB|p(`_Jesb=9*$Cc(p1S;T`t*sL96r*&Vp`+a+=Pw0$N%|Wz zVHm-~he3_?61c{oYBv`Y0ILFq==C;LKWxB!9VR(4BbYjZF(o(?dv=pSF%rAlF*`=(d_WU!G6{4@3e7t9B_bSZ# zZ&8tRJ-bT5XcFBbcoR&qAKD*8%c|+I7Zxo8yZPa%p`~---%q5brsieiDI^UP^wZ-o z04oaAcTPjr{`^1-l4z-{c6^H!2E+C9LI904V)jTRWi+iWFwYA+b^yx~j zyYuNltumty^5G_I<{BTWbvCf+);A*-D3EfSV&&+1zG?D#h=&IUlm{Szz5RPoE2a0m zy}jEFyGIK&lJ$(dkCBEwrd5sJz#-rl(X-!Q>W1C|qMg&$6v%V1jUK|QsIai|v|W`c zmY0_o_J6j@b6S-$P109?z*faPY^2ydTky>*+yI%7;M)rLgY1+q+4P70$aY718N}?hn8s27>b#MRx0fpY=SOT}1i)H? zY2>NN-Qqze033h-UKbB+_O0$&78F=9!KVNA4Q!Z&N}mxa|7-xNZ*O0FL6}6p`ubA7 zeEFXk484aX4jBK)XAuC2j*UBJoe0eMazkNN zmgqIbGCP+kCdtyefWoOtkF{e6`qa=+4FSP2Ac*hZGs^dMot>R+Se58v{#nsUxuT58 zSXR~N|CVq{Jph7nt9Gg!sRuqg?f6;rpbo*slChR z7ii6RtWED_X|=Vr>ua6#VXf$5+6_raNRpG2;dd~ZPy<`^Ilx-eWTDHUq;u{ERp-~Q zLco2gKC1soO2C|dc%AL1`hIPMFVHFk1nF?5b>9t`fzVM|c_`xT0T-ZN0E$?J!L#&8 zqK{Re=se}+MG324P=yu;D!h$DnXH=H(o7w~`gb@4K|w)CuQhx0ImU{0!`h49!Irle z{+^}6xZCydjWWY$c$4%QohkG_#^2B~+ZY<}z#&0K1cnGF0&s2SATbtda-V610+2@q zc*%!rv4Bu%#zE{PFx%Dj9)NJZnvs!_ywYP!U1&bZPqLx4x}WX0hY_&@TLV3tQ`h?* zCd)%GEa2JSMMp<)7O4Yj)AQ?>fcrjebHbL~>hF}{Ar;Oonh$LY;9}k5>&Y56%};y34Sjxq2d8z&#*aZ zfI9#kkQ}G;_wO-y!ee7&aHwWxT1Q5HPD~_p8ymXnYczmt`TTh|(9f_BA8h9uX`*HQ za{W-^*g!U7(W!PCE7THm!Sqqn(@XvG1uOoIMUhhKAMlM5zRvo$EwH_={rLIwj9Xn` z=OVx)%q5CtAcIIqfz9erCr_ptT-gZ=V%cBU;*ybph>^t(-fx9zUn_$f{0L3WTOU$- z&-ocQ5hya?B!!0FjgZb%W^i$F!NEDU=1cD5gTfsVp#VE2uq90;-yQ?QN+tggz;4s^ zd9RYFF6#8hdxV+^j!sT2EHm?)n^=5>AmU(SH@NOlOq6bgfXuF6jB6uIXUla+K7|mXz1vW z;o_nLd^|fpFV?~fu)shTS5Z|3b#Qno79b|HBB|8q-sR%gb)R}syezNQ1~bP?*b&I^ zLfW3weo9N52YVd}E;%SUdAiZtle0dteHAkxFc6qUxRgCBZm1+-7)a^Xwzj5LR;z1k z`gZWz(Kj=*va|#q&mpXbIfR`kf4ouB1RCr1^_3{8p2#%1aHWO$JqCO^35iR17Jf25 zXZx?j#KfGPd3U?E?nFpmY&Y!q$rJHrG&cGG4KnM$9ym3@$1v$j;uZT=FkYf(H25~U z-LNl_o6K4sBzSy`#lL@{Ae%aE&pZ_r#LQg(05_$DcfP;;f+fKBK6v-m!`xh4T+m+u zm{m-ITnZMDsj0P*5#BA%=YqwEm3ti1oy6)RKt_>820jmXSI{Bb+aH6^E#!0Q20-aW zU^6175DiV{<)t$cDi#9888C6+UsY9A%``P=uoV~>fYJi;l#-Ew0^ZQgoSB(v_A4P$ zWO2I2ZoD|+XU5`Rc*tNKWAWw4)AjcE+kGEp8u%!grbrn;0(k7jADJI!5}BF1?uaZ9UM1!41d1=^5u)@^=YP*Qb-N@9Y|oFM>o(2!lumAfFdj`K1Nw4hB@YeF!L2oZ$;A{)3Y_)#m#1soghWIj zk78sd0djBCZy*^R8|!FqCm@(bA;ue`A&rPjfC_dK2_*~-74?V55r)2eUy(3WRd8={ zLg1^BUH@Bqdr*zkm|j&RVJOOo>w$A0&#H4gu6Hl_2A@9=WvJBP8G!EzYrfqs(JQB? ze0h?ji53p3~?p6ZRDmlSS>dt}dW6znx0BFS+dUQhOR$ zq?NyaKP4pvSU3k!bpbiR$H(W<($&(`%*vug$}cX~YoZ__$qpQz50zB&b!LiPhoFKk zM2q5kQFv*)aEVDsZ2o-j{_}^z%{W~-Athzl*cpT-aHd9z$WB*ka1R-g#Xrj}14NLL za{cgOTLc(McFiY!|Lh+?Z1C}ybTs|uf*A?JpbUT!byvti(7@LAYkYjzQA!JqOytVa z5|6tUgb6S)_5s=tnq4l(>x~shjPzLw1xfV&@!%&fPEUUX;^b3r_4F~6s7^Tb27Afb z$_$1^i%Dl0Amh>Bs*t;?=E@gY`PoYj?$4e*Q&8xGTFlHmC+c~;d3LZ0C{Q~j2qi8~ zNJt3UQm<(;V$`qI14qXLedlam&?bILT94~KLU#ZXLl@Q3vS1HfgORZt>Su4fZ)9lb z;N+W-lbtGyLa2IB|I2~Q4GpOb&;%T^Gce$G5k~aCm&`ak3}0zlyE+=zRe*RR`pn4@(J*0|4AFdh5GV5W@00xFe_;P0**mnJAv*!p8h`3Q3j5-4Ess?jwT|{KIX}FzhQ3nj-l5AVopl zYz{%LdV?PDKgAIr9G&%3FOjIug8cmay!p7#p8?83{42$#);~g82Q{h_fcE(*%TMZ4 zK!spMQV6;EN$nmt_w+EavO3Q<`%gg5N)3wY+4aRv@})gD?2N81Su`}X!{_}eg7FCn zS&J!IZbCkQwyw^3e?-;-^XP~m1IhhfH9f7dvUDVQ;^)s3LpJLQpSqVIvjKg7Y`b$B zl0m>1o`vB28_ACW6lUEyu#&IF1mHYYj+a{rI3EN4zMBw5)XBm#*3^C=IRIzVKfa(< z`A=xa#{jWvxTSv7HxNY~6FQ0W#y-cohL(!T1AP3~FJJn@P54PtgBTJ?DM~TS0xaF? z_snRTcp&6R05K1k2{|m8ySVV3^J}j`n-Ujq3=QobX9Fi2y2>K>!*f57e3kDR^Ruw9 zM3O(X23uBWA8yQb=TD$WB$%Lp%HaSDS`5(wAs3-Crur;r0*h~BvvqOu3ZNIX-Pg8K zQYbYU86c&D`21|!02#Az1vFK;=g&I~+o*6t8r%;|0b5F;%-Cf=HZoca4|k$s&1r;) zTajMV0^|)8iUanKk8!ZDkjq7Opcp46YOO7r_x<{1ePjtc=R8`L7KG(!S>Vec*MUe_ zSh)E+h1zY~Eg2wRY*G@J`2ba^0ayeE1`7*qGRgygaB&W=8Q6Me5)WS;3A}c=Obt_4M%2iK=7=w(o3dI<7bQA)FG3sew^~jtoR> zuFcjm}4Rs!(?1!5AyauiB_CiBLSqL%1<{`7u-`5w2R+-M}bIA|l`X=cICj1W|yzpx2 zF6^C>aOa?*prq^FJi^C-lKbI9l5GvTcmk=Y&&;=1eoADLxJ##divXxvZU2QUGswSq z5%vB(v49i0G~*OfsAL9Xc$P|j&btR;?bz7V>7|jKiwB@r`1LRDp&*Kzm}En|;=~R6 z{&%UdIjq#{%<8>-svgXA- zNL3sh^lN+w)AK!5E>JIsR+_ixfA;33t)IUCkqN}4+CMA<)oIU|1U(cO=E3#V#q=dI zV-ESlhj8?Q+JDmlwvJ2H8(8udK=kLZ`!fS}LYnC5G5kfa5EUp$vBfnVU0nV&xZe9n zXq#FOB~nGDoGpH8;NM}R_l28>2OQ^5?S=+>9)I{oMn`pjoc97HzPUV5@{Y>h@3CC>yECnTnO$=%%@5<=#e zT&RKf2?^J?wj%b8%H*;^O6-bb)tP^TCc6V%Lq#PcHpGIJ1;v~a|tWhJRYWod!uKr*;<@h*rCVz6>hi^V^(tD92V z$#}Uu*&4pN+_X~Yyo22G=zY>{z7?MA40DPIjpyZ6mCl8qf&>LYlXH;e1*5CtF% z-xlaL-rwD|ck80^0B9yg7tu(^&0Wwf7zhFxJ-z2h-b)6@N9dnYQXBzrett`Zj_&Jw z18!zugqE5bJ_Uur=|&n{6zp%6d>+z>|MJ1W4Gqh}BO)|eXaI~0q$p;q0IdmZIn})T z2%Y*tD9_dl9<)Etv$^VC=P=e8!x!)^vy#|(@Z7+-Wz*>Zb07f68L@TRvm--FMBfNf2t2~V zZMy}`ISr_w@IRYj#VEHzcn z9vXT_2`3kqb`9ITtI!Z|`9NF)b|XWA7T{;^=qTuQihKTpG}Ytk{HWZd7klBi{>D)H zvk>r7RPqxJGfN5!vF=5kg2`Blj^mB-TOR^vm*9EbD)sm`5c_RuX|cB=_Au&F zVW^eMW@2FA_d1nbjEAhy(rU@GrrK-J>lPO71NQmvZGjai$-YO^(FK0hBQ~a6#YX#} zdwiTIbA27;VzBB<&oXQ)PY}bzsIqc$AYt=_xE(SvC6MIg#}1T79hOUuYaJQO6%JiX-_?=>+Cm=7Tp{KS?8vZ}2N*N{+y zk~DnE3lB@Dsj<1M3ta&uu1ZKXfPc51Gf0ihdpD{Rm}6Sg@>M>p%ESb}rmlqn&>WDG zn;Ud!&~G6q7)pWIn7qYTgqi^0&dxRll!Xfz#DKa*#a%6q6M0r9yyo*jsUxe^U#naQ%cfrLi z8Dy42CbA6f5_q!Ue3sTrK#B;s9gr@H%u|_2a#jWg z^Y8Vyp16kxX`;Mz%-ZjijG39&Zm2lM%Aoa75D?tu02(JREBkKr)r*(;BhAgtQ1_8a zirs|XC@R`I{=NwCvx-6)10oDN5vU)m6&UM4_1sMHa3K%};dKN2OQ_(p}!bNmYx^K4|&9?ko-Fr z0hvWeSCyA^*!4kh2slVyiw-L1d#gP z-}YM_huCqkLxEoDD>8AZFb6MhL}X+~M!m=JCP`uOVet+2365 zF3@}y=jqh7h-@7CG9h+5(EyA{`jSAVLkPT;ADNml0Lt1$aotO|<2JavZdJ?61RxaID|O_8E}cl?`SX1= zSiu_;gRycVW8a$zs z5{`~S?|>tq?`(oTb&Umx{0vHRm7BM9J}|v&NW(eQ1+(p$o4H|hgss1wNf>5}y&6FB=Omx1NwKJ|n>~Dlzw_m%v*VzV}B|!cS;1ZqU z7Y_Yq1WZi*l8D#a4M26T&NoWZ5H0(D{#hsPI2pbnr*ASm5$ zgv`3JF}_etnpE&TO2Yg1@050oDi@5xyuwtqjUa3m{wW84ps~(NT?Q}-<$dpG+ADSS z>%(Cs(QCK#=mt}PXW1%BU-%;j`)0z!f5D#c-5LZcCL<%0ZXt01RcLK3p-0Y}tsc-& zZ#=tBt^K2($O8!Wb^ZQrdk@WgYH||5WZzd|9kiGkfHnVFW}oBY)~Uvug5DvszxhtA zRtaV@>znV$jVU!<5b(sre4_t$X&fd>YOE&_g;?H6C$pB)$rGn0B)l&_a=CaED+dW1 zw}sYrm=gjsf6W97EF&nm%N;*Tp88&Ud3m)GQDzL9L-&E=U->2$a%C_A0P`C@p^^cH z;dwyl;n|&C_=a3lSpqy#V*;@u_0y*Sk)Dddf7RwgPP@h2WCdT@21Pgq#2+Ew`T*SSoJ_VP z@mi_N%5vI)$9 z)cbIl+FD^cZL*0HM!G_yqMi*izM+c&nwcu-O3{umC~@PvXD38q*Yi2w#xB1Qx>RoN zDp)H6lv71e!pjp9CV&yD=Bv&ALa1wK*qN%rTmHTx16SA5@(7HJQ31qQxrY!_hSdaF z7e+MXp$ zs6%RjBnd)JpuFmSce~#ZCj}-1`~lHltET&P5W9lVwx8e=UR-2GmKnGC<~z^+RE~VDI!6qX&LkltgSjQpa&d?`=9BG& z%4&bi;(!8pu+pcH%m=0|#>Q)Kk_26>U7ej#D70uFK);7Wd@y&<9Y(}DJ2{E5iUL!g zI`Yxe%S6?nyyYhkYwzjlxz(5_N+EEn{o`EFdzJ+ie9D=AyHQBH`!}`utLWfbt%+hp%fZBI)mEk+EQmI34?_z5e_@(7E7C(GwILJ;QT_7;pXO6z(Wr7{%1W3Z~>CUz~owa zdV{eyWFkm|q#!iD1Y-j}#|rQl`=*P=hK~pcW?%*hI8zf3kaj3Y8Lb3cB(3@)DjXFy_j0QBSae4s9L_BZ}pTdRe& z=P^@#-QZ%=8^Kq=~Ii1a^vm?Gff^wxQ6X?q(q ze25IpZ+`Z9g#Lh#Fj6Y{C&U2kX6p&UKAb@i=FS~|XxNlZ&!})A^!AXL*w2(m3DU@5 z><1E4F+mIqIPX$dw0;{CK8D_0yE!2{86sEWt?LGZLAnhtqbHh`FV)ovAC%{0Wg(k< z0j6R-Q#<(Q%|)YassN~$K0b{S>E?qKpjpSqYnZQ*e%|;4YUkJJ=uo7Y6Ofww)hcY=m3i_QQovH0VZcaF^8V&;!;f> z`2$9fp;q~zp?YIPb(U!1sl0xTl-KR@NIr|;SOk_I{9N0CG=KABdvO79xHzE30cG*ygy}FCzC+|lyUjWL{$1z1 zQN1Dxv!)@POF-dy=uDSgD{l6>#B@B)=Q93xI40QL4t)(}U z0uri$*&&A|bb*xOi_MQ?;0DxMjk75;+lRnJq35wRRl3OVz`*YILzp~LD^j--pa5Y` zYlBEINMf&-y$Rq~G0g35@>f;pw_I8b=LAHAQguP)Ivl#hLWj)5$H=5Rcg4Fei6sAx2Kh-`==k~c0l=KcX@h7N*GoJvo+vn!({mTJG;QU4;wUU zq&gxWl2KBINI4(DSQ!j&5y1Tcnv_*if(fEkB1)U9)TnEjag;F_qe4VPbozpi2t~_q zkUABc3}Y~49ma7yJOreA zuq==eFRNrv?6?wHcq&Z_T3{68iS-1+691iufB?iR3eiz&@AE?lskHt*J_Ob70bY#u z1rE&Zeuquzez3x~Pd)bG!#}!z#m#`Oz^;V0Gpr?zehd6y^@vS8X<>Tm*DtIs7po^| z|1*4jEXH9VlaYm`FfR{*i|G&+`Qw)_$d@sD@CMrdP$5{w0qNkbt|}nr=M2gUE1>em% zTnG5sw?W$O$hHN*Eie-DSb4B?<=?+Vpe0hy&gX}TAluX&uUlT8zJ(7nP`GxxJT+o| zlebGUOP~q&bFjBJs3m}o2_7q4s-MGFQPYhpJd%0TBNT=L<|=Jn&Dys&*H^&@AI2c9 z2)y%7Q^EE5(MEWPnrX!`gRi1ks}OenhnM>TyTPaO^M*&L-4#829R{Y3cS2*fEOLj*fL-KsPpw#n(A zinccCE>5KYpVe3)B#7wPJ+Cj%Qhl%U1NYW~BQaoBZ=y+bK3MqUHc&o6K{ZMx2raw2 z`+E_fZo`GbG+g7vrLJCKVIkzJa^LoL&QkW ziyp=If{y?S5JJb#_h8~UIgNmTUzS(=8$2`+v%eKE!!*^$j~@XZJaIRHBp}3{$R?=H zq9ZX1VOq1kp<#oL=p7?Zg9xuT$>DY5#Cs@kwDh@<%wG4Tx@j{kW+Ai{)CTDI`u>qd|gpj#a<+Lr+m0Os9VI&uOXHXD9Lsdt@vbplvzZi z_-SVvq-SPkgxF3}aHO-j1(-^~9t)dIB9o1;{3-(z88D6lUYC9+k{l%aVcr@X^^qY{ zQB8nG$kz*!Z1La;i@NO+O_U};rU3>-z@{5n{7?Y$%PqEr+b;cFWw*ft#k)FQhNL>SBM}V0QkG~FnNs;yv5fu+Y^=?^Ycb?x<>kX`PO!rNih3L}2nyy(&2nOW083I+bE4Eh z&)o6I?m?*WZ2e`mhVFusx<1LN9p(r*#Jk(WR^joC{jK{ivyXrJaR9Qbx87WxWBfv) z*$wzL;`i?_G`E49(X*S2CNc`r@7h|PKN8yd;|6)UTgMTM>ZGR&<4~*Ky>sI^3BMKI zAoX#%hz=3^yT-bi@^n#=k#)f27URJ(2Pgw~DD8gUHxBWM@#Z-znE$^|PCoKw`pwiW z%GcKR*eEK7Fsh`C%oE2ak5l`jK742dRdFnH2=gIBPw& zRFvw8w}|uEem^AU^^FWI!IXo2sc9#8l>{vx#!}tDyE0Xz1EV@SE33B7LbN1PjcL57 z_vY|(ZpYE)%YS0dgvuE_68r|ke=+Myh!^1oUG@7 z9-W4WFH)eCXoKFF1~@F{M{#6Wz~IaQnX0aW4>FdSJ0&`KdC`uuq) zLqP#-$FENvs}qUv(BFYRjHI=H1I_9dEf2l@AWsLrYhQ{W+AvKeT$Ej@T@COnEOd1J z3eGRVzVIO`>gq05g~e-5=P;ZZ$D;Miv?BTJ^KCSXhGtm*rcS&iIT`8naG2al;0g*O z$P-WgO+Bj8?pxgJ>1AeOo_kvd7Q|v)yvBFW6UE_|+Im*u@F72|eaQv!BYIBYB;@6p zKNE>~L`O$@$`}C}1pvN+vnO8pVe-6{QYh~RG89!d(nrta;49DI(3lo`Pn5pOzr`rMRF&*6Ut{ZIhlvnde%aFy9S!_5NA z4HQCnzMyx;f5va})=^hgrHSc26t1L$m^Qqbchuk8$VgOHmT}ut&D}Yeb+31^c^4gh zf42)jCn$UZyQP}MT*mgMra9Xu&t{r@MHv~NhtY*VIQQ+_GKL*L8uU+)TE0Bd0Ezr) z1Jlom5T@Tdx29biPjSKCfO)7|`#aL!U$1XCs>!B8e*?@N92}frUA<9ra*{95SyP~W z01N#C!nuT3Zcuvo9zRBDcu7KKk+Zos$O>-X1Kmgn{G~?^Fw^LszC>u~?28NIXfTaO@f=`r4*VC&7 z5qE{%8fFMMIR^m`iYMZSv_a6*1Ms+>S03~uAm;TJ5pNe-gHnBla?UWN;pb*OkAXnh zfP&+u`r+AXCb$SJdX0uKv%~5!22(%qD{}B7R?PO8z6FSfc=VAQR>M^bkX?dX5~2X# zvM?(v3#Jj^JIUC>5T|p8o2yE%N75A-2ym7fGtFIU8KOF; z4yvbIvVtt0n_IvB&GQHF4I8+uu(l{Oi_{Va5(l=g7v^GlZ|6%SC{i>T{8}e z2$^M=uRmJ%NRN#*6plme#f60(U%qU8pE?gJ4qg7|P--06T#@>%W`!u=6O)tM zh_xCEUd7VOd7=-^W=BuYgSO|YuKmykKq~k~zvN8IYh~7MN@hPI**%z7O{Wnfd>OnD zQL+su2^AGlYYSsw!QF+$MU}T)1bQF}(7KCoswY2xUen$_iIS!muT&4gh_zKHm-(Hx zL=63{gI%1wythnEAMsop?(Z$0#lf>vic6TE|F(^d-*fxZen!~ihYEwXC==8H#L7k5 zHxCbI;GeeJ_i1UaBg1GDIZmsii-$!-B3JSmeSWtp*`cq%Ji{r}1S5)r!_@hb2t2sg z+1abvUUfh0v$L}q_HJ>SUFA}zpk(&125wgR@uSR|QkoX5!0-X<>OO;nH!e>5(xpq9 znmSkiWZ$~{sM*vhW%ECf4o421%1uhvidDyCfP$~0tgNXOIL>Ma|AU*`M;wFnAG*hX zHtTUMeCs3u+I#GnhR9$m4AzQ@ieM9ubq)S(Nm2S(Dt$TIR{6}Cg|cO;>RhxC+>+Pf zErEpe&ekduA~cMu*MW;izBec8&p9~43x|8)-vN;bl=Grl$g8Bs_>9k<-Fsp`4X?*w zk>xMMh^;lt!WM-Dp_0BmqCP(1hDI!ZU=4<%L?7MI;WX;k5RZXk`*#A0!N82>7eP9J zZk40osnnq9Ly8CY;}lS+Zf=`ETLkjMuHz?Z51l>*+ClN`{iX2;h>%m1hWG^pENyJm zO&ztaU!VH{|B^5Mr2t^y0VNtfPoF)b`eQx^YTU+VMxQH? z=dtZxL7M8BK@Z!xAqD#{m5#6v!Bq*W0}(vYzubVq1C-9r%%tls*i3C~X(1*-@X+c4 z?PPOb2TR6PVvChmekbX~!unJ>@rf=jGR*I7#7@N_`uvtQKtg(Y`qtK%ow7+KH~oik z9$achLQ+j_?UR*@v3vLK6&C(-?%QAZ(*Ox9Mti{FulIHwGl>7j%znIxeZtr2M(Q>H zEqgZ^8U2OrUN`~lX9r{=$(bq;S<>9xywhcWVtl-nr6vC}>l>z-J2cI_37?vq(YaY#TMG$Z96kXdj!F=7r1Ur(N1(b?9EY(*V4Fq|RQMa?dQxgy z+I{nz&w*oMvW^oo=aQ_3C%UG;KkePqS*lbaknrZ#)*-pacw(C1oEx?D*!(lydmAvQ z$2cA#8nR+RgAi8Hx|%V%*sr(sPOvn)yVv`yvKrO}Pavy9u{+uR*Ox;E26FTsF%tkI zUcPLEZegduoa5&DJ>tJMP~Z<~*(-=Iuh<(|99U_F9)DvQ@WO{nK*OIh42p}oMA1Oj_W0R6*fBb0v zOX^ozS{l-PnMW=U+jnW{D*)e~_jmV|?|erOL^(7dfbLTZvLe7bFkKCqM8b}e{{`i> zu4EMP*w}6?ZnBbu>S1S>zt_tI+t}wC_~Xee2W4;a1PzoneENh@(DZtr+vTkvGrtcr ze!_eOs6&Emca-M6wFYjha}NjWZRKG5?R{rg4J0W%Mr37S;pa!+!@i2$AGFxD6gjZb+&4df0Hw}z z(Sn#Bkzoz&5NyWP%k)HmfL00j%1oB`wy0S#dVRrz#wXm>ojz#S__6p*|I*`J7w*{D& z#}<8Swl@By)Pto4peT*3GpOWjY>A}oPS6#R@0l8WYkiu8EiO(8?|@u`h9 zYETHJ27_-5_kIi%*_F1|b;3jB?BmGDXHrf`^bEAs`{M7PM0C^B@wYsLgbOE^ zB{mu9S%9ZNb+?x$7^<$_icl@H{}>jYpwtOGroO$8}sQyZv2N2TwFlX z(+t1XeV(4albn3fT_)s==*g4ZzwC}mc3HiB^$M`^9&>K>XJUvar6vtQf<1B9E-hW#2Z{CN%~4kH!-!NYS4We$D<;KtoVvJxImnOfWZr943kMUwf)7&7hN23 z25|Z9+f~w8g$V+hv-=`oU}IMFV7iCcUc>Y~Ln?$-@J2?6e#1lrp%12UjW4!`pvG{# zdzaylpgYw6Fa!ZXla1GyhNu zLPf83K-Q;V{j#QJN4B18VPAAqR6(93%pVt9Tz#s(&axOBd0~jw1OhE_cpbR*-g4JM zS9$GPkZ$=Jh}dUwaUoC&-j0VW@y}P@+Gt_+-mydY#zRf1vRG#Or=5v_?Bnz_72#oRYmWn6;A#KnF8()~h5L0lRmWV+~`m!W;&ak_Q* z@L^j!JEm2WQ}D7J?DL5@`Y#g0dIC4aTp#gy* z0U{U`T}gu*WaQ+7rH%FZysc0L5lh&HMmPYSzJ8ex%5fI03RYg7`BnnL>UG`?XhvWj zi}QIXA4KFm4@&O6-vzg$o}Lu_=N!~2KuGuQ6;pgnY{B7yk;_MloTeHjI_1rqVu+8x zz=+hNS(SUxab`$~7Sj+qh#+Pm9x;_a3kwf6pM@=d2j=T?|31*%kr&Eks5*OBP8cHm zNXn7rOOl+y^GDZs(1D*lOYOqEot9oPn<#T;^<+A%l)8F)avs8|ou$gm4_|)8c!sf| zv0EcNI-2kC{>pNpqfb5{X>@Fsd~I!wkM9Mh4YTTzlK>NOq*Bbs8oq)77~a}pS@Mil zGe`;i{B}Kml67Yp`C;VbODW-EVZIG`#de# z$ILu{K6Y(!A4bn>`D4d4jnKX-C|@*$A)Xi$K5lh}jg?sL{Cc`wN;lc`Enr+b8GR^{mjEbznf2l{K{}Ew?ugao|1t<;Zt_`_>VT zFp8Ta=)!Ip+XsBk89U^%_|qB^>D)80G{)rR%_FqbS7aR@2Td$li8i!PwY9!J7W=Iv zdV72Q-{jnd4D0yGll(U458;52ebDhDJt#dYiXn?^5>t)S497sOLPk4Y=lgrF%Ff9! zSTV7(9-*2xesLj|*c93h$@8@4-1zu=c$hM1A1OCarEZC1HhMk!2oJEJrvHhaV@}2wA^T zPuTnXgg3Sn`UslcyUCFw>S|mL$N?zj4uj&U-eTIu^WKE2Dlnq=vX&#FQ&UMJbHOeH zPqdEkg2?4*Y%JVVsZx2@%*ItUTglqNL?KJfdiuvXw!V|%CoqZP4@XJW z4mU4MEO$&ye59@7A`z&%5lZiLerKU7&W^EjWMO~w-j}#Q+`(cbFI`hpvjpfiWaUv0 z`Hy$+{wf~1EoWRqardsMh^7CQ@{qB%*#7389^Srps{g+h;K6i{ctb|V3z&obeS8+~ z1?A)jo45a^|5q%xUwT%-_Y_VB9AEwXgHRquKO>xJ%*;QroHI#{S)wE6Z*?6vA*Z#p zv_zNY+sl0q!yFd+>Z{|0hR0cu3~FmeBUeKS@^P)1aqwMIsrFV(`3#T|I7R0EHYlbvsSUA%$4-i0xja!0kQopRg=L^`vnjxIKn4vr zCXmYlCoFQK_OHF}K}IVKv|o(#oXc;uJrBh03yAyA1uGwZ`jwH|ul!Zv2dRM2?V*(m zk=x^E1aTXLix6!wRPDC7z$eQ0a|SsZmv=%iUXqaD)+Bm01@NmJx(e;rEoX{2v=QWh z(>*}*;lyt`ejTV%`F;&^;4p?}1`{S~Iy;o1&50pXKQNzg9X_nXcr^uV50tLOR;>#6 zqO;zK$;89sM=XQxV+<~&rr_z#qr5LymLUioE}NtkTXAY_^^ z?x^r?HvPN0dcDlmcklrD?)`;$zaTZE-rpC7V}tWyxmFi|hp4`)$V#)&&@x6g_Yck1 zuIN8&%e}M^^Tx&&DjEP;52^$p*4D%o!J|h{BeD4YeH9ZEvaF}*lY#@}nM01@P(suf zq32OO`hw`_tIp3}cqehF_5S?C$cc#wgc6R`Z-5dK zml!Ak4Cgaj4@3ryhw>9Y5td+liiq|ZB0i$+M4h!`fOORUJ)%lV90F&(Lcm=k@PPMy zj+2dzaCs3g2uB6`l!s_XD=Lz~vK2d3!tD*^+#F47zO2t}fk+ezU<8iSJt4NX@K8BccSW*=C7QBA_`OBBYN<)soIw>mOe5~*tQc?y^w9mWSB5x5~Al=jrc$tyg0MSEOz=$kn61Ykc ztJ{^EBB0GBATlyBp|TY*fc0{Kb^46Uh)=Dt%9%3>r|d{2#JK%`hLvJ*5Ko!CSvRo( zp9>Yb1!TX{)Z|YHHLe@pns+T6^ZqE`ws0{rfM(NrWV?ZTznE zc1F4ezS=$8W-ys{j#rTQ2k>UhGR)%@Y6idw;JeJjt+7|J0v4B-E!Tcw(nGDX8%*%*|8u6`eQNL;U?+&eX*~#Ks}G*Ad&RLz7fZG!w|s zZ<|)+r zs{70Bcdl#p@i+Sc8R6{Q80bWWK{Q{^wF19@j;zwszUu0Hz!Ouz8f;K0(bacw9`3Bh!JnZL+iV(RwzOKMD+-MpxAMav-|s16rGn z6lYE-G|*sS>2lwhf1Hqjd1wOwb)ivZ*c_h@8aV`;@Eq(~TVHfYbK#S%prgLU6pv1ScXQqC)HJjSUUeazr3 z@)TQDvyaoLsou9XHT^RB7okePA13kX&BgY&GFUPY<0FcReA%Qhf&|Aj(tDSNtI1tl z$k|?XAy%GnyW0zU1-DGhxo<*gi%ok;EAFqBqM{cx8uymBC6tq-?=OG^3MUH-3Mv6C z7I`T__nqxSNNc`i6k8MVlaLT0bMuiq)Y@K<;3DJx+$qV1ANKuyeZIY;%rMWK1;M16 z2|zyT>R$`^-hf>_m32G4U|ow-89o6Ic)KRGnT2$He$yX~X$lD{3FGMqBVup&UTr~o z?)&6f;RMPN%vaK7eW=y0fS?MSpRHE?um`oJt9{lPyYZP;)%E))+$X6Ve+?Vej97iq1-Mg+=*LLomALxrKREb@iE+6mKG_vX(id!6xh4FuUK+$HxbEB~+2xPfH>=#Cg?xfL#Fk zG{)N=PcSJv+RElVfe;i5*0M6TEL!t&5Ti3QY~|6ZI>gqT+8>iA!^b5UPW7(d4(wuX zG|n?rlZqwN$OS~|aIcsn{=5s+RDw&g&j{7IY%(p6LY9rF(mrl3~~%7#J?!-ugQ+$w-Ch9`eTD%LTVpF$2}GXUJg7AZbgl__xM0vA}>Z zIyg`;TW&6&B@5tQebbL%R$$jbwnwcktgMz+XgM-Iag9IqB7IhO44D`{-@=fJ9Ua)1 zqTs!Yo>7jAE48^;$J*LjQ-c#sQh4c}|6X=rV449MAO9zr6!E@4At*XsW(u_ykQkt+ zJh#suLaGjyCtx1e{`A+cOTj2A@-1!u`1uo}p?SUI#y|m2tvt!|e0Z6IZWB zE0Us|8hYrjG@e+$1Ir z0C5P&Nv3CKzhi0nePAsE{1PWCuduMX=V`{$@m8hFYHF5E%#cwlM)zWc{Sll%m^u)c z1Ouw@y*!mLPuJDC&`ac7e}y{6W{}xlfT@M5lbV;lyA$gYUC?_R!($P8Pokp%A%1l0 zb&OgAvXI&%8W9(F;82KVR1KQQKT{{3N#1>7yK?j%NV)Doxn%ExJ)n(1P}Hnl53Dq- zsjEXKsNjuK3XOv_)xda^6jxsz3p48Sp&ZrDR=g^+p$!cK05;N&1)XA>Y50ofX_|*^ zd!{A@d3n>{yvcx8=WUEyTxwbx#O1wzK|r|e6V&nac#MGn4|phS@fBnxV3|ByG!y`t z&Cks-o^M4|vzItjyG#NUu8n5+$Sxx_l&NP)N^gqTWxp(h>j>!+zo;%+X5#V%c(g7f zyCwOqst|||Flv|)drJtNoVGO8II_2v1vJi9xQnAA3+XwaKwU89XRd@cqomn=8r>&a zO`Pr1V2kYd0uas}82DZa=#b>yxfwg*W5@OxJ~?;c0{pJQ$wwuuB&5*go0vQ&tRN|1 za$;gQULJG3MtLS?1I$?8v-L7^azaI&GjOCSDrq>n_6&jhRBn4Jf~lT+RPERIc_n>) zH!wSZ_IPKmT*4%$(?z^gMuGOA5&f8!&e_|dDR)d+{E&zN_wv2I0g~|GTE&82|A@r@ z_HJ_yLk|pO&bl#@*C(eP`B)f8V9#{8YEoKUOw8HYnW81d5?4M!oLwjC zKn|LaOt_&C3u@z+94-ZeCU|lXomL%AQ#$vyad}iO1gU4-=KlF5!P}#l5YvPXNcanf z9Cndzf$1`I9TYMS|3SqEUX=Zqq0>1}vO&skI6Q&B1wQ>01~O)?KbJDVFUy_@*R+7` zs-VP`Aqlvg3DO#DaQFs_X(p37v`S5LY7jr_3fICdMG&BoL~EcyqE? zV3~T`q9}F#yAOOYX^h0y91>)0IVvIX?fdtzT4Mm6dpusQWM*c53l%6maKg9-go^E+ z{uiG=Utnh+gnyC3Q3}^)wYS&G?FMsaX*r1_*3#@k;)$EP=-r-qz?=rN2?MiZ7IdAX z0-zybWO(FJ^Zfa*%=5>w?IAk&+}7qb?wD!LeymDPid2~jypZSYZNd;0~jzM$diLk<)Jq>Gn} z#c6_rUDfjd^s36r%^723CgkMx=sF*Ak55c+9U0L8zb~Zw&W!%y0d^0hWI7oblq0iZ zK0nP2K9|+Sr%?GN$%Xx-kHgpq^B{4QSxT}nHbzLrZSudY1oKt3+-TuW#GFVgTrtPH z`StVX9;pT8mX+DvnTi)NBXV*+T=8mvefg=JM_Kf@NPPY9C{=98-sz%Y7wQ>2v9!d4ayF( z?%(59eCsAGz!;F{Qtrk{Vz+uO7q;0d#ZGISA7~YnIt5yNa_PrF!~)ZonjV3U2jK%B zh+=Zl7f2QkkMDSdNju<_+qwf;SnnJR-c|N59z9B!P2P{Ij(&GqqB}iPbtF57my?rI zL?jDF9h3twQ>O|9XsSVA^}f#OIDx?c8j!-E*Z5-St=`%1yt5gKi3_TQfNo`Y zIJp6Uex_pUgu|f(p|45hX0x?wD(TyB;9w+BU!b}Os?Z+)nFwI4D1dew=F$=ZV zP+oH8@bWEPEv+Zx#x=k?As4Vs)-*Z6(r`5wOvH(s>#?GjA+!$+)IcSB{`@(z($Vkj z!fh=k4K18XyC7^28t-?P8?k>6(Gcx!nZ`Q_HqhnzEW#Z46bBc$gZuX-q2y{c!)HVl z$IO-}Zut|Zs9|T;MVv^IE`JXCSA$yt%CeTF<=h^C(ZBMy8g?M#^mz{(8^plwjCA|v zv03!ghm?u}ss=O_NG<-cQis`g#9+^1A)(DYbFo>#6^NUF`|tFKh5yz#26acrKj=X~ ztE^U8dKH;ATPOz6g9bV+DH+w0evsnzOUiDlt3epMu+#oPvV$8HKVSc?jblhmY^md= zEy>K2$VkP%FDpKO1`|7kE<$WSPJwF|FY22d=nn|MGY9cqys_Apt_vLg)D8(TF_^un z{#cp8?UDIK5wK!ROfjm$h%w1z>LyM)D@?;xn@Xci2&o8TD}oo5ap;Ct=fhPE786rb zs$45MM4mw6xF=kvMP1x04`1E(7f4cWhUcXzjap;^<}p~*lW zo%~j!6p4`_*DT*CyJUoGUf2vo&9T#ObOw%C^TR%H=B^imck9%w#}pv06EqC__I>|$ z0}ApR@h7ecMyI7k86Ns@27BM~n_xVH*)oJakp5`8{D(VfL@hcF^P~iPgLrMhqzkBk zRCaAk;?^ep!6?LjjR-WdiCc7_k&6~=f$Soy5SAE5+h^S+zf6%)) zb*&9Hgn%I0@XVL=CPmk4pf%{}l^VLHe>+d7e|GdH4tm((Kf0XcB;UM*$Zu%Ph@Y^j z953f5l(P<}2Ugx9r2`v>+LjyatAs?I_1C$kf+`sa~ z$Vexxm2~3fgN*Np_r(*qQR-}mvuw;nTadY_zyBsW)`lEqgI@wf&ruW@BAZ=CMj1o6 z%3yBOMG1BZ!11~KUh>#8adCfNX*&z_8L~jZCmC-OX^4gg-qjl=j=QUmU(U%z=W1$U z@vVpA4b0Ox2!SKkvUh*~uI>4OM##ZIg4_Hv0I$x4azYAppSXS~B_xnJs*wguGax{@ z?S!K4{>rpzgnR>eMSgA3n*RO}38$HOj4bN0BEE$Q)--1da6zk~z-v#}1Rfm_l?V>0 z+3kVSgsTZhMt1lh0|e>;ZH-*~gJwr8L~5F^?2w23@?}K4{yv`vnEOgf&NlT@`YO^l z_iNLfSC@|+oRoHRT&oBaa~%LVjvEnBxRHO| z;fU7NWA|GQ5Plv-hPx<(-nm5p0stjDr5>jJ;iNueO?EYC5Zu25h>1u&qSAAdgmk>Sg1DEH9`fz2&+S5Z`~s;ngOF!eU-0+gj5 zPeDI*1A*HcT2=@?1#%KN{skAa)Q76fadVNP@xyQ$$iRt7g`!$QBK75wG_;nMmWabZ zzYOZ>7PysrhxtWC(eWl|Y5By9k&;b}i7&k=-{Kly352A^*;%pmPtFfiA23`#vLbxy zz+94&*drNc<&YYHzXN!H@_}eEn2F{W7C@G4%?BOaL#}n_jwS|_{(c!wAHnJ@#MMhBYCxeFYkqV1KH^N@i#dljBNbH=oSaCu`B;J3Y<-TkfW z6*--U4D(vV)U6@m_siAhD+ln5YzR6ueNxsBH!nIoHpITT_)NK@tO2kw{gMS~0M`3e zef|C)dtdwc`Qcw8^@U#33{j+NNO=ut@IfLT#z<+$DIKHXuO+u2s2F!$HOkWg4jK>~ zoRzaB$36&+qKYuXw*tuw^K{%zF_+K1e7^Zy>nX9H|W}d$t?rL_hN=qqp zc62}+e{^md_}u^KUedGUj3H+jUe>Rp6^0tI++~H$?$vYBeJy*B0GW6LC8J^I*u%s4 zRL>+X&S{72L7B?Uy`ud1HkmTAuh!^DJWTn%vdUEf%{Yh=V}UKBT9a`%@y zuA-<x22nThLWvkP>j)MKdUnQDM}YdkK_9NX!k0yvWO$};v|X+l z7cfS&AAQ9!g(Bz^x&Tv);wVE%qX}ec3-Fc9>Ex2_BzSsyqQXZU zziMZ9IYv*@2G?lryL~$b-xmz=P^XQT`27VFuHP?scxB|AW~3K#J;i{Hn^{>gHj8cu z;crHyE0GUu`;a6dF3!shPrk@aqC3+dz1zH3?tj=|9YNUQ0u5IQN49B_Se+FUJ%a$;eH zHXtNF1+XvS zDDQ2`!A-4>Yxae~!8DP>kk0`FnX6}&c0OKS41kec#zINg(btFtK~xh2K1qzOUV~}=`XSSv8o++Gp*<36b7i7+EEG~Qn%B6O-76@4J48tWKtuW^Sa7kDKAQlQBh*D0Vn{rGsF48@hOUbk~}=f&(j|lA^{QukO(c1uT%&#E2{wvRmh%wQlN=>Lv5*j?+(wg83#tK3kv|Wkcjb^}C#Trbm^ZnJ zoS2*2g_4uU z5o#_XLS-b+L4|1&Sp7YR7DksbHFNU`tY`!q@%@tVcEZjAcUV>?tJr<14<;D~hPxC0 ziS_84;cJFGdel?qCROzm6|n@zIVy&fFa^T-kXjQXxJKRi4zhxKPAl?SgT#A-mM2e2 zN1MNM->d@@9v&><391D1gph7wK=LXSzKAjU_0?eY<*!Iv%-hniBA{#NVpzL|oC*v! zc)5GKH)uH&HjAbMv46qWW~Iu4R~?k&5E9z0D#ihX?h2k$>I=WJ__Hpj4t_zG4nqjI zS>*zqMIh}kYGMjFH?T3kcGvIKt6sd2fODr2Qim-D{Yi+NCWaAMu`gX}L2E9REkV4o z?N!On?PMWDCE<4I-r~baEwEAm)xEc#Jcmb$!;qq$$rG}C==%Z!@Xec5ucP{g zdGqR<8zIlTXizci$1(%N#CIs;>J^kfNKk-F$Y1Io!_kGs3k?FG;=mr!%0DK!e-|V- ztLW7mH$sy+S%QD!L*oJ$qM=PdAjs$TZsN9fbL$8Ex7yQ<#gOoHm6%(I%h%9YN|!N& zv7A7L5&dw)XVfbcBS+?M#DV6M)MB_HB&U`%-g_t`g8{LC6MWqKZyI zaZ1WCUKNpiLnmN2udQix|2u$F+?)&E_roaFPaG3M+kX*}zMB0EmxR9w4`;ynRe7>~ zyR)y)%EV*|x6Emhc!;An1rCiF7kJ*?_kB?P5NVux{yvBe-YKksLc|&{H!Zshf2UMi+8Wcnyya-0g)iHw34V3MIZrg;N|C)(YWY_WCIQ_ri*Lh zrk`23)B16K#zaPrti-!Eg{1=k#n;FChkpB<>ivYMD19wnpAQjozoC%;(GP7cCRu0+ zUEp>B!@IsdTT~>Ds}gE!RUkHsjlBkdm6VK@hUO_mZB^Y^y_JalF{+S&N&7A?as&ln zgK~Q8*w=uA91$l>7n^1+yvsKnt|+P9dWyA~F(jFvRc&1fxsBtqMzh(F*Ge^o5Y+aC46~ z#r*s4U%$pR$J9uHSZ?IS0UWw63zT68XO0XO8}xYQxBwL=7XPnf8o{Duqmpa#+31V9gv zp|h7~j@tF>rKr;u7FpP#3ky_2apt;g7hw2?a0RCVrs-@9Bg%@3 ziZ7~PQ)8pR;llt$arh(oHNX3HY3W8=TjZxt#J>#Al3m`d6Otu1XU^UxO2w-@F-ao@ zXq-Kmjtbxt-Y-43UsIC+npgB*Xfd=jA8TuAiL%gW)(R@uBc=^KpDGJrvF5L{T|n1M z2EWqHrH7COAuhV7Cr7vFzoBFZ6fvQJVp#pTi?A9(!zwb?mL5bAcHR~)iSnD7pB{PH z7{YIW3ePF*4!qyQ1V;LO9#I;>$v3U1D2xiafs{ZuM!y=q1}=Dr=P1F`$zx;QKPHC1 z$2$|9<#bW#uJR1LZQN9Y4b36RHwcd%#FPmj4T#qPeQkGbdHL4qA+Q!``}eNSSzq|9 zzaev)Kq#jKl7hEdxSI!$gvj)K7jly~BpMTOt9@0^cRYuj9Gl+a12y$QX3IA@1g8_t zflhPzf!8$MVB?4G?JvO6xi8d&ITsitAgKoNrpOXiJ-oWU&dkKb8BF;h1O;$*z`78p zFmNr@nBc))WIUl}V(djjj0iqZ&PH#T%&wgEuY*k&kMtvMn=Df=E<-_^{Jyu3VFzJ@ znOX2@SZUfVW8)Dt5NRQlAENM>F@Zy~Wr;b?@|gCOE0aT>2sp6@H1qoP#(L3nP^(Qb zILnV=S%hmp3@yrQ+~h}LleHf^9%kJDOF_8@Ve05k!kjVk7eLcM`ay9MZ~G2lly~n~ zj4rf%#Dof91{mzCAElyk%{Cb1@aKpEejO5yTKf9nyjOW|B||5kz^}vNw>+MLWVlLP zH|VIlUHsz3&x(iMm-3kjEk{^cW5>tUh=V^%RHfP5+*|;a$}9{70$D}-7S^!^l*>xh zhw%Fj8C=5lx5iG&ddt(EOZszR5sZZXD#`q4bP4CU;(7dr{#(K!DLK*<%Jz*Q0w zR$Z&h0@4S`2m#@tR3QtQC_CT_H|z+6{$8k3kcIwG+6ob)CfWqTx<) z1t>{OjFYM=pkR;~@QoTSn+b;xPg#Cs901=&R9^=W+b!T4fFG2V zcM%Ah9F?SmjSCB2){s8grZF4HZr0h>t~~5JV+q4q#iypzi!S%XlXuo z?i^HQ*9;8afIKN3#G19oMtLKi3Fp|*j~~9Jy@o;fyFVuj{eZq^B|nnY<2sqa>HRTOvM(lan7@5MA^9ZKS%ONg>-wP9Si}d+n^4RYX<|bm=${ zFjkDN4B+^XlqvxPzp^pJ-vAVEjnZ!e#A#4PlqMBDunA49P9T~W1!jA z;d^`*Q_bAU3b=uCcQriUrltZ6OoxAV`QiNz4JFYYMfn)_#;3KJ36tCEdVkj+su;pc zEmYWYj|x=Mo{b!IaJaw_mWY8PZ@p`c@k!+McM;^Z$tal#{n7vIf@;M!o$RMwSQZ4#IAg8jeZ|Hfk3g7`0IAVD~b!05)*R_>(?Qnz-SMVRad1r zz!SVYFZJBJIOnk&;gGdcA`l2ESm4Qe_*J34zO|ktrQb}pRWX1=&5h=T{JWXCIa(Pi z=A?aaB=`18q4|G@SUgWNY^|1yOUOvl)^>t{50YBazJZRKfY36B1rr?*tK>1w@si#x z#Qg-C9{mBsX)=7Z-MT*rEr+0${ELej&>7NC{dx3=3RgX0s=ephjS7{Tb_|d?l?2r> za5JcL4JIOi2e6yZ5d?Gy4%YY?T-!kGKgcYvRR6GNmkyw%q{J0G)2qZp1o&SR3tr)B z8Dv;B+mc6^*;&Q|)-qtgrr4yY~R^pzLErlGqB(zuq&8ZY(Mt;$#5e*F4X^5MgLqCR|9 zolQ+wuE%%91YoPecc$o1TvDEjX@meV)OPF-ETCaZ+?WM%f$rtYm7~iz4nf8SL))FG zAoV0E>CKz+q7NUQwOqz;J8Za28U$rdqaD3JsGZD;2+3T){h7pAwVDW63L9Srd#P;P)S4f-Pt zQ=a_iFfPA*i3>$UW{ZJkp&ndFIL-9+U1=t6;?2uL=fVGg10PhF`1_c^GhrNnd;DY~ z2Nt-?%6{By5wW6&^l`*;!lgSO+(f<0dw6E%#`WtLmgHenalr26*b6>?s=s94ukMdf z#fXY7!YDOx2V;-DlM`Hi!ijeG$7W~Q*^}g}{_oG2;Q8&^)l0l(;kKHTpAlk)aZJrG zFI_~gPgRvy{M2uv@EKvglsiZWo`*g0{EeVv`}4;Uw$Ta(pQax-J}@F;wF`{!Uw!P2 z#6&i<@0FrrVE~Ejp{3iD<|Ysv?h!wsn8WG*fdL!bgXipJdnz749j^MFe^Lfs5|Oo- zLy_`_a*c~7qkZzQJe09tJZ)Rd#0(6QFmnx4{%2qS%Z{ z!>bb&n*}#0hy5}xK|xqeQ1IGGP`#RSJr6NY()9S-^{-zC=xgAFyq0SJY}KY5==ZQF zyR9T7tMQkcRcT4?Csd>%Apx`MNFeSxu)KAv`HmwmKmV`kY2Shl=2@h&garQq;U6xF z_8~x!_?`RMJvP9xav}=H)(4=$yZ7%ASh#R62F)2r6Z60DjAiX%mnFrXB^b^H&=FD* zOZL6LKl?1L%0q4-$Q_?PtpnC`?e9c~CnqC8gY{qENEu_+3#m8%b^czWoymQl-#30Nc zI#~i4TUc;#O@V3MK6EA1(+r0WUHpRXtA)1$EsZjA3-XGJaP!67&CjU5=mplAbKw6( zzTO30M`YQ+uclw-8XG@MASA!?WD+C<>2P@_J?Y8xMx@Kw+5I?K@(fzJ^6e9C`L8fZ;_eQ$n4v}v z0-=xu6@q=}vzwU6WsqderY(D1psk`iC1e9R7) zT!Op?1|MACMB1l=&4Sp3JC5SGQPg9bfZqa+n3`IRcuXem$i-s8?l;EwWu6+q^n`y{ zxYq=&3;0Z2(Li<}!T?AdG(9l3ssDReD#Qh5d?mvobieq2o(FJk8YZN=zsvBYk1s82ZP_NjI3FGPnTH4tq5&SO=jWAe_M&tIgqotafK7_7W^#DDA@PQrM zSN;s-+UgmL_PqYp^NUhfuV3$*zXd!*R(1eqwZaLhM53(^u4qtxcyXe5e>jcr5A zgcw`W2m}pBg@toQEfF+=>!qshw317INh%-u^{al^_T0bUAwc{cFA(^ZmlqKufEi)1 z(y6wl2B@^Pxw(Sw_D@Xy$Bw?- ztAC~s5Wh#oEb$eF17aF1d*bw<8?1Nig`XM*&s)t9^M$k_kXK5dr+Vm+g2d+jtPp#B zXoYx|97Y4=^xz`y@eA9AJzwT#-4a;rS6NwmCEg?={h{0 zAEgR{=lb>dT4O+)a9{Scw8%qI;Pbxd{P_nn!^4$o!uTfg#~Be~W%QNAbH-ae10Ym^ z$M)8t>rqMgW5B`7E9o$P32k}XPvHDoT15#7{g^l#4x*`XS0bVo|NF^iQ{bo?u_Ec- zmRRyg@57_j&}H&t2J4M;4ET!49(0i9{3nbw2%a-P2R`atmU^sx`7%8tW1&s|I-mh+ z7h!A)Jz`~}Lxj^6P0goB8-ZnC4n~TpnHiKu@`N}X8DhEQ)PyDMGPIK4P`iiKxlf)X zMi-%iS0!M8-tZ&#bW5n@L?R6ucpy!*ba+P5grN~lu4VluoL5XA0)$#g&`jJzC5u*A~=(TQIK%JWZT}_+WpQ>slM~< z&Wa!Qxak~1A7lzI!Z0Ts6C{CYjPQ_H=2#&|EQEU+uIL2ydiId&;pZ6{^|k#7lY_dh zhMf-op)RV9d?KfkAG}9~Kx@2r?M9m5*vcPFUI3pFcZuPjiJ2KDJT5*;{D2&`28SM! zH6UM)lXdGsk|pRasgH@Z#)vXQu&Kw_Bz`alx&{UsRXikk0{?m$ZcfgWtkai>Eb7IJ zFlJo6s*csAtBY8+4;YluTH^{NfCR9!Vn1JluL)9K5RCvesK@A_(SrA z9fVZhrXPy!^7x;>&t;$3jsKJ|Cq?Y*h<{Gt0}}txVFdp75C6~oi@zSvxVWC&T>OqI PP9UhNs4M3v8hZU7CEP_t From 24e3a38e93df9ff181fe7ee4810f5e996c3e48e7 Mon Sep 17 00:00:00 2001 From: Sascha Heimann Date: Mon, 6 Oct 2025 08:05:03 +0200 Subject: [PATCH 10/36] add: added new example apllication to all example.md --- content/v3/de/examples.md | 1 + content/v3/en/examples.md | 1 + content/v3/es/examples.md | 1 + content/v3/fr/examples.md | 1 + content/v3/id/examples.md | 1 + content/v3/ja/examples.md | 1 + content/v3/ko/examples.md | 1 + content/v3/lv/examples.md | 1 + content/v3/pt/examples.md | 1 + content/v3/ru/examples.md | 1 + content/v3/uk/examples.md | 1 + content/v3/zh/examples.md | 1 + 12 files changed, 12 insertions(+) diff --git a/content/v3/de/examples.md b/content/v3/de/examples.md index 91cf879a..f80198f0 100644 --- a/content/v3/de/examples.md +++ b/content/v3/de/examples.md @@ -29,6 +29,7 @@ Während diese nicht offiziell vom Flight-Team gesponsert werden, könnten diese - [Generisches Content-Management-System (mit....sehr wenig Dokumentation)](https://github.com/recepuncu/cms) - [Ein kleines PHP-Framework basierend auf Flight und medoo.](https://github.com/ycrao/tinyme) - [Beispiel MVC Anwendung](https://github.com/paddypei/Flight-MVC) +- [Prduktionsreifes Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Produktionsreifes Authentifizierungsframework, das Ihnen wochenlange Entwicklungszeit erspart. Bietet Sicherheit auf Unternehmensniveau: 2FA/TOTP, LDAP-Integration, Azure SSO, intelligente Ratenbegrenzung, Session-Fingerprinting, Brute-Force-Schutz, Sicherheitsanalyse-Dashboard, umfassende Audit-Protokollierung und granulare rollenbasierte Zugriffskontrolle. ## Möchten Sie Ihr eigenes Beispiel teilen? diff --git a/content/v3/en/examples.md b/content/v3/en/examples.md index 6f52d304..f997231f 100644 --- a/content/v3/en/examples.md +++ b/content/v3/en/examples.md @@ -29,6 +29,7 @@ While these are not officially sponsored by the Flight Team, these could give yo - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Production-ready authentication framework that saves you weeks of development. Features enterprise-grade security: 2FA/TOTP, LDAP integration, Azure SSO, intelligent rate limiting, session fingerprinting, brute-force protection, security analytics dashboard, comprehensive audit logging, and granular role-based access control. ## Want to Share Your Own Example? diff --git a/content/v3/es/examples.md b/content/v3/es/examples.md index 54375c07..0cc2555e 100644 --- a/content/v3/es/examples.md +++ b/content/v3/es/examples.md @@ -29,6 +29,7 @@ Aunque estos no están oficialmente patrocinados por el equipo de Flight, ¡podr - [Sistema de Gestión de Contenidos Genérico (con....muy poca documentación)](https://github.com/recepuncu/cms) - [Un pequeño marco PHP basado en Flight y medoo.](https://github.com/ycrao/tinyme) - [Ejemplo de Aplicación MVC](https://github.com/paddypei/Flight-MVC) +- [Modelo de vuelo listo para producción](https://github.com/madcoda9000/SecStore) - Marco de autenticación listo para producción que le ahorra semanas de desarrollo. Ofrece seguridad de nivel empresarial: 2FA/TOTP, integración con LDAP, SSO de Azure, limitación de velocidad inteligente, huellas digitales de sesión, protección contra ataques de fuerza bruta, panel de análisis de seguridad, registro de auditoría completo y control de acceso granular basado en roles. ## ¿Quieres compartir tu propio ejemplo? diff --git a/content/v3/fr/examples.md b/content/v3/fr/examples.md index f7adaaa4..bf40d6c7 100644 --- a/content/v3/fr/examples.md +++ b/content/v3/fr/examples.md @@ -29,6 +29,7 @@ Bien que ceux-ci ne soient pas officiellement sponsorisés par l'équipe Flight, - [Système de Gestion de Contenu Générique (avec....très peu de documentation)](https://github.com/recepuncu/cms) - [Un petit framework php basé sur Flight et medoo.](https://github.com/ycrao/tinyme) - [Application MVC Exemple](https://github.com/paddypei/Flight-MVC) +- [Préparation de vol prête pour la production](https://github.com/madcoda9000/SecStore) - Framework d'authentification prêt pour la production qui vous fait gagner des semaines de développement. Sécurité de niveau entreprise : 2FA/TOTP, intégration LDAP, SSO Azure, limitation intelligente du débit, empreinte digitale de session, protection contre les attaques par force brute, tableau de bord d'analyse de sécurité, journalisation d'audit complète et contrôle d'accès précis basé sur les rôles. ## Voulez-vous partager votre propre exemple ? diff --git a/content/v3/id/examples.md b/content/v3/id/examples.md index 80a011b5..42ee7d65 100644 --- a/content/v3/id/examples.md +++ b/content/v3/id/examples.md @@ -29,6 +29,7 @@ Meskipun ini tidak secara resmi disponsori oleh Tim Flight, ini bisa memberi And - [Sistem Manajemen Konten Generik (dengan....sangat sedikit dokumentasi)](https://github.com/recepuncu/cms) - [Framework php kecil yang berbasis pada Flight dan medoo.](https://github.com/ycrao/tinyme) - [Contoh Aplikasi MVC](https://github.com/paddypei/Flight-MVC) +- [Flight Boilerplate Siap Produksi](https://github.com/madcoda9000/SecStore) - Kerangka kerja autentikasi siap produksi yang menghemat waktu pengembangan Anda selama berminggu-minggu. Dilengkapi keamanan tingkat perusahaan: 2FA/TOTP, integrasi LDAP, Azure SSO, pembatasan kecepatan cerdas, sidik jari sesi, perlindungan brute-force, dasbor analitik keamanan, pencatatan audit komprehensif, dan kontrol akses berbasis peran yang terperinci. ## Ingin Membagikan Contoh Anda Sendiri? diff --git a/content/v3/ja/examples.md b/content/v3/ja/examples.md index 3a6220b3..5776d6d2 100644 --- a/content/v3/ja/examples.md +++ b/content/v3/ja/examples.md @@ -29,6 +29,7 @@ - [一般的なコンテンツ管理システム (非常に少ないドキュメント付き)](https://github.com/recepuncu/cms) - [Flightとmedooに基づく小さなphpフレームワーク。](https://github.com/ycrao/tinyme) - [例のMVCアプリケーション](https://github.com/paddypei/Flight-MVC) +- [本番環境対応のフライトボイラープレート](https://github.com/madcoda9000/SecStore) - 数週間の開発期間を短縮する、本番環境対応の認証フレームワークです。エンタープライズグレードのセキュリティ機能を備えています。2FA/TOTP、LDAP統合、Azure SSO、インテリジェントなレート制限、セッションフィンガープリンティング、ブルートフォース攻撃対策、セキュリティ分析ダッシュボード、包括的な監査ログ、きめ細かなロールベースのアクセス制御などを備えています。 ## 自分の例を共有したいですか? diff --git a/content/v3/ko/examples.md b/content/v3/ko/examples.md index 78ca0c6e..9f7f6dfc 100644 --- a/content/v3/ko/examples.md +++ b/content/v3/ko/examples.md @@ -29,6 +29,7 @@ - [일반 콘텐츠 관리 시스템 (문서가 거의 없음)](https://github.com/recepuncu/cms) - [Flight와 medoo를 기반으로 한 작은 php 프레임워크.](https://github.com/ycrao/tinyme) - [예제 MVC 응용 프로그램](https://github.com/paddypei/Flight-MVC) +- [프로덕션 준비 완료 Flight 보일러플레이트](https://github.com/madcoda9000/SecStore) - 몇 주에 달하는 개발 시간을 절약해 주는 프로덕션 준비 인증 프레임워크입니다. 엔터프라이즈급 보안 기능을 제공합니다: 2FA/TOTP, LDAP 통합, Azure SSO, 지능형 속도 제한, 세션 지문 인식, 무차별 대입 공격 방어, 보안 분석 대시보드, 포괄적인 감사 로깅, 세분화된 역할 기반 접근 제어. ## 자신의 예제를 공유하고 싶으신가요? diff --git a/content/v3/lv/examples.md b/content/v3/lv/examples.md index 75ce5beb..5cb30234 100644 --- a/content/v3/lv/examples.md +++ b/content/v3/lv/examples.md @@ -29,6 +29,7 @@ Lai gan šie nav oficiāli atbalstīti no Flight komandas, tie var dot jums idej - [Vispārējs satura pārvaldības sistēma (ar....ļoti maz dokumentācijas)](https://github.com/recepuncu/cms) - [Mazs php framework, kas balstīts uz Flight un medoo.](https://github.com/ycrao/tinyme) - [Piemēru MVC lietojumprogramma](https://github.com/paddypei/Flight-MVC) +— [Ražošanai gatava izmēģinājuma versija](https://github.com/madcoda9000/SecStore) — Ražošanai gatava autentifikācijas sistēma, kas ietaupa jūsu izstrādes laiku nedēļām. Piedāvā uzņēmuma līmeņa drošību: 2FA/TOTP, LDAP integrāciju, Azure SSO, viedu ātruma ierobežošanu, sesijas pirkstu nospiedumu noņemšanu, brutālas piespēles aizsardzību, drošības analītikas informācijas paneli, visaptverošu audita reģistrēšanu un detalizētu uz lomām balstītu piekļuves kontroli. ## Vēlaties dalīties ar savu piemēru? diff --git a/content/v3/pt/examples.md b/content/v3/pt/examples.md index fac1cb76..b0002f04 100644 --- a/content/v3/pt/examples.md +++ b/content/v3/pt/examples.md @@ -29,6 +29,7 @@ Embora esses não sejam oficialmente patrocinados pela equipe Flight, eles podem - [Sistema de Gerenciamento de Conteúdo Genérico (com....muito pouca documentação)](https://github.com/recepuncu/cms) - [Um pequeno framework php baseado no Flight e medoo.](https://github.com/ycrao/tinyme) - [Exemplo de Aplicativo MVC](https://github.com/paddypei/Flight-MVC) +- [Produção pronta para produção](https://github.com/madcoda9000/SecStore) - Estrutura de autenticação pronta para produção que poupa semanas de desenvolvimento. Oferece segurança de nível empresarial: 2FA/TOTP, integração com LDAP, SSO do Azure, limitação de taxa inteligente, impressão digital de sessão, proteção contra força bruta, painel de análise de segurança, registo de auditoria abrangente e controlo de acesso granular baseado em funções. ## Quer Compartilhar Seu Próprio Exemplo? diff --git a/content/v3/ru/examples.md b/content/v3/ru/examples.md index 7120e8e1..9dcd2b58 100644 --- a/content/v3/ru/examples.md +++ b/content/v3/ru/examples.md @@ -29,6 +29,7 @@ - [Универсальная система управления контентом (с....очень мало документации)](https://github.com/recepuncu/cms) - [Маленький php фреймворк на основе Flight и medoo.](https://github.com/ycrao/tinyme) - [Пример MVC приложения](https://github.com/paddypei/Flight-MVC) +- [Готовый шаблон Flight Boilerplate](https://github.com/madcoda9000/SecStore) — готовый к использованию фреймворк аутентификации, который сэкономит вам недели разработки. Обеспечивает безопасность корпоративного уровня: 2FA/TOTP, интеграция с LDAP, единый вход в Azure, интеллектуальное ограничение скорости, фингерпринтинг сеансов, защита от подбора паролей, панель аналитики безопасности, комплексное ведение журнала аудита и детальное управление доступом на основе ролей. ## Хотите поделиться своим примером? diff --git a/content/v3/uk/examples.md b/content/v3/uk/examples.md index d7b5a056..a81d45c4 100644 --- a/content/v3/uk/examples.md +++ b/content/v3/uk/examples.md @@ -29,6 +29,7 @@ - [Універсальна система управління контентом (з....дуже малою документацією)](https://github.com/recepuncu/cms) - [Маленький php фреймворк на основі Flight та medoo.](https://github.com/ycrao/tinyme) - [Приклад MVC-додатку](https://github.com/paddypei/Flight-MVC) +- [Продукційно готовий шаблон Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Готовий до використання фреймворк автентифікації, який заощаджує вам тижні розробки. Забезпечує безпеку корпоративного рівня: 2FA/TOTP, інтеграцію LDAP, єдиний вхід Azure, інтелектуальне обмеження швидкості, відбитки сеансів, захист методом повного перебору, панель інструментів аналітики безпеки, комплексне ведення журналу аудиту та детальний контроль доступу на основі ролей. ## Хочете поділитися власним прикладом? diff --git a/content/v3/zh/examples.md b/content/v3/zh/examples.md index 2507af25..ff9e24c7 100644 --- a/content/v3/zh/examples.md +++ b/content/v3/zh/examples.md @@ -29,6 +29,7 @@ - [通用内容管理系统(带有……非常少的文档)](https://github.com/recepuncu/cms) - [基于 Flight 和 medoo 的小型 PHP 框架。](https://github.com/ycrao/tinyme) - [示例 MVC 应用](https://github.com/paddypei/Flight-MVC) +- [生產就緒的 Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 一款生產就緒的驗證框架,可為您節省數週的開發時間。它具備企業級安全性:2FA/TOTP、LDAP 整合、Azure SSO、智慧限速、會話指紋辨識、暴力破解保護、安全分析儀表板、全面的稽核日誌記錄以及基於角色的細粒度存取控制。 ## 想要分享您自己的示例吗? From 2849febb267f28dc1acbd572ea83efaab154a678 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Mon, 6 Oct 2025 12:52:56 +0100 Subject: [PATCH 11/36] added new example --- content/v3/en/examples.md | 1 + 1 file changed, 1 insertion(+) diff --git a/content/v3/en/examples.md b/content/v3/en/examples.md index f997231f..6374ae7d 100644 --- a/content/v3/en/examples.md +++ b/content/v3/en/examples.md @@ -16,6 +16,7 @@ Community contributed examples: While these are not officially sponsored by the Flight Team, these could give you ideas on how to structure your own projects that are built with Flight! +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental is a single-page, mobile-friendly car rental web application built with PHP (FlightPHP), JavaScript, and MySQL. It supports user registration, browsing, and booking cars, while admins can manage cars, users, and bookings. The app features a REST API, JWT authentication, and a responsive design for a modern rental experience. - [Decay](https://github.com/boxybird/decay) - Flight v3 with HTMX and SleekDB all about zombies! ([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 with Middleware, Controllers, Active Record, and Latte. - [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Simple CRUD API project using the Flight framework, which provides a basic structure for new users to quickly set up a PHP application with CRUD operations and database connectivity. The project demonstrates how to use Flight for RESTful API development, making it an ideal learning tool for beginners and a useful starter kit for more experienced developers. From b50623632ef6aae885c7733525ddb79d6a67b391 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Mon, 6 Oct 2025 18:39:10 +0100 Subject: [PATCH 12/36] added async and retranslated --- content/v3/de/awesome-plugins/async.md | 212 +++++++++++++++ .../v3/de/awesome-plugins/awesome_plugins.md | 58 ++-- content/v3/de/examples.md | 57 ++-- content/v3/de/learn/requests.md | 98 +++---- content/v3/de/learn/routing.md | 164 ++++++------ content/v3/en/awesome-plugins/async.md | 212 +++++++++++++++ .../v3/en/awesome-plugins/awesome_plugins.md | 6 + content/v3/es/awesome-plugins/async.md | 212 +++++++++++++++ .../v3/es/awesome-plugins/awesome_plugins.md | 44 +-- content/v3/es/examples.md | 47 ++-- content/v3/es/learn/requests.md | 100 +++---- content/v3/es/learn/routing.md | 68 ++--- content/v3/fr/awesome-plugins/async.md | 212 +++++++++++++++ .../v3/fr/awesome-plugins/awesome_plugins.md | 36 +-- content/v3/fr/examples.md | 37 +-- content/v3/fr/learn/requests.md | 70 ++--- content/v3/fr/learn/routing.md | 96 +++---- content/v3/id/awesome-plugins/async.md | 212 +++++++++++++++ .../v3/id/awesome-plugins/awesome_plugins.md | 58 ++-- content/v3/id/examples.md | 35 +-- content/v3/id/learn/requests.md | 45 ++-- content/v3/id/learn/routing.md | 154 +++++------ content/v3/ja/awesome-plugins/async.md | 212 +++++++++++++++ .../v3/ja/awesome-plugins/awesome_plugins.md | 68 ++--- content/v3/ja/examples.md | 49 ++-- content/v3/ja/learn/requests.md | 75 +++--- content/v3/ja/learn/routing.md | 136 +++++----- content/v3/ko/awesome-plugins/async.md | 212 +++++++++++++++ .../v3/ko/awesome-plugins/awesome_plugins.md | 46 ++-- content/v3/ko/examples.md | 63 ++--- content/v3/ko/learn/requests.md | 126 +++++---- content/v3/ko/learn/routing.md | 161 +++++------ content/v3/lv/awesome-plugins/async.md | 212 +++++++++++++++ .../v3/lv/awesome-plugins/awesome_plugins.md | 66 ++--- content/v3/lv/examples.md | 55 ++-- content/v3/lv/learn/requests.md | 84 +++--- content/v3/lv/learn/routing.md | 242 +++++++++-------- content/v3/pt/awesome-plugins/async.md | 212 +++++++++++++++ .../v3/pt/awesome-plugins/awesome_plugins.md | 46 ++-- content/v3/pt/examples.md | 47 ++-- content/v3/pt/learn/requests.md | 40 +-- content/v3/pt/learn/routing.md | 234 ++++++++-------- content/v3/ru/awesome-plugins/async.md | 212 +++++++++++++++ .../v3/ru/awesome-plugins/awesome_plugins.md | 56 ++-- content/v3/ru/examples.md | 55 ++-- content/v3/ru/learn/requests.md | 66 ++--- content/v3/ru/learn/routing.md | 250 +++++++++--------- content/v3/uk/awesome-plugins/async.md | 212 +++++++++++++++ .../v3/uk/awesome-plugins/awesome_plugins.md | 74 +++--- content/v3/uk/examples.md | 61 ++--- content/v3/uk/learn/requests.md | 26 +- content/v3/uk/learn/routing.md | 123 +++++---- content/v3/zh/awesome-plugins/async.md | 212 +++++++++++++++ .../v3/zh/awesome-plugins/awesome_plugins.md | 50 ++-- content/v3/zh/examples.md | 57 ++-- content/v3/zh/learn/requests.md | 72 ++--- content/v3/zh/learn/routing.md | 104 ++++---- 57 files changed, 4436 insertions(+), 1813 deletions(-) create mode 100644 content/v3/de/awesome-plugins/async.md create mode 100644 content/v3/en/awesome-plugins/async.md create mode 100644 content/v3/es/awesome-plugins/async.md create mode 100644 content/v3/fr/awesome-plugins/async.md create mode 100644 content/v3/id/awesome-plugins/async.md create mode 100644 content/v3/ja/awesome-plugins/async.md create mode 100644 content/v3/ko/awesome-plugins/async.md create mode 100644 content/v3/lv/awesome-plugins/async.md create mode 100644 content/v3/pt/awesome-plugins/async.md create mode 100644 content/v3/ru/awesome-plugins/async.md create mode 100644 content/v3/uk/awesome-plugins/async.md create mode 100644 content/v3/zh/awesome-plugins/async.md diff --git a/content/v3/de/awesome-plugins/async.md b/content/v3/de/awesome-plugins/async.md new file mode 100644 index 00000000..e3c9ef4f --- /dev/null +++ b/content/v3/de/awesome-plugins/async.md @@ -0,0 +1,212 @@ +# Async + +Async ist ein kleines Paket für das Flight-Framework, das es Ihnen ermöglicht, Ihre Flight-Apps in asynchronen Servern und Runtimes wie Swoole, AdapterMan, ReactPHP, Amp, RoadRunner, Workerman usw. auszuführen. Out of the box enthält es Adapter für Swoole und AdapterMan. + +Das Ziel: Entwickeln und Debuggen mit PHP-FPM (oder dem integrierten Server) und Wechseln zu Swoole (oder einem anderen asynchronen Treiber) für die Produktion mit minimalen Änderungen. + +## Requirements + +- PHP 7.4 oder höher +- Flight-Framework 3.16.1 oder höher +- [Swoole-Erweiterung](https://www.openswoole.com) + +## Installation + +Installieren Sie es über Composer: + +```bash +composer require flightphp/async +``` + +Falls Sie mit Swoole ausführen möchten, installieren Sie die Erweiterung: + +```bash +# using pecl +pecl install swoole +# or openswoole +pecl install openswoole + +# or with a package manager (Debian/Ubuntu example) +sudo apt-get install php-swoole +``` + +## Quick Swoole example + +Unten ist eine minimale Einrichtung zu sehen, die zeigt, wie Sie sowohl PHP-FPM (oder den integrierten Server) als auch Swoole mit demselben Codebase unterstützen können. + +Dateien, die Sie in Ihrem Projekt benötigen: + +- index.php +- swoole_server.php +- SwooleServerDriver.php + +### index.php + +Diese Datei ist ein einfacher Schalter, der die App im PHP-Modus für die Entwicklung erzwingt. + +```php +// index.php +route('/', function() use ($app) { + $app->json(['hello' => 'world']); +}); + +if (!defined('NOT_SWOOLE')) { + // Require the SwooleServerDriver class when running in Swoole mode. + require_once __DIR__ . '/SwooleServerDriver.php'; + + Swoole\Runtime::enableCoroutine(); + $Swoole_Server = new SwooleServerDriver('127.0.0.1', 9501, $app); + $Swoole_Server->start(); +} else { + $app->start(); +} +``` + +### SwooleServerDriver.php + +Ein knapper Treiber, der zeigt, wie man Swoole-Anfragen in Flight über die AsyncBridge und die Swoole-Adapter überbrückt. + +```php +// SwooleServerDriver.php +Swoole = new SwooleServer($host, $port); + $this->app = $app; + + $this->setDefault(); + $this->bindWorkerEvents(); + $this->bindHttpEvent(); + } + + protected function setDefault() { + $this->Swoole->set([ + 'daemonize' => false, + 'dispatch_mode' => 1, + 'max_request' => 8000, + 'open_tcp_nodelay' => true, + 'reload_async' => true, + 'max_wait_time' => 60, + 'enable_reuse_port' => true, + 'enable_coroutine' => true, + 'http_compression' => false, + 'enable_static_handler' => true, + 'document_root' => __DIR__, + 'static_handler_locations' => ['/css', '/js', '/images', '/.well-known'], + 'buffer_output_size' => 4 * 1024 * 1024, + 'worker_num' => 4, + ]); + + $app = $this->app; + $app->map('stop', function (?int $code = null) use ($app) { + if ($code !== null) { + $app->response()->status($code); + } + }); + } + + protected function bindHttpEvent() { + $app = $this->app; + $AsyncBridge = new AsyncBridge($app); + + $this->Swoole->on('Start', function(SwooleServer $server) { + echo "Swoole http server is started at http://127.0.0.1:9501\n"; + }); + + $this->Swoole->on('Request', function (SwooleRequest $request, SwooleResponse $response) use ($AsyncBridge) { + $SwooleAsyncRequest = new SwooleAsyncRequest($request); + $SwooleAsyncResponse = new SwooleAsyncResponse($response); + + $AsyncBridge->processRequest($SwooleAsyncRequest, $SwooleAsyncResponse); + + $response->end(); + gc_collect_cycles(); + }); + } + + protected function bindWorkerEvents() { + $createPools = function() { + // create worker-specific connection pools here + }; + $closePools = function() { + // close pools / cleanup here + }; + $this->Swoole->on('WorkerStart', $createPools); + $this->Swoole->on('WorkerStop', $closePools); + $this->Swoole->on('WorkerError', $closePools); + } + + public function start() { + $this->Swoole->start(); + } +} +``` + +## Running the server + +- Entwicklung (PHP integrierter Server / PHP-FPM): + - php -S localhost:8000 (oder fügen Sie -t public/ hinzu, wenn Ihr index in public/ liegt) +- Produktion (Swoole): + - php swoole_server.php + +Tipp: Für die Produktion verwenden Sie einen Reverse-Proxy (Nginx) vor Swoole, um TLS, statische Dateien und Lastverteilung zu handhaben. + +## Configuration notes + +Der Swoole-Treiber stellt mehrere Konfigurationsoptionen zur Verfügung: +- worker_num: Anzahl der Worker-Prozesse +- max_request: Anfragen pro Worker vor dem Neustart +- enable_coroutine: Coroutines für Parallelität verwenden +- buffer_output_size: Ausgabepuffer-Größe + +Passen Sie diese an Ihre Host-Ressourcen und Traffic-Muster an. + +## Error handling + +AsyncBridge übersetzt Flight-Fehler in korrekte HTTP-Antworten. Sie können auch fehlerbehandlung auf Routenebene hinzufügen: + +```php +$app->route('/*', function() use ($app) { + try { + // route logic + } catch (Exception $e) { + $app->response()->status(500); + $app->json(['error' => $e->getMessage()]); + } +}); +``` + +## AdapterMan and other runtimes + +[AdapterMan](https://github.com/joanhey/adapterman) wird als alternativer Runtime-Adapter unterstützt. Das Paket ist so konzipiert, dass es anpassbar ist – das Hinzufügen oder Verwenden anderer Adapter folgt im Allgemeinen demselben Muster: Konvertieren Sie die Server-Anfrage/Antwort in die Flight-Anfrage/Antwort über die AsyncBridge und die runtime-spezifischen Adapter. \ No newline at end of file diff --git a/content/v3/de/awesome-plugins/awesome_plugins.md b/content/v3/de/awesome-plugins/awesome_plugins.md index a5d96790..e8e1cc1c 100644 --- a/content/v3/de/awesome-plugins/awesome_plugins.md +++ b/content/v3/de/awesome-plugins/awesome_plugins.md @@ -1,30 +1,36 @@ # Tolle 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, und andere sind Mikro-/Lite-Bibliotheken, die Ihnen den Einstieg erleichtern. +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, und andere sind Micro/Lite-Bibliotheken, um Ihnen den Einstieg zu erleichtern. ## API-Dokumentation -API-Dokumentation ist entscheidend für jede API. Sie hilft Entwicklern zu verstehen, wie sie mit Ihrer API interagieren können und was sie als Rückgabe erwarten können. Es gibt ein paar Tools, die Ihnen helfen, API-Dokumentation für Ihre Flight-Projekte zu generieren. +API-Dokumentation ist entscheidend für jede API. Sie hilft Entwicklern zu verstehen, wie sie mit Ihrer API interagieren können und was sie als Rückgabe erwarten können. Es gibt einige Tools, die Ihnen helfen können, API-Dokumentation für Ihre Flight-Projekte zu generieren. - [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Blog-Beitrag von Daniel Schreiber darüber, wie man die OpenAPI-Spezifikation mit FlightPHP verwendet, um Ihre API mit einem API-First-Ansatz aufzubauen. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ist ein großartiges Tool, um API-Dokumentation für Ihre Flight-Projekte zu generieren. Es ist sehr einfach zu bedienen und kann an Ihre Bedürfnisse angepasst werden. Dies ist die PHP-Bibliothek, die Ihnen hilft, die Swagger-Dokumentation zu generieren. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ist ein großartiges Tool, um API-Dokumentation für Ihre Flight-Projekte zu generieren. Es ist sehr einfach zu verwenden und kann an Ihre Bedürfnisse angepasst werden. Dies ist die PHP-Bibliothek, die Ihnen hilft, die Swagger-Dokumentation zu generieren. -## Anwendungsleistungsüberwachung (APM) +## Application Performance Monitoring (APM) -Anwendungsleistungsüberwachung (APM) ist entscheidend für jede Anwendung. Sie hilft Ihnen zu verstehen, wie Ihre Anwendung performt und wo die Engpässe liegen. Es gibt eine Reihe von APM-Tools, die mit Flight verwendet werden können. -- offiziell [flightphp/apm](/awesome-plugins/apm) - Flight APM ist eine einfache APM-Bibliothek, die verwendet werden kann, um Ihre Flight-Anwendungen zu überwachen. Sie kann verwendet werden, um die Leistung Ihrer Anwendung zu überwachen und Ihnen bei der Identifizierung von Engpässen zu helfen. +Application Performance Monitoring (APM) ist entscheidend für jede Anwendung. Es hilft Ihnen zu verstehen, wie Ihre Anwendung performt und wo die Engpässe liegen. Es gibt eine Reihe von APM-Tools, die mit Flight verwendet werden können. +- offiziell [flightphp/apm](/awesome-plugins/apm) - Flight APM ist eine einfache APM-Bibliothek, die verwendet werden kann, um Ihre Flight-Anwendungen zu überwachen. Sie kann verwendet werden, um die Performance Ihrer Anwendung zu überwachen und Ihnen zu helfen, Engpässe zu identifizieren. + +## Async + +Flight ist bereits ein schnelles Framework, aber es mit einem Turbo-Motor auszustatten macht alles noch spaßiger (und herausfordernder)! + +- [flightphp/async](/awesome-plugins/async) - Offizielle Flight Async-Bibliothek. Diese Bibliothek ist eine einfache Möglichkeit, asynchrone Verarbeitung zu Ihrer Anwendung hinzuzufügen. Sie verwendet Swoole/Openswoole im Hintergrund, um eine einfache und effektive Möglichkeit zu bieten, Aufgaben asynchron auszuführen. ## Autorisierung/Berechtigungen -Autorisierung und Berechtigungen sind entscheidend für jede Anwendung, die Kontrollen benötigt, um festzulegen, wer auf was zugreifen kann. +Autorisierung und Berechtigungen sind entscheidend für jede Anwendung, die Steuerungen benötigt, um festzulegen, wer auf was zugreifen kann. -- offiziell [flightphp/permissions](/awesome-plugins/permissions) - Offizielle Flight-Berechtigungs-Bibliothek. Diese Bibliothek ist eine einfache Möglichkeit, Benutzer- und Anwendungsebenen-Berechtigungen zu Ihrer Anwendung hinzuzufügen. +- offiziell [flightphp/permissions](/awesome-plugins/permissions) - Offizielle Flight Permissions-Bibliothek. Diese Bibliothek ist eine einfache Möglichkeit, Benutzer- und Anwendungsebene-Berechtigungen zu Ihrer Anwendung hinzuzufügen. ## Caching Caching ist eine großartige Möglichkeit, Ihre Anwendung zu beschleunigen. Es gibt eine Reihe von Caching-Bibliotheken, die mit Flight verwendet werden können. -- offiziell [flightphp/cache](/awesome-plugins/php-file-cache) - Leichte, einfache und eigenständige PHP-In-Datei-Caching-Klasse +- offiziell [flightphp/cache](/awesome-plugins/php-file-cache) - Leichte, einfache und eigenständige PHP-in-File-Caching-Klasse ## CLI @@ -40,44 +46,44 @@ Cookies sind eine großartige Möglichkeit, kleine Datenmengen auf der Client-Se ## Debugging -Debugging ist entscheidend, wenn Sie in Ihrer lokalen Umgebung entwickeln. Es gibt ein paar Plugins, die Ihr Debugging-Erlebnis verbessern können. +Debugging ist entscheidend, wenn Sie in Ihrer lokalen Umgebung entwickeln. Es gibt einige Plugins, die Ihr Debugging-Erlebnis verbessern können. -- [tracy/tracy](/awesome-plugins/tracy) - Dies ist ein vollständiges Fehlerbehandlungs-Tool, das mit Flight verwendet werden kann. Es hat eine Reihe von Panels, die Ihnen helfen können, Ihre Anwendung zu debuggen. Es ist auch sehr einfach zu erweitern und eigene Panels hinzuzufügen. -- offiziell [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Wird mit dem [Tracy](/awesome-plugins/tracy) Fehlerbehandlungs-Tool verwendet, fügt dieses Plugin ein paar zusätzliche Panels hinzu, die speziell für das Debugging von Flight-Projekten helfen. +- [tracy/tracy](/awesome-plugins/tracy) - Dies ist ein vollständiges Fehlerbehandlungstool, das mit Flight verwendet werden kann. Es hat eine Reihe von Panels, die Ihnen helfen können, Ihre Anwendung zu debuggen. Es ist auch sehr einfach zu erweitern und eigene Panels hinzuzufügen. +- offiziell [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - In Verbindung mit dem [Tracy](/awesome-plugins/tracy) Fehlerbehandlungstool fügt dieses Plugin einige zusätzliche Panels hinzu, um das Debugging speziell für Flight-Projekte zu erleichtern. ## Datenbanken -Datenbanken sind das Herzstück der meisten Anwendungen. So speichern und rufen Sie Daten ab. Einige Datenbank-Bibliotheken sind einfach Wrapper, um Abfragen zu schreiben, und einige sind vollwertige ORMs. +Datenbanken sind der Kern der meisten Anwendungen. So speichern und rufen Sie Daten ab. Einige Datenbankbibliotheken sind einfach Wrapper, um Abfragen zu schreiben, und einige sind vollwertige ORMs. -- offiziell [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Offizieller Flight-PDO-Wrapper, der zum Kern gehört. Dies ist ein einfacher Wrapper, der den Prozess des Schreibens und Ausführens von Abfragen vereinfacht. Es handelt sich nicht um ein ORM. -- offiziell [flightphp/active-record](/awesome-plugins/active-record) - Offizielles Flight-ActiveRecord-ORM/Mapper. Tolle kleine Bibliothek, um Daten einfach in Ihrer Datenbank abzurufen und zu speichern. +- offiziell [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Offizieller Flight PDO-Wrapper, der zum Kern gehört. Dies ist ein einfacher Wrapper, der den Prozess des Schreibens und Ausführens von Abfragen vereinfacht. Es handelt sich nicht um ein ORM. +- offiziell [flightphp/active-record](/awesome-plugins/active-record) - Offizielles Flight ActiveRecord ORM/Mapper. Tolle kleine Bibliothek, um Daten einfach in Ihrer Datenbank abzurufen und zu speichern. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin, um alle Datenbankänderungen für Ihr Projekt zu verfolgen. ## Verschlüsselung -Verschlüsselung ist entscheidend für jede Anwendung, die sensible Daten speichert. Das Verschlüsseln und Entschlüsseln der Daten ist nicht allzu schwer, aber das ordnungsgemäße Speichern des Verschlüsselungsschlüssels [kann](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [sein](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [schwierig](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Das Wichtigste ist, Ihren Verschlüsselungsschlüssel niemals in einem öffentlichen Verzeichnis zu speichern oder ihn in Ihr Code-Repository zu committen. +Verschlüsselung ist entscheidend für jede Anwendung, die sensible Daten speichert. Das Verschlüsseln und Entschlüsseln der Daten ist nicht besonders schwer, aber das ordnungsgemäße Speichern des Verschlüsselungsschlüssels [kann](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [sein](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [schwierig](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Das Wichtigste ist, Ihren Verschlüsselungsschlüssel niemals in einem öffentlichen Verzeichnis zu speichern oder ihn in Ihr Code-Repository zu committen. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Dies ist eine Bibliothek, die verwendet werden kann, um Daten zu verschlüsseln und zu entschlüsseln. Der Einstieg ist ziemlich einfach, um mit dem Verschlüsseln und Entschlüsseln von Daten zu beginnen. -## Job-Warteschlange +## Job Queue -Job-Warteschlangen sind wirklich hilfreich, um Aufgaben asynchron zu verarbeiten. Das kann das Senden von E-Mails, das Verarbeiten von Bildern oder alles sein, was nicht in Echtzeit erledigt werden muss. +Job-Warteschlangen sind wirklich hilfreich, um Aufgaben asynchron zu verarbeiten. Das kann das Versenden von E-Mails, die Verarbeitung von Bildern oder alles sein, was nicht in Echtzeit erledigt werden muss. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue ist eine Bibliothek, die verwendet werden kann, um Jobs asynchron zu verarbeiten. Sie kann mit beanstalkd, MySQL/MariaDB, SQLite und PostgreSQL verwendet werden. ## Session -Sessions sind für APIs nicht wirklich nützlich, aber beim Aufbau einer Web-Anwendung können Sessions entscheidend für die Aufrechterhaltung von Zuständen und Anmeldeinformationen sein. +Sessions sind für APIs nicht wirklich nützlich, aber beim Aufbau einer Web-Anwendung können Sessions entscheidend für die Aufrechterhaltung des Zustands und Login-Informationen sein. -- offiziell [flightphp/session](/awesome-plugins/session) - Offizielle Flight-Session-Bibliothek. Dies ist eine einfache Session-Bibliothek, die verwendet werden kann, um Session-Daten zu speichern und abzurufen. Sie verwendet die integrierte Session-Behandlung von PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session-Manager (nicht-blockierend, Flash, Segment, Session-Verschlüsselung). Verwendet PHP open_ssl für optionale Verschlüsselung/Entschlüsselung von Session-Daten. +- offiziell [flightphp/session](/awesome-plugins/session) - Offizielle Flight Session-Bibliothek. Dies ist eine einfache Session-Bibliothek, die verwendet werden kann, um Session-Daten zu speichern und abzurufen. Sie verwendet die integrierte Session-Behandlung von PHP. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (nicht-blockierend, Flash, Segment, Session-Verschlüsselung). Verwendet PHP open_ssl für optionale Verschlüsselung/Entschlüsselung von Session-Daten. -## Vorlagen +## Templating -Vorlagen sind das Herzstück jeder Web-Anwendung mit einer Benutzeroberfläche. Es gibt eine Reihe von Vorlagen-Engines, die mit Flight verwendet werden können. +Templating ist der Kern jeder Web-Anwendung mit einer UI. Es gibt eine Reihe von Templating-Engines, die mit Flight verwendet werden können. -- veraltet [flightphp/core View](/learn#views) - Dies ist eine sehr grundlegende Vorlagen-Engine, die zum Kern gehört. Es wird nicht empfohlen, sie zu verwenden, wenn Ihr Projekt mehr als ein paar Seiten hat. -- [latte/latte](/awesome-plugins/latte) - Latte ist eine vollständige Vorlagen-Engine, die sehr einfach zu bedienen ist und sich näher an der PHP-Syntax anfühlt als Twig oder Smarty. Sie ist auch sehr einfach zu erweitern und eigene Filter und Funktionen hinzuzufügen. +- veraltet [flightphp/core View](/learn#views) - Dies ist eine sehr grundlegende Templating-Engine, die zum Kern gehört. Es wird nicht empfohlen, sie zu verwenden, wenn Ihr Projekt mehr als ein paar Seiten hat. +- [latte/latte](/awesome-plugins/latte) - Latte ist eine vollständige Templating-Engine, die sehr einfach zu verwenden ist und sich näher an der PHP-Syntax anfühlt als Twig oder Smarty. Sie ist auch sehr einfach zu erweitern und eigene Filter und Funktionen hinzuzufügen. ## WordPress-Integration @@ -85,6 +91,6 @@ Möchten Sie Flight in Ihrem WordPress-Projekt verwenden? Es gibt ein praktische - [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Dieses WordPress-Plugin ermöglicht es Ihnen, Flight direkt neben WordPress auszuführen. Es ist perfekt, um benutzerdefinierte APIs, Microservices oder sogar vollständige Apps zu Ihrer WordPress-Site mit dem Flight-Framework hinzuzufügen. Super nützlich, wenn Sie das Beste aus beiden Welten wollen! -## Mitwirken +## Beitrag Haben Sie ein Plugin, das Sie teilen möchten? Reichen Sie einen Pull Request ein, um es zur Liste hinzuzufügen! \ No newline at end of file diff --git a/content/v3/de/examples.md b/content/v3/de/examples.md index f80198f0..cd8918e9 100644 --- a/content/v3/de/examples.md +++ b/content/v3/de/examples.md @@ -1,36 +1,37 @@ -# Brauchen Sie einen schnellen Start? +# Schneller Einstieg? -Sie haben zwei Optionen, um mit einem neuen Flight-Projekt zu beginnen: +Sie haben zwei Optionen, um mit einem neuen Flight-Projekt zu starten: -- [Vollständiges Skeleton-Basisgerüst](https://github.com/flightphp/skeleton): Ein umfassenderes Beispiel mit Controllern und Ansichten. -- [Einzeldatei Skeleton-Basisgerüst](https://github.com/flightphp/skeleton-simple): Eine Einzeldatei, die alles enthält, was Sie benötigen, um Ihre App in einer einzigen einfachen Datei auszuführen. +- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Ein umfassenderes Beispiel mit Controllern und Views. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Eine einzelne Datei, die alles enthält, was Sie benötigen, um Ihre App in einer einfachen einzigen Datei auszuführen. -Von der Community beigesteuerte Beispiele: +Community-beigetragene Beispiele: - [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP mit Laravel-Verzeichnissen, mit PHP-Tools + GH Actions -- [fleact](https://github.com/flightphp/fleact) - Ein FlightPHP-Startkit mit ReactJS-Integration. -- [flastro](https://github.com/flightphp/flastro) - Ein FlightPHP-Startkit mit Astro-Integration. -- [velt](https://github.com/flightphp/velt) - Velt ist eine schnelle und einfache Svelte-Startvorlage mit einem FlightPHP-Backend. - -## Brauchen Sie etwas Inspiration? - -Während diese nicht offiziell vom Flight-Team gesponsert werden, könnten diese Ihnen Ideen geben, wie Sie Ihre eigenen Projekte strukturieren, die mit Flight erstellt wurden! - -- [Decay](https://github.com/boxybird/decay) - Flight v3 mit HTMX und SleekDB über Zombies! ([Demo](https://decay.andrewrhyand.com)) -- [Flight Beispiel Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 mit Middleware, Controllern, Active Record und Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Einfaches CRUD-API-Projekt, das das Flight-Framework verwendet und eine grundlegende Struktur für neue Benutzer bietet, um schnell eine PHP-Anwendung mit CRUD-Operationen und Datenbankverbindungen einzurichten. Das Projekt demonstriert, wie man Flight für die Entwicklung von RESTful APIs verwendet, was es zu einem idealen Lernwerkzeug für Anfänger und einem nützlichen Starterkit für erfahrenere Entwickler macht. -- [Flight Schulmanagementsystem](https://github.com/krmu/FlightPHP_School) - Flight v3 -- [Paste Bin mit Kommentaren](https://github.com/n0nag0n/commie2) - Flight v3 -- [Basis-Skeleton-App](https://github.com/markhughes/flight-skeleton) -- [Beispiel-Wiki](https://github.com/Skayo/FlightWiki) -- [Die IT-Innovator PHP Framework Anwendung](https://github.com/itinnovator/myphp-app) -- [LittleEducationalCMS (Spanisch)](https://github.com/casgin/LittleEducationalCMS) -- [Italienisches Branchenbuch API](https://github.com/chiccomagnus/PGAPI) -- [Generisches Content-Management-System (mit....sehr wenig Dokumentation)](https://github.com/recepuncu/cms) -- [Ein kleines PHP-Framework basierend auf Flight und medoo.](https://github.com/ycrao/tinyme) -- [Beispiel MVC Anwendung](https://github.com/paddypei/Flight-MVC) -- [Prduktionsreifes Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Produktionsreifes Authentifizierungsframework, das Ihnen wochenlange Entwicklungszeit erspart. Bietet Sicherheit auf Unternehmensniveau: 2FA/TOTP, LDAP-Integration, Azure SSO, intelligente Ratenbegrenzung, Session-Fingerprinting, Brute-Force-Schutz, Sicherheitsanalyse-Dashboard, umfassende Audit-Protokollierung und granulare rollenbasierte Zugriffskontrolle. +- [fleact](https://github.com/flightphp/fleact) - Ein FlightPHP-Starter-Kit mit ReactJS-Integration. +- [flastro](https://github.com/flightphp/flastro) - Ein FlightPHP-Starter-Kit mit Astro-Integration. +- [velt](https://github.com/flightphp/velt) - Velt ist eine schnelle und einfache Svelte-Starter-Vorlage mit einem FlightPHP-Backend. + +## Brauchen Sie Inspiration? + +Obwohl diese nicht offiziell von dem Flight-Team gesponsert werden, könnten sie Ihnen Ideen geben, wie Sie Ihre eigenen Projekte strukturieren, die mit Flight aufgebaut sind! + +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental ist eine einseitige, mobilfreundliche Autovermietungs-Web-Anwendung, die mit PHP (FlightPHP), JavaScript und MySQL aufgebaut wurde. Sie unterstützt Benutzerregistrierung, Durchsuchen und Buchen von Autos, während Admins Autos, Benutzer und Buchungen verwalten können. Die App verfügt über eine REST-API, JWT-Authentifizierung und ein responsives Design für ein modernes Vermietungserlebnis. +- [Decay](https://github.com/boxybird/decay) - Flight v3 mit HTMX und SleekDB, alles über Zombies! ([Demo](https://decay.andrewrhyand.com)) +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 mit Middleware, Controllern, Active Record und Latte. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Einfaches CRUD-API-Projekt mit dem Flight-Framework, das eine grundlegende Struktur für neue Benutzer bietet, um schnell eine PHP-Anwendung mit CRUD-Operationen und Datenbankverbindung einzurichten. Das Projekt demonstriert, wie man Flight für die RESTful-API-Entwicklung verwendet, was es zu einem idealen Lernwerkzeug für Anfänger und einem nützlichen Starter-Kit für erfahrene Entwickler macht. +- [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 +- [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 +- [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) +- [Example Wiki](https://github.com/Skayo/FlightWiki) +- [The IT-Innovator PHP Framework Application](https://github.com/itinnovator/myphp-app) +- [LittleEducationalCMS (Spanish)](https://github.com/casgin/LittleEducationalCMS) +- [Italian Yellow Pages API](https://github.com/chiccomagnus/PGAPI) +- [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) +- [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) +- [Example MVC Application](https://github.com/paddypei/Flight-MVC) +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Produktionsreifes Authentifizierungs-Framework, das Ihnen Wochen der Entwicklung erspart. Es bietet unternehmensklasse Sicherheit: 2FA/TOTP, LDAP-Integration, Azure SSO, intelligente Ratenbegrenzung, Sitzungs-Fingerprinting, Schutz vor Brute-Force-Angriffen, Sicherheits-Analytics-Dashboard, umfassende Audit-Protokollierung und granulare rollenbasierte Zugriffssteuerung. ## 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 dieser Liste hinzuzufügen! \ No newline at end of file +Wenn Sie ein Projekt haben, das Sie teilen möchten, reichen Sie bitte einen Pull Request ein, um es zu dieser Liste hinzuzufügen! \ No newline at end of file diff --git a/content/v3/de/learn/requests.md b/content/v3/de/learn/requests.md index 7feca9b5..673e1953 100644 --- a/content/v3/de/learn/requests.md +++ b/content/v3/de/learn/requests.md @@ -1,6 +1,6 @@ # Requests -## Overview +## Übersicht Flight kapselt die HTTP-Anfrage in ein einzelnes Objekt, das wie folgt zugänglich ist: @@ -8,27 +8,27 @@ Flight kapselt die HTTP-Anfrage in ein einzelnes Objekt, das wie folgt zugängli $request = Flight::request(); ``` -## Understanding +## Verständnis -HTTP-Anfragen sind einer der Kernaspekte, die es zu verstehen gilt, um den HTTP-Lebenszyklus zu verstehen. Ein Benutzer führt eine Aktion in einem Webbrowser oder einem HTTP-Client aus, und sie senden eine Reihe von Headern, Body, URL usw. an Ihr Projekt. Sie können diese Header (die Sprache des Browsers, welche Art von Komprimierung sie handhaben können, den User Agent usw.) erfassen und den Body und die URL, die an Ihre Flight-Anwendung gesendet werden, erfassen. Diese Anfragen sind essenziell, damit Ihre App versteht, was als Nächstes zu tun ist. +HTTP-Anfragen sind eines der Kernaspekte, die man über den HTTP-Lebenszyklus verstehen muss. Ein Benutzer führt eine Aktion in einem Webbrowser oder einem HTTP-Client aus, und sie senden eine Reihe von Headern, Body, URL usw. an Ihr Projekt. Sie können diese Header (die Sprache des Browsers, welche Art von Kompression sie handhaben können, den User-Agent usw.) erfassen und den Body sowie die URL, die an Ihre Flight-Anwendung gesendet wird, erfassen. Diese Anfragen sind essenziell, damit Ihre App versteht, was als Nächstes zu tun ist. -## Basic Usage +## Grundlegende Verwendung -PHP hat mehrere Super-Globalen, einschließlich `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` und `$_COOKIE`. Flight abstrahiert diese in praktische [Collections](/learn/collections). Sie können die Eigenschaften `query`, `data`, `cookies` und `files` als Arrays oder Objekte zugreifen. +PHP hat mehrere Super-Globalen, einschließlich `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` und `$_COOKIE`. Flight abstrahiert diese in handliche [Collections](/learn/collections). Sie können die Eigenschaften `query`, `data`, `cookies` und `files` als Arrays oder Objekte zugreifen. > **Hinweis:** Es wird **STRONGLICH** davon abgeraten, diese Super-Globalen in Ihrem Projekt zu verwenden, und sie sollten über das `request()`-Objekt referenziert werden. -> **Hinweis:** Es gibt keine Abstraktion für `$_ENV`. +> **Hinweis:** Es gibt keine Abstraktion für `$_ENV` verfügbar. ### `$_GET` -Sie können das `$_GET`-Array über die `query`-Eigenschaft zugreifen: +Sie können das `$_GET`-Array über die Eigenschaft `query` zugreifen: ```php // GET /search?keyword=something Flight::route('/search', function(){ $keyword = Flight::request()->query['keyword']; - // or + // oder $keyword = Flight::request()->query->keyword; echo "You are searching for: $keyword"; // query a database or something else with the $keyword @@ -37,13 +37,13 @@ Flight::route('/search', function(){ ### `$_POST` -Sie können das `$_POST`-Array über die `data`-Eigenschaft zugreifen: +Sie können das `$_POST`-Array über die Eigenschaft `data` zugreifen: ```php Flight::route('POST /submit', function(){ $name = Flight::request()->data['name']; $email = Flight::request()->data['email']; - // or + // oder $name = Flight::request()->data->name; $email = Flight::request()->data->email; echo "You submitted: $name, $email"; @@ -53,12 +53,12 @@ Flight::route('POST /submit', function(){ ### `$_COOKIE` -Sie können das `$_COOKIE`-Array über die `cookies`-Eigenschaft zugreifen: +Sie können das `$_COOKIE`-Array über die Eigenschaft `cookies` zugreifen: ```php Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; - // or + // oder $savedLogin = Flight::request()->cookies->myLoginCookie; // check if it's really saved or not and if it is auto log them in if($savedLogin) { @@ -72,7 +72,7 @@ Für Hilfe beim Setzen neuer Cookie-Werte siehe [overclokk/cookie](/awesome-plug ### `$_SERVER` -Es gibt einen Shortcut, um das `$_SERVER`-Array über die `getVar()`-Methode zuzugreifen: +Es gibt einen Shortcut, um das `$_SERVER`-Array über die Methode `getVar()` zugreifen: ```php @@ -81,22 +81,22 @@ $host = Flight::request()->getVar('HTTP_HOST'); ### `$_FILES` -Sie können hochgeladene Dateien über die `files`-Eigenschaft zugreifen: +Sie können hochgeladene Dateien über die Eigenschaft `files` zugreifen: ```php // raw access to $_FILES property. See below for recommended approach $uploadedFile = Flight::request()->files['myFile']; -// or +// oder $uploadedFile = Flight::request()->files->myFile; ``` Siehe [Uploaded File Handler](/learn/uploaded-file) für mehr Infos. -#### Processing File Uploads +#### Verarbeiten von Datei-Uploads _v3.12.0_ -Sie können Datei-Uploads mit dem Framework und einigen Hilfsmethoden verarbeiten. Es läuft im Wesentlichen darauf hinaus, die Dateidaten aus der Anfrage zu ziehen und sie an einen neuen Speicherort zu verschieben. +Sie können Datei-Uploads mit dem Framework mithilfe einiger Hilfsmethoden verarbeiten. Es kommt im Wesentlichen darauf an, die Dateidaten aus der Anfrage zu ziehen und sie an einen neuen Ort zu verschieben. ```php Flight::route('POST /upload', function(){ @@ -119,11 +119,11 @@ Flight::route('POST /upload', function(){ }); ``` -> **Sicherheitshinweis:** Validieren und sanitieren Sie immer Benutzereingaben, insbesondere bei Datei-Uploads. Validieren Sie immer den Typ der Erweiterungen, die Sie hochladen lassen, aber Sie sollten auch die "Magic Bytes" der Datei validieren, um sicherzustellen, dass es tatsächlich der Dateityp ist, den der Benutzer angibt. Es gibt [Artikel](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [und](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [Bibliotheken](https://github.com/RikudouSage/MimeTypeDetector), die dabei helfen. +> **Sicherheitshinweis:** Validieren und sanitieren Sie immer Benutzereingaben, insbesondere bei Datei-Uploads. Validieren Sie immer den Typ der Erweiterungen, die Sie zum Hochladen erlauben, aber Sie sollten auch die "Magic Bytes" der Datei validieren, um sicherzustellen, dass es tatsächlich der Typ der Datei ist, den der Benutzer angibt. Es gibt [Artikel](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [und](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [Bibliotheken](https://github.com/RikudouSage/MimeTypeDetector), die dabei helfen. ### Request Body -Um den rohen HTTP-Anfragetext zu erhalten, z. B. bei POST/PUT-Anfragen, können Sie Folgendes tun: +Um den rohen HTTP-Request-Body zu erhalten, z. B. bei POST/PUT-Anfragen, können Sie Folgendes tun: ```php Flight::route('POST /users/xml', function(){ @@ -134,7 +134,7 @@ Flight::route('POST /users/xml', function(){ ### JSON Body -Wenn Sie eine Anfrage mit dem Inhaltstyp `application/json` und den Beispieldaten `{"id": 123}` erhalten, ist sie über die `data`-Eigenschaft verfügbar: +Wenn Sie eine Anfrage mit dem Content-Type `application/json` und den Beispieldaten `{"id": 123}` erhalten, ist sie über die Eigenschaft `data` verfügbar: ```php $id = Flight::request()->data->id; @@ -142,47 +142,47 @@ $id = Flight::request()->data->id; ### Request Headers -Sie können Anfrage-Header mit der `getHeader()`- oder `getHeaders()`-Methode zugreifen: +Sie können Request-Header mit der Methode `getHeader()` oder `getHeaders()` zugreifen: ```php // Maybe you need Authorization header $host = Flight::request()->getHeader('Authorization'); -// or +// oder $host = Flight::request()->header('Authorization'); // If you need to grab all headers $headers = Flight::request()->getHeaders(); -// or +// oder $headers = Flight::request()->headers(); ``` ### Request Method -Sie können die Anfragemethode mit der `method`-Eigenschaft oder der `getMethod()`-Methode zugreifen: +Sie können die Request-Methode über die Eigenschaft `method` oder die Methode `getMethod()` zugreifen: ```php $method = Flight::request()->method; // actually populated by getMethod() $method = Flight::request()->getMethod(); ``` -**Hinweis:** Die `getMethod()`-Methode zieht zunächst die Methode aus `$_SERVER['REQUEST_METHOD']`, dann kann sie von `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` überschrieben werden, falls vorhanden, oder `$_REQUEST['_method']`, falls vorhanden. +**Hinweis:** Die Methode `getMethod()` zieht zunächst die Methode aus `$_SERVER['REQUEST_METHOD']`, dann kann sie durch `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` überschrieben werden, falls vorhanden, oder `$_REQUEST['_method']`, falls vorhanden. -## Request Object Properties +## Eigenschaften des Request-Objekts -Das Anfrage-Objekt stellt die folgenden Eigenschaften bereit: +Das Request-Objekt stellt die folgenden Eigenschaften bereit: -- **body** - Der rohe HTTP-Anfragetext +- **body** - Der rohe HTTP-Request-Body - **url** - Die angeforderte URL - **base** - Das übergeordnete Unterverzeichnis der URL -- **method** - Die Anfragemethode (GET, POST, PUT, DELETE) +- **method** - Die Request-Methode (GET, POST, PUT, DELETE) - **referrer** - Die Referrer-URL - **ip** - IP-Adresse des Clients - **ajax** - Ob es sich um eine AJAX-Anfrage handelt - **scheme** - Das Server-Protokoll (http, https) - **user_agent** - Browser-Informationen -- **type** - Der Inhaltstyp -- **length** - Die Inhaltslänge +- **type** - Der Content-Type +- **length** - Die Content-Länge - **query** - Query-String-Parameter - **data** - Post-Daten oder JSON-Daten - **cookies** - Cookie-Daten @@ -190,24 +190,24 @@ Das Anfrage-Objekt stellt die folgenden Eigenschaften bereit: - **secure** - Ob die Verbindung sicher ist - **accept** - HTTP-Accept-Parameter - **proxy_ip** - Proxy-IP-Adresse des Clients. Scannt das `$_SERVER`-Array nach `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` in dieser Reihenfolge. -- **host** - Der Anfragen-Hostname +- **host** - Der Request-Hostname - **servername** - Der SERVER_NAME aus `$_SERVER` -## Helper Methods +## Hilfsmethoden Es gibt ein paar Hilfsmethoden, um Teile einer URL zusammenzusetzen oder mit bestimmten Headern umzugehen. -### Full URL +### Volle URL -Sie können die vollständige Anfrage-URL mit der `getFullUrl()`-Methode zugreifen: +Sie können die volle Request-URL mit der Methode `getFullUrl()` zugreifen: ```php $url = Flight::request()->getFullUrl(); // https://example.com/some/path?foo=bar ``` -### Base URL +### Basis-URL -Sie können die Basis-URL mit der `getBaseUrl()`-Methode zugreifen: +Sie können die Basis-URL mit der Methode `getBaseUrl()` zugreifen: ```php // http://example.com/path/to/something/cool?query=yes+thanks @@ -216,20 +216,20 @@ $url = Flight::request()->getBaseUrl(); // Notice, no trailing slash. ``` -## Query Parsing +## Query-Parsing -Sie können eine URL an die `parseQuery()`-Methode übergeben, um den Query-String in ein assoziatives Array zu parsen: +Sie können eine URL an die Methode `parseQuery()` übergeben, um den Query-String in ein assoziatives Array zu parsen: ```php $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` -## Negotiate Content Accept Types +## Verhandeln von Content-Accept-Types _v3.17.2_ -Sie können die `negotiateContentType()`-Methode verwenden, um den besten Inhaltstyp zu bestimmen, mit dem geantwortet werden soll, basierend auf dem `Accept`-Header, der vom Client gesendet wird. +Sie können die Methode `negotiateContentType()` verwenden, um den besten Content-Type für die Antwort basierend auf dem vom Client gesendeten `Accept`-Header zu bestimmen. ```php @@ -248,15 +248,15 @@ if ($typeToServe === 'application/json') { > **Hinweis:** Wenn keiner der verfügbaren Typen im `Accept`-Header gefunden wird, gibt die Methode `null` zurück. Wenn kein `Accept`-Header definiert ist, gibt die Methode den ersten Typ im `$availableTypes`-Array zurück. -## See Also -- [Routing](/learn/routing) - See how to map routes to controllers and render views. -- [Responses](/learn/responses) - How to customize HTTP responses. -- [Why a Framework?](/learn/why-frameworks) - How requests fit into the big picture. -- [Collections](/learn/collections) - Working with collections of data. -- [Uploaded File Handler](/learn/uploaded-file) - Handling file uploads. +## Siehe auch +- [Routing](/learn/routing) - So ordnen Sie Routen Controllern zu und rendern Views. +- [Responses](/learn/responses) - So passen Sie HTTP-Antworten an. +- [Warum ein Framework?](/learn/why-frameworks) - Wie Anfragen in das große Ganze passen. +- [Collections](/learn/collections) - Arbeiten mit Datensammlungen. +- [Uploaded File Handler](/learn/uploaded-file) - Behandeln von Datei-Uploads. -## Troubleshooting -- `request()->ip` and `request()->proxy_ip` can be different if your webserver is behind a proxy, load balancer, etc. +## Fehlerbehebung +- `request()->ip` und `request()->proxy_ip` können unterschiedlich sein, wenn Ihr Webserver hinter einem Proxy, Load Balancer usw. steht. ## Changelog - v3.17.2 - Added negotiateContentType() diff --git a/content/v3/de/learn/routing.md b/content/v3/de/learn/routing.md index 05ee8b69..8702351b 100644 --- a/content/v3/de/learn/routing.md +++ b/content/v3/de/learn/routing.md @@ -1,12 +1,12 @@ # Routing -## Überblick -Routing in Flight PHP ordnet URL-Muster Callback-Funktionen oder Klassenmethoden zu, um eine schnelle und einfache Anforderungsbehandlung zu ermöglichen. Es ist für minimale Overhead, benutzerfreundliche Nutzung für Anfänger und Erweiterbarkeit ohne externe Abhängigkeiten konzipiert. +## Übersicht +Routing in Flight PHP ordnet URL-Muster Callback-Funktionen oder Klassenmethoden zu, um schnelle und einfache Anfragenverarbeitung zu ermöglichen. Es ist für minimale Overhead, benutzerfreundliche Nutzung für Anfänger und Erweiterbarkeit ohne externe Abhängigkeiten konzipiert. ## Verständnis -Routing ist der Kernmechanismus, der HTTP-Anfragen mit Ihrer Anwendungslogik in Flight verbindet. Durch das Definieren von Routen legen Sie fest, wie verschiedene URLs spezifischen Code auslösen, sei es durch Funktionen, Klassenmethoden oder Controller-Aktionen. Das Routing-System von Flight ist flexibel und unterstützt grundlegende Muster, benannte Parameter, reguläre Ausdrücke sowie erweiterte Funktionen wie Dependency Injection und Resourceful Routing. Dieser Ansatz hält Ihren Code organisiert und einfach zu warten, während er für Anfänger schnell und einfach bleibt und für fortgeschrittene Nutzer erweiterbar ist. +Routing ist der Kernmechanismus, der HTTP-Anfragen mit der Anwendungslogik in Flight verbindet. Durch das Definieren von Routen spezifizieren Sie, wie verschiedene URLs spezifischen Code auslösen, sei es durch Funktionen, Klassenmethoden oder Controller-Aktionen. Das Routing-System von Flight ist flexibel und unterstützt grundlegende Muster, benannte Parameter, reguläre Ausdrücke sowie erweiterte Funktionen wie Dependency Injection und ressourcenorientiertes Routing. Dieser Ansatz hält Ihren Code organisiert und leicht wartbar, während er für Anfänger schnell und einfach bleibt und für fortgeschrittene Benutzer erweiterbar ist. -> **Hinweis:** Möchten Sie mehr über Routing erfahren? Schauen Sie sich die Seite ["why a framework?](/learn/why-frameworks) für eine detailliertere Erklärung an. +> **Hinweis:** Möchten Sie mehr über Routing erfahren? Schauen Sie auf der Seite ["why a framework?"](/learn/why-frameworks) für eine detailliertere Erklärung nach. ## Grundlegende Nutzung @@ -19,10 +19,10 @@ Flight::route('/', function(){ }); ``` -> Routen werden in der Reihenfolge abgeglichen, in der sie definiert sind. Die erste Route, die einer Anfrage entspricht, wird aufgerufen. +> Routen werden in der Reihenfolge abgeglichen, in der sie definiert werden. Die erste Route, die zu einer Anfrage passt, wird ausgeführt. ### Verwendung von Funktionen als Callbacks -Der Callback kann jedes aufrufbare Objekt sein. Sie können also eine reguläre Funktion verwenden: +Der Callback kann jedes aufrufbare Objekt sein. Sie können also eine normale Funktion verwenden: ```php function hello() { @@ -43,11 +43,11 @@ class GreetingController { } Flight::route('/', [ 'GreetingController','hello' ]); -// or -Flight::route('/', [ GreetingController::class, 'hello' ]); // preferred method -// or +// oder +Flight::route('/', [ GreetingController::class, 'hello' ]); // bevorzugte Methode +// oder Flight::route('/', [ 'GreetingController::hello' ]); -// or +// oder Flight::route('/', [ 'GreetingController->hello' ]); ``` @@ -77,11 +77,11 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **Hinweis:** Standardmäßig wird bei Aufruf eines Controllers im Framework die Klasse `flight\Engine` immer injiziert, es sei denn, Sie spezifizieren es über einen [Dependency Injection Container](/learn/dependency-injection-container) +> **Hinweis:** Standardmäßig wird beim Aufruf eines Controllers im Framework die Klasse `flight\Engine` immer injiziert, es sei denn, Sie spezifizieren es über einen [Dependency Injection Container](/learn/dependency-injection-container). ### Methode-spezifisches Routing -Standardmäßig werden Routenmuster gegen alle Anfragemethoden abgeglichen. Sie können auf spezifische Methoden reagieren, indem Sie einen Identifier vor die URL setzen. +Standardmäßig werden Routenmuster gegen alle Anfragemethoden abgeglichen. Sie können auf spezifische Methoden reagieren, indem Sie einen Bezeichner vor die URL stellen. ```php Flight::route('GET /', function () { @@ -92,15 +92,15 @@ Flight::route('POST /', function () { echo 'I received a POST request.'; }); -// You cannot use Flight::get() for routes as that is a method -// to get variables, not create a route. +// 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 einzelnen Callback abbilden, indem Sie den `|`-Trennzeichen verwenden: +Sie können auch mehrere Methoden auf einen einzigen Callback abbilden, indem Sie den `|`-Trenner verwenden: ```php Flight::route('GET|POST /', function () { @@ -114,27 +114,27 @@ Flight bietet integrierte Behandlung für `HEAD`- und `OPTIONS`-HTTP-Anfragen: #### HEAD-Anfragen -- **HEAD-Anfragen** werden genau wie `GET`-Anfragen behandelt, aber Flight entfernt automatisch den Response-Body, bevor er an den Client gesendet wird. -- Das bedeutet, Sie können eine Route für `GET` definieren, und HEAD-Anfragen zur gleichen URL geben nur Header zurück (keinen Inhalt), wie es die HTTP-Standards erwarten. +- **HEAD-Anfragen** werden genauso wie `GET`-Anfragen behandelt, aber Flight entfernt automatisch den Response-Body, bevor er an den Client gesendet wird. +- Das bedeutet, Sie können eine Route für `GET` definieren, und HEAD-Anfragen an dieselbe URL geben nur Header zurück (keinen Inhalt), wie es HTTP-Standards erwarten. ```php Flight::route('GET /info', function() { echo 'This is some info!'; }); -// A HEAD request to /info will return the same headers, but no body. +// Eine HEAD-Anfrage an /info gibt dieselben Header zurück, aber keinen Body. ``` #### OPTIONS-Anfragen -`OPTIONS`-Anfragen werden von Flight automatisch für jede definierte Route behandelt. -- Wenn eine OPTIONS-Anfrage empfangen wird, antwortet Flight mit einem `204 No Content`-Status und einem `Allow`-Header, der alle unterstützten HTTP-Methoden für diese Route auflistet. -- Sie müssen keine separate Route für OPTIONS definieren, es sei denn, Sie möchten benutzerdefiniertes Verhalten oder die Response modifizieren. +`OPTIONS`-Anfragen werden automatisch von Flight für jede definierte Route behandelt. +- Wenn eine OPTIONS-Anfrage empfangen wird, antwortet Flight mit einem Status `204 No Content` und einem `Allow`-Header, der alle unterstützten HTTP-Methoden für diese Route auflistet. +- Sie müssen keine separate Route für OPTIONS definieren. ```php -// For a route defined as: +// Für eine Route, die als: Flight::route('GET|POST /users', function() { /* ... */ }); -// An OPTIONS request to /users will respond with: +// Eine OPTIONS-Anfrage an /users antwortet mit: // // Status: 204 No Content // Allow: GET, POST, HEAD, OPTIONS @@ -148,12 +148,12 @@ Zusätzlich können Sie das Router-Objekt abrufen, das einige Hilfsmethoden für $router = Flight::router(); -// maps all methods just like Flight::route() +// mapped alle Methoden genau wie Flight::route() $router->map('/', function() { echo 'hello world!'; }); -// GET request +// GET-Anfrage $router->get('/users', function() { echo 'users'; }); @@ -168,14 +168,14 @@ Sie können reguläre Ausdrücke in Ihren Routen verwenden: ```php Flight::route('/user/[0-9]+', function () { - // This will match /user/1234 + // Dies passt zu /user/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 spezifizieren, die an Ihre Callback-Funktion weitergegeben werden. **Dies dient hauptsächlich der Lesbarkeit der Route. Bitte sehen Sie den Abschnitt unten zu wichtigen Einschränkungen.** +Sie können benannte Parameter in Ihren Routen spezifizieren, die an Ihre Callback-Funktion weitergegeben werden. **Dies dient hauptsächlich der Lesbarkeit der Route. Bitte lesen Sie den Abschnitt unten zu wichtigen Einschränkungen.** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -183,20 +183,20 @@ Flight::route('/@name/@id', function (string $name, string $id) { }); ``` -Sie können auch reguläre Ausdrücke mit Ihren benannten Parametern kombinieren, indem Sie den `:`-Trennzeichen verwenden: +Sie können auch reguläre Ausdrücke mit Ihren benannten Parametern kombinieren, indem Sie den `:`-Trenner verwenden: ```php Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { - // This will match /bob/123 - // But will not match /bob/12345 + // Dies passt zu /bob/123 + // Passt aber nicht zu /bob/12345 }); ``` -> **Hinweis:** Das Abgleichen von Regex-Gruppen `()` mit positionalen Parametern wird nicht unterstützt. Ex: `:'\(` +> **Hinweis:** Das Abgleichen von Regex-Gruppen `()` mit positionsbasierten Parametern wird nicht unterstützt. Beispiel: `:'\(` #### Wichtige Einschränkung -Während im obigen Beispiel erscheint, als ob `@name` direkt mit der Variable `$name` verknüpft ist, ist das nicht der Fall. Die Reihenfolge der Parameter in der Callback-Funktion bestimmt, was an sie weitergegeben wird. Wenn Sie die Reihenfolge der Parameter in der Callback-Funktion umkehren würden, würden die Variablen ebenfalls umgekehrt. Hier ein Beispiel: +Während im obigen Beispiel `@name` direkt mit der Variable `$name` verknüpft zu sein scheint, ist das nicht der Fall. Die Reihenfolge der Parameter in der Callback-Funktion bestimmt, was weitergegeben wird. Wenn Sie die Reihenfolge der Parameter in der Callback-Funktion umkehren würden, würden auch die Variablen umgekehrt. Hier ein Beispiel: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -205,7 +205,7 @@ Flight::route('/@name/@id', function (string $id, string $name) { ``` Und wenn Sie zur folgenden URL gehen: `/bob/123`, wäre die Ausgabe `hello, 123 (bob)!`. -_Bitte seien Sie vorsichtig_, wenn Sie Ihre Routen und Callback-Funktionen einrichten! +_Seien Sie vorsichtig_, wenn Sie Ihre Routen und Callback-Funktionen einrichten! ### Optionale Parameter Sie können benannte Parameter spezifizieren, die optional für das Abgleichen sind, indem Sie Segmente in Klammern setzen. @@ -214,7 +214,7 @@ Sie können benannte Parameter spezifizieren, die optional für das Abgleichen s Flight::route( '/blog(/@year(/@month(/@day)))', function(?string $year, ?string $month, ?string $day) { - // This will match the following URLS: + // Dies passt zu den folgenden URLs: // /blog/2012/12/10 // /blog/2012/12 // /blog/2012 @@ -223,35 +223,35 @@ Flight::route( ); ``` -Jede optionale Parameter, die nicht abgeglichen wird, wird als `NULL` weitergegeben. +Optionale Parameter, die nicht abgeglichen werden, werden als `NULL` weitergegeben. ### Wildcard-Routing -Das Abgleichen erfolgt nur auf einzelne URL-Segmente. Wenn Sie mehrere Segmente abgleichen möchten, können Sie das `*`-Wildcard verwenden. +Das Abgleichen erfolgt nur auf einzelne URL-Segmente. Wenn Sie mehrere Segmente abgleichen möchten, können Sie den `*`-Wildcard verwenden. ```php Flight::route('/blog/*', function () { - // This will match /blog/2000/02/01 + // Dies passt zu /blog/2000/02/01 }); ``` -Um alle Anfragen an einen einzelnen Callback zu routen, können Sie tun: +Um alle Anfragen an einen einzigen Callback zu routen, können Sie Folgendes tun: ```php Flight::route('*', function () { - // Do something + // Etwas tun }); ``` ### 404 Not Found Handler -Standardmäßig sendet Flight bei einer nicht gefundenen URL eine sehr einfache und schlichte `HTTP 404 Not Found`-Response. -Wenn Sie eine personalisiertere 404-Response haben möchten, können Sie Ihre eigene `notFound`-Methode [mappen](/learn/extending): +Standardmäßig sendet Flight bei einer nicht gefundenen URL eine sehr einfache und schlichte `HTTP 404 Not Found`-Antwort. +Wenn Sie eine personalisiertere 404-Antwort haben möchten, können Sie Ihre eigene `notFound`-Methode [mappen](/learn/extending): ```php Flight::map('notFound', function() { $url = Flight::request()->url; - // You could also use Flight::render() with a custom template. + // Sie könnten auch Flight::render() mit einer benutzerdefinierten Vorlage verwenden. $output = <<My Custom 404 Not Found

The page you have requested {$url} could not be found.

@@ -267,9 +267,9 @@ Flight::map('notFound', function() { ### Method Not Found Handler -Standardmäßig sendet Flight bei einer gefundenen URL, aber nicht erlaubten Methode eine sehr einfache und schlichte `HTTP 405 Method Not Allowed`-Response (Ex: Method Not Allowed. Allowed Methods are: GET, POST). Es wird auch ein `Allow`-Header mit den erlaubten Methoden für diese URL enthalten. +Standardmäßig sendet Flight bei einer gefundenen URL, aber nicht erlaubten Methode, eine sehr einfache und schlichte `HTTP 405 Method Not Allowed`-Antwort (z. B. Method Not Allowed. Allowed Methods are: GET, POST). Es enthält auch einen `Allow`-Header mit den erlaubten Methoden für diese URL. -Wenn Sie eine personalisiertere 405-Response haben möchten, können Sie Ihre eigene `methodNotFound`-Methode [mappen](/learn/extending): +Wenn Sie eine personalisiertere 405-Antwort haben möchten, können Sie Ihre eigene `methodNotFound`-Methode [mappen](/learn/extending): ```php use flight\net\Route; @@ -278,7 +278,7 @@ Flight::map('methodNotFound', function(Route $route) { $url = Flight::request()->url; $methods = implode(', ', $route->methods); - // You could also use Flight::render() with a custom template. + // Sie könnten auch Flight::render() mit einer benutzerdefinierten Vorlage verwenden. $output = <<My Custom 405 Method Not Allowed

The method you have requested for {$url} is not allowed.

@@ -297,7 +297,7 @@ Flight::map('methodNotFound', function(Route $route) { ## Erweiterte Nutzung ### Dependency Injection in Routen -Wenn Sie Dependency Injection über einen Container (PSR-11, PHP-DI, Dice usw.) verwenden möchten, ist der einzige Routentyp, bei dem das verfügbar ist, entweder das direkte Erstellen des Objekts selbst und die Verwendung des Containers, um Ihr Objekt zu erstellen, oder Sie können Strings verwenden, um die Klasse und Methode zu definieren, die aufgerufen werden soll. Sie können zur [Dependency Injection](/learn/dependency-injection-container)-Seite für weitere Informationen gehen. +Wenn Sie Dependency Injection über einen Container (PSR-11, PHP-DI, Dice usw.) verwenden möchten, ist der einzige Routentyp, bei dem dies verfügbar ist, entweder das direkte Erstellen des Objekts selbst und die Verwendung des Containers, um Ihr Objekt zu erstellen, oder Sie können Strings verwenden, um die Klasse und Methode zum Aufrufen zu definieren. Sie können zur Seite [Dependency Injection](/learn/dependency-injection-container) für weitere Informationen gehen. Hier ein kurzes Beispiel: @@ -372,7 +372,7 @@ Flight::route('/user/*', function () { Es wird nun empfohlen, [Middleware](/learn/middleware) für komplexe Anwendungsfälle wie diesen zu verwenden. ### Route-Aliasing -Durch das Zuweisen eines Aliases zu einer Route können Sie diesen Alias später dynamisch in Ihrer App aufrufen, um ihn später in Ihrem Code zu generieren (z. B. ein Link in einer HTML-Vorlage oder das Generieren einer Weiterleitungs-URL). +Durch das Zuweisen eines Aliases zu einer Route können Sie diesen Alias später dynamisch in Ihrer App aufrufen, um ihn später in Ihrem Code zu generieren (z. B. ein Link in einer HTML-Vorlage oder das Generieren einer Redirect-URL). ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); @@ -394,7 +394,7 @@ class UserController { ``` Dies ist besonders hilfreich, wenn sich Ihre URL ändert. Im obigen Beispiel, sagen wir, dass Benutzer zu `/admin/users/@id` verschoben wurden. -Mit Aliasing an Ort und Stelle müssen Sie nicht mehr alle alten URLs in Ihrem Code finden und ändern, da der Alias nun `/admin/users/5` wie im obigen Beispiel zurückgibt. +Mit Aliasing vorhanden für die Route müssen Sie nicht mehr alle alten URLs in Ihrem Code finden und ändern, da der Alias nun `/admin/users/5` zurückgibt, wie im obigen Beispiel. Route-Aliasing funktioniert auch in Gruppen: @@ -406,8 +406,8 @@ Flight::group('/users', function() { }); ``` -### Inspektion von Routeninformationen -Wenn Sie die passende Routeninformation inspizieren möchten, gibt es 2 Wege, das zu tun: +### Überprüfen von Routeninformationen +Wenn Sie die passende Routeninformation überprüfen möchten, gibt es 2 Wege, dies zu tun: 1. Sie können die `executedRoute`-Eigenschaft auf dem `Flight::router()`-Objekt verwenden. 2. Sie können das Routenobjekt anfordern, das an Ihren Callback weitergegeben wird, indem Sie `true` als dritten Parameter in der Routenmethode übergeben. Das Routenobjekt wird immer der letzte Parameter sein, der an Ihre Callback-Funktion weitergegeben wird. @@ -440,7 +440,7 @@ Flight::route('/', function() { }); ``` -> **Hinweis:** Die `executedRoute`-Eigenschaft wird nur nach der Ausführung einer Route gesetzt. Wenn Sie sie vor der Ausführung einer Route abrufen, ist sie `NULL`. Sie können executedRoute auch in [Middleware](/learn/middleware) verwenden! +> **Hinweis:** Die `executedRoute`-Eigenschaft wird nur gesetzt, nachdem eine Route ausgeführt wurde. Wenn Sie versuchen, darauf zuzugreifen, bevor eine Route ausgeführt wurde, ist sie `NULL`. Sie können executedRoute auch in [Middleware](/learn/middleware) verwenden! #### `true` in Routendefinition übergeben ```php @@ -465,12 +465,12 @@ Flight::route('/', function(\flight\net\Route $route) { // Shows the alias assigned to this route $route->alias; -}, true);// <-- This true parameter is what makes that happen +}, true);// <-- Dieser true-Parameter ist das, was das bewirkt ``` ### Routengruppierung und Middleware -Es kann Fälle geben, in denen Sie verwandte Routen gruppieren möchten (z. B. `/api/v1`). -Sie können das tun, indem Sie die `group`-Methode verwenden: +Es kann vorkommen, dass Sie verwandte Routen gruppieren möchten (z. B. `/api/v1`). +Sie können dies tun, indem Sie die `group`-Methode verwenden: ```php Flight::group('/api/v1', function () { @@ -514,7 +514,7 @@ Flight::group('/api', function () { #### Gruppierung mit Objektkontext -Sie können Routengruppierung immer noch mit dem `Engine`-Objekt auf folgende Weise verwenden: +Sie können die Routengruppierung immer noch mit dem `Engine`-Objekt auf folgende Weise verwenden: ```php $app = Flight::app(); @@ -543,15 +543,15 @@ Flight::group('/api/v1', function () { Flight::route('/users', function () { // Matches /api/v1/users }); -}, [ MyAuthMiddleware::class ]); // or [ new MyAuthMiddleware() ] if you want to use an instance +}, [ MyAuthMiddleware::class ]); // oder [ new MyAuthMiddleware() ], wenn Sie eine Instanz verwenden möchten ``` -Weitere Details finden Sie auf der [Gruppen-Middleware](/learn/middleware#grouping-middleware)-Seite. +Weitere Details finden Sie auf der Seite [group middleware](/learn/middleware#grouping-middleware). -### Resource Routing -Sie können eine Reihe von Routen für eine Resource mit der `resource`-Methode erstellen. Dies erstellt eine Reihe von Routen für eine Resource, die den RESTful-Konventionen folgt. +### Ressourcen-Routing +Sie können eine Reihe von Routen für eine Ressource mit der `resource`-Methode erstellen. Dies erstellt eine Reihe von Routen für eine Ressource, die den RESTful-Konventionen folgt. -Um eine Resource zu erstellen, tun Sie Folgendes: +Um eine Ressource zu erstellen, tun Sie Folgendes: ```php Flight::resource('/users', UsersController::class); @@ -571,7 +571,7 @@ Und was im Hintergrund passiert, ist, dass es die folgenden Routen erstellt: ] ``` -Und Ihr Controller wird die folgenden Methoden verwenden: +Und Ihr Controller verwendet die folgenden Methoden: ```php class UsersController @@ -608,11 +608,11 @@ class UsersController > **Hinweis**: Sie können die neu hinzugefügten Routen mit `runway` anzeigen, indem Sie `php runway routes` ausführen. -#### Anpassen von Resource-Routen +#### Anpassen von Ressourcen-Routen -Es gibt einige Optionen, um die Resource-Routen zu konfigurieren. +Es gibt einige Optionen, um die Ressourcen-Routen zu konfigurieren. -##### Alias-Basis +##### Alias Base Sie können die `aliasBase` konfigurieren. Standardmäßig ist der Alias der letzte Teil der angegebenen URL. Zum Beispiel würde `/users/` zu einem `aliasBase` von `users` führen. Wenn diese Routen erstellt werden, @@ -625,7 +625,7 @@ Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); ##### Only und Except -Sie können auch spezifizieren, welche Routen Sie erstellen möchten, indem Sie die `only`- und `except`-Optionen verwenden. +Sie können auch spezifizieren, welche Routen Sie erstellen möchten, indem Sie die Optionen `only` und `except` verwenden. ```php // Whitelist only these methods and blacklist the rest @@ -637,27 +637,27 @@ Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` -Diese sind im Wesentlichen Whitelisting- und Blacklisting-Optionen, damit Sie spezifizieren können, welche Routen Sie erstellen möchten. +Dies sind im Wesentlichen Whitelist- und Blacklist-Optionen, damit Sie spezifizieren können, welche Routen Sie erstellen möchten. ##### Middleware -Sie können auch Middleware spezifizieren, die für jede der von der `resource`-Methode erstellten Routen ausgeführt wird. +Sie können auch Middleware spezifizieren, die auf jeder der von der `resource`-Methode erstellten Routen ausgeführt wird. ```php Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]); ``` -### Streaming-Responses +### Streaming-Antworten -Sie können nun Responses an den Client streamen, indem Sie `stream()` oder `streamWithHeaders()` verwenden. -Dies ist nützlich für das Senden großer Dateien, lang laufender Prozesse oder das Generieren großer Responses. -Das Streamen einer Route wird etwas anders gehandhabt als eine reguläre Route. +Sie können nun Antworten an den Client streamen, indem Sie `stream()` oder `streamWithHeaders()` verwenden. +Dies ist nützlich für das Senden großer Dateien, lang laufender Prozesse oder das Generieren großer Antworten. +Das Streamen einer Route wird etwas anders gehandhabt als eine normale Route. -> **Hinweis:** Streaming-Responses sind nur verfügbar, wenn Sie [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) auf `false` gesetzt haben. +> **Hinweis:** Streaming-Antworten sind nur verfügbar, wenn Sie [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) auf `false` gesetzt haben. #### Stream mit manuellen Headern -Sie können eine Response an den Client streamen, indem Sie die `stream()`-Methode auf einer Route verwenden. Wenn Sie +Sie können eine Antwort an den Client streamen, indem Sie die `stream()`-Methode auf einer Route verwenden. Wenn Sie das tun, müssen Sie alle Header manuell setzen, bevor Sie etwas an den Client ausgeben. Dies geschieht mit der `header()`-PHP-Funktion oder der `Flight::response()->setRealHeader()`-Methode. @@ -734,11 +734,11 @@ Flight::route('/stream-users', function() { - [Middleware](/learn/middleware) - Verwendung von Middleware mit Routen für Authentifizierung, Logging usw. - [Dependency Injection](/learn/dependency-injection-container) - Vereinfachung der Objekterstellung und -verwaltung in Routen. - [Why a Framework?](/learn/why-frameworks) - Verständnis der Vorteile der Verwendung eines Frameworks wie Flight. -- [Erweitern](/learn/extending) - Wie man Flight mit eigener Funktionalität erweitert, einschließlich der `notFound`-Methode. -- [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - PHP-Funktion für reguläres Ausdrucksabgleichen. +- [Extending](/learn/extending) - Wie man Flight mit eigener Funktionalität erweitert, einschließlich der `notFound`-Methode. +- [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - PHP-Funktion für reguläre Ausdrucksabgleichung. ## Fehlerbehebung -- Routenparameter werden nach Reihenfolge abgeglichen, nicht nach Name. Stellen Sie sicher, dass die Parameterreihenfolge des Callbacks mit der Routendefinition übereinstimmt. +- Routenparameter werden nach Reihenfolge abgeglichen, nicht nach Namen. Stellen Sie sicher, dass die Parameterreihenfolge des Callbacks zur Routendefinition passt. - Die Verwendung von `Flight::get()` definiert keine Route; verwenden Sie `Flight::route('GET /...')` für Routing oder den Router-Objektkontext in Gruppen (z. B. `$router->get(...)`). - Die executedRoute-Eigenschaft wird nur nach der Ausführung einer Route gesetzt; sie ist NULL vor der Ausführung. - Streaming erfordert, dass die Legacy-Flight-Output-Buffering-Funktionalität deaktiviert ist (`flight.v2.output_buffering = false`). @@ -746,8 +746,8 @@ Flight::route('/stream-users', function() { ### 404 Not Found oder unerwartetes Routenverhalten -Wenn Sie einen 404 Not Found-Fehler sehen (aber Sie schwören bei Ihrem Leben, dass er wirklich da ist und es kein Tippfehler ist), könnte das tatsächlich ein Problem damit sein, -dass Sie einen Wert in Ihrem Routenendpunkt zurückgeben, anstatt ihn nur auszugeben. Der Grund dafür ist absichtlich, könnte aber einige Entwickler überraschen. +Wenn Sie einen 404 Not Found-Fehler sehen (aber Sie schwören bei Ihrem Leben, dass er wirklich da ist und es kein Tippfehler ist), könnte dies tatsächlich ein Problem damit sein, +dass Sie einen Wert in Ihrem Routen-Endpunkt zurückgeben, anstatt ihn nur auszugeben. Der Grund dafür ist absichtlich, könnte aber einige Entwickler überraschen. ```php Flight::route('/hello', function(){ @@ -761,9 +761,9 @@ Flight::route('/hello', function(){ }); ``` -Der Grund dafür ist ein spezieller Mechanismus, der in den Router integriert ist und die Rückgabe als Signal interpretiert, "zur nächsten Route zu gehen". -Sie können das Verhalten in dem [Routing](/learn/routing#passing)-Abschnitt dokumentiert sehen. +Der Grund dafür ist ein spezieller Mechanismus, der in den Router integriert ist und die Rückgabeausgabe als Signal behandelt, um "zur nächsten Route zu gehen". +Sie können das Verhalten in dem Abschnitt [Routing](/learn/routing#passing) dokumentiert sehen. ## Changelog -- v3: Hinzugefügt Resource-Routing, Route-Aliasing und Streaming-Unterstützung, Routengruppen und Middleware-Unterstützung. -- v1: Überwiegende Mehrheit der grundlegenden Funktionen verfügbar. \ No newline at end of file +- v3: Hinzugefügt Ressourcen-Routing, Route-Aliasing und Streaming-Unterstützung, Routengruppen und Middleware-Unterstützung. +- v1: Überwiegender Teil der grundlegenden Funktionen verfügbar. \ No newline at end of file diff --git a/content/v3/en/awesome-plugins/async.md b/content/v3/en/awesome-plugins/async.md new file mode 100644 index 00000000..4893c434 --- /dev/null +++ b/content/v3/en/awesome-plugins/async.md @@ -0,0 +1,212 @@ +# Async + +Async is a small package for the Flight framework that lets you run your Flight apps inside asynchronous servers and runtimes like Swoole, AdapterMan, ReactPHP, Amp, RoadRunner, Workerman, etc. Out of the box it includes adapters for Swoole and AdapterMan. + +The goal: develop and debug with PHP-FPM (or the built-in server) and switch to Swoole (or another async driver) for production with minimal changes. + +## Requirements + +- PHP 7.4 or higher +- Flight framework 3.16.1 or higher +- [Swoole extension](https://www.openswoole.com) + +## Installation + +Install via composer: + +```bash +composer require flightphp/async +``` + +If you plan to run with Swoole, install the extension: + +```bash +# using pecl +pecl install swoole +# or openswoole +pecl install openswoole + +# or with a package manager (Debian/Ubuntu example) +sudo apt-get install php-swoole +``` + +## Quick Swoole example + +Below is a minimal setup that shows how to support both PHP-FPM (or built-in server) and Swoole using the same codebase. + +Files you will need in your project: + +- index.php +- swoole_server.php +- SwooleServerDriver.php + +### index.php + +This file is a simple switch that forces the app to run in PHP mode for development. + +```php +// index.php +route('/', function() use ($app) { + $app->json(['hello' => 'world']); +}); + +if (!defined('NOT_SWOOLE')) { + // Require the SwooleServerDriver class when running in Swoole mode. + require_once __DIR__ . '/SwooleServerDriver.php'; + + Swoole\Runtime::enableCoroutine(); + $Swoole_Server = new SwooleServerDriver('127.0.0.1', 9501, $app); + $Swoole_Server->start(); +} else { + $app->start(); +} +``` + +### SwooleServerDriver.php + +A concise driver showing how to bridge Swoole requests into Flight using the AsyncBridge and Swoole adapters. + +```php +// SwooleServerDriver.php +Swoole = new SwooleServer($host, $port); + $this->app = $app; + + $this->setDefault(); + $this->bindWorkerEvents(); + $this->bindHttpEvent(); + } + + protected function setDefault() { + $this->Swoole->set([ + 'daemonize' => false, + 'dispatch_mode' => 1, + 'max_request' => 8000, + 'open_tcp_nodelay' => true, + 'reload_async' => true, + 'max_wait_time' => 60, + 'enable_reuse_port' => true, + 'enable_coroutine' => true, + 'http_compression' => false, + 'enable_static_handler' => true, + 'document_root' => __DIR__, + 'static_handler_locations' => ['/css', '/js', '/images', '/.well-known'], + 'buffer_output_size' => 4 * 1024 * 1024, + 'worker_num' => 4, + ]); + + $app = $this->app; + $app->map('stop', function (?int $code = null) use ($app) { + if ($code !== null) { + $app->response()->status($code); + } + }); + } + + protected function bindHttpEvent() { + $app = $this->app; + $AsyncBridge = new AsyncBridge($app); + + $this->Swoole->on('Start', function(SwooleServer $server) { + echo "Swoole http server is started at http://127.0.0.1:9501\n"; + }); + + $this->Swoole->on('Request', function (SwooleRequest $request, SwooleResponse $response) use ($AsyncBridge) { + $SwooleAsyncRequest = new SwooleAsyncRequest($request); + $SwooleAsyncResponse = new SwooleAsyncResponse($response); + + $AsyncBridge->processRequest($SwooleAsyncRequest, $SwooleAsyncResponse); + + $response->end(); + gc_collect_cycles(); + }); + } + + protected function bindWorkerEvents() { + $createPools = function() { + // create worker-specific connection pools here + }; + $closePools = function() { + // close pools / cleanup here + }; + $this->Swoole->on('WorkerStart', $createPools); + $this->Swoole->on('WorkerStop', $closePools); + $this->Swoole->on('WorkerError', $closePools); + } + + public function start() { + $this->Swoole->start(); + } +} +``` + +## Running the server + +- Development (PHP built-in server / PHP-FPM): + - php -S localhost:8000 (or add -t public/ if your index is in public/) +- Production (Swoole): + - php swoole_server.php + +Tip: For production use a reverse proxy (Nginx) in front of Swoole to handle TLS, static files, and load-balancing. + +## Configuration notes + +The Swoole driver exposes several config options: +- worker_num: number of worker processes +- max_request: requests per worker before restart +- enable_coroutine: use coroutines for concurrency +- buffer_output_size: output buffer size + +Adjust these to fit your host resources and traffic patterns. + +## Error handling + +AsyncBridge translates Flight errors into proper HTTP responses. You can also add route-level error handling: + +```php +$app->route('/*', function() use ($app) { + try { + // route logic + } catch (Exception $e) { + $app->response()->status(500); + $app->json(['error' => $e->getMessage()]); + } +}); +``` + +## AdapterMan and other runtimes + +[AdapterMan](https://github.com/joanhey/adapterman) is supported as an alternative runtime adapter. The package is designed to be adaptable — adding or using other adapters generally follows the same pattern: convert the server request/response into Flight's request/response via the AsyncBridge and the runtime-specific adapters. diff --git a/content/v3/en/awesome-plugins/awesome_plugins.md b/content/v3/en/awesome-plugins/awesome_plugins.md index 4cec655c..27c5578f 100644 --- a/content/v3/en/awesome-plugins/awesome_plugins.md +++ b/content/v3/en/awesome-plugins/awesome_plugins.md @@ -14,6 +14,12 @@ API documentation is crucial for any API. It helps developers understand how to Application Performance Monitoring (APM) is crucial for any application. It helps you understand how your application is performing and where the bottlenecks are. There are a number of APM tools that can be used with Flight. - official [flightphp/apm](/awesome-plugins/apm) - Flight APM is a simple APM library that can be used to monitor your Flight applications. It can be used to monitor the performance of your application and help you identify bottlenecks. +## Async + +Flight is already a fast framework but strapping it a turbo engine on it makes everything more fun (and challenging)! + +- [flightphp/async](/awesome-plugins/async) - Official Flight Async library. This library is a simple way to add asynchronous processing to your application. It uses Swoole/Openswoole under the hood to provide a simple and effective way to run tasks asynchronously. + ## Authorization/Permissions Authorization and Permissions are crucial for any application that requires controls to be in place for who can access what. diff --git a/content/v3/es/awesome-plugins/async.md b/content/v3/es/awesome-plugins/async.md new file mode 100644 index 00000000..0dd01d25 --- /dev/null +++ b/content/v3/es/awesome-plugins/async.md @@ -0,0 +1,212 @@ +# Async + +Async es un paquete pequeño para el framework Flight que te permite ejecutar tus aplicaciones Flight dentro de servidores y entornos asíncronos como Swoole, AdapterMan, ReactPHP, Amp, RoadRunner, Workerman, etc. De fábrica incluye adaptadores para Swoole y AdapterMan. + +El objetivo: desarrollar y depurar con PHP-FPM (o el servidor integrado) y cambiar a Swoole (u otro controlador asíncrono) para producción con cambios mínimos. + +## Requisitos + +- PHP 7.4 o superior +- Framework Flight 3.16.1 o superior +- [Extensión Swoole](https://www.openswoole.com) + +## Instalación + +Instala vía composer: + +```bash +composer require flightphp/async +``` + +Si planeas ejecutar con Swoole, instala la extensión: + +```bash +# usando pecl +pecl install swoole +# o openswoole +pecl install openswoole + +# o con un administrador de paquetes (ejemplo Debian/Ubuntu) +sudo apt-get install php-swoole +``` + +## Ejemplo rápido de Swoole + +A continuación se muestra una configuración mínima que ilustra cómo soportar tanto PHP-FPM (o servidor integrado) como Swoole utilizando el mismo código base. + +Archivos que necesitarás en tu proyecto: + +- index.php +- swoole_server.php +- SwooleServerDriver.php + +### index.php + +Este archivo es un simple interruptor que fuerza a la aplicación a ejecutarse en modo PHP para desarrollo. + +```php +// index.php +route('/', function() use ($app) { + $app->json(['hello' => 'world']); +}); + +if (!defined('NOT_SWOOLE')) { + // Require la clase SwooleServerDriver cuando se ejecute en modo Swoole. + require_once __DIR__ . '/SwooleServerDriver.php'; + + Swoole\Runtime::enableCoroutine(); + $Swoole_Server = new SwooleServerDriver('127.0.0.1', 9501, $app); + $Swoole_Server->start(); +} else { + $app->start(); +} +``` + +### SwooleServerDriver.php + +Un controlador conciso que muestra cómo conectar solicitudes Swoole a Flight utilizando el AsyncBridge y los adaptadores de Swoole. + +```php +// SwooleServerDriver.php +Swoole = new SwooleServer($host, $port); + $this->app = $app; + + $this->setDefault(); + $this->bindWorkerEvents(); + $this->bindHttpEvent(); + } + + protected function setDefault() { + $this->Swoole->set([ + 'daemonize' => false, + 'dispatch_mode' => 1, + 'max_request' => 8000, + 'open_tcp_nodelay' => true, + 'reload_async' => true, + 'max_wait_time' => 60, + 'enable_reuse_port' => true, + 'enable_coroutine' => true, + 'http_compression' => false, + 'enable_static_handler' => true, + 'document_root' => __DIR__, + 'static_handler_locations' => ['/css', '/js', '/images', '/.well-known'], + 'buffer_output_size' => 4 * 1024 * 1024, + 'worker_num' => 4, + ]); + + $app = $this->app; + $app->map('stop', function (?int $code = null) use ($app) { + if ($code !== null) { + $app->response()->status($code); + } + }); + } + + protected function bindHttpEvent() { + $app = $this->app; + $AsyncBridge = new AsyncBridge($app); + + $this->Swoole->on('Start', function(SwooleServer $server) { + echo "Swoole http server is started at http://127.0.0.1:9501\n"; + }); + + $this->Swoole->on('Request', function (SwooleRequest $request, SwooleResponse $response) use ($AsyncBridge) { + $SwooleAsyncRequest = new SwooleAsyncRequest($request); + $SwooleAsyncResponse = new SwooleAsyncResponse($response); + + $AsyncBridge->processRequest($SwooleAsyncRequest, $SwooleAsyncResponse); + + $response->end(); + gc_collect_cycles(); + }); + } + + protected function bindWorkerEvents() { + $createPools = function() { + // create worker-specific connection pools here + }; + $closePools = function() { + // close pools / cleanup here + }; + $this->Swoole->on('WorkerStart', $createPools); + $this->Swoole->on('WorkerStop', $closePools); + $this->Swoole->on('WorkerError', $closePools); + } + + public function start() { + $this->Swoole->start(); + } +} +``` + +## Ejecutando el servidor + +- Desarrollo (servidor integrado de PHP / PHP-FPM): + - php -S localhost:8000 (o agrega -t public/ si tu index está en public/) +- Producción (Swoole): + - php swoole_server.php + +Consejo: Para producción, usa un proxy inverso (Nginx) delante de Swoole para manejar TLS, archivos estáticos y balanceo de carga. + +## Notas de configuración + +El controlador Swoole expone varias opciones de configuración: +- worker_num: número de procesos de worker +- max_request: solicitudes por worker antes del reinicio +- enable_coroutine: usar corutinas para concurrencia +- buffer_output_size: tamaño del búfer de salida + +Ajusta estos para adaptarlos a los recursos de tu host y patrones de tráfico. + +## Manejo de errores + +AsyncBridge traduce los errores de Flight en respuestas HTTP adecuadas. También puedes agregar manejo de errores a nivel de ruta: + +```php +$app->route('/*', function() use ($app) { + try { + // lógica de la ruta + } catch (Exception $e) { + $app->response()->status(500); + $app->json(['error' => $e->getMessage()]); + } +}); +``` + +## AdapterMan y otros entornos + +[AdapterMan](https://github.com/joanhey/adapterman) está soportado como un adaptador de entorno alternativo. El paquete está diseñado para ser adaptable — agregar o usar otros adaptadores generalmente sigue el mismo patrón: convertir la solicitud/respuesta del servidor en la solicitud/respuesta de Flight a través del AsyncBridge y los adaptadores específicos del entorno. \ No newline at end of file diff --git a/content/v3/es/awesome-plugins/awesome_plugins.md b/content/v3/es/awesome-plugins/awesome_plugins.md index 0bfa40c2..7c190429 100644 --- a/content/v3/es/awesome-plugins/awesome_plugins.md +++ b/content/v3/es/awesome-plugins/awesome_plugins.md @@ -14,17 +14,23 @@ La documentación de API es crucial para cualquier API. Ayuda a los desarrollado El Monitoreo de Rendimiento de Aplicaciones (APM) es crucial para cualquier aplicación. Te ayuda a entender cómo está funcionando tu aplicación y dónde están los cuellos de botella. Hay una serie de herramientas APM que se pueden usar con Flight. - oficial [flightphp/apm](/awesome-plugins/apm) - Flight APM es una biblioteca APM simple que se puede usar para monitorear tus aplicaciones Flight. Se puede usar para monitorear el rendimiento de tu aplicación y ayudarte a identificar cuellos de botella. +## Async + +Flight ya es un framework rápido, pero agregarle un motor turbo lo hace todo más divertido (¡y desafiante)! + +- [flightphp/async](/awesome-plugins/async) - Biblioteca oficial de Flight Async. Esta biblioteca es una forma simple de agregar procesamiento asíncrono a tu aplicación. Usa Swoole/Openswoole bajo el capó para proporcionar una forma simple y efectiva de ejecutar tareas de manera asíncrona. + ## Autorización/Permisos -La Autorización y Permisos son cruciales para cualquier aplicación que requiera controles en su lugar para quién puede acceder a qué. +La autorización y los permisos son cruciales para cualquier aplicación que requiera controles en su lugar para quién puede acceder a qué. -- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca oficial de Permisos de Flight. Esta biblioteca es una forma simple de agregar permisos a nivel de usuario y aplicación a tu aplicación. +- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca oficial de Permisos de Flight. Esta biblioteca es una forma simple de agregar permisos a nivel de usuario y aplicación a tu aplicación. ## Caché -El Caché es una gran manera de acelerar tu aplicación. Hay una serie de bibliotecas de caché que se pueden usar con Flight. +El caché es una gran manera de acelerar tu aplicación. Hay una serie de bibliotecas de caché que se pueden usar con Flight. -- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Clase ligera, simple y standalone de caché en archivo PHP +- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Clase ligera, simple y autónoma de caché en archivo PHP ## CLI @@ -34,28 +40,28 @@ Las aplicaciones CLI son una gran manera de interactuar con tu aplicación. Pued ## Cookies -Las Cookies son una gran manera de almacenar pequeños bits de datos en el lado del cliente. Se pueden usar para almacenar preferencias de usuario, configuraciones de aplicación y más. +Las cookies son una gran manera de almacenar pequeños bits de datos en el lado del cliente. Se pueden usar para almacenar preferencias de usuario, configuraciones de aplicación y más. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie es una biblioteca PHP que proporciona una forma simple y efectiva de gestionar cookies. ## Depuración -La Depuración es crucial cuando estás desarrollando en tu entorno local. Hay unos pocos plugins que pueden elevar tu experiencia de depuración. +La depuración es crucial cuando estás desarrollando en tu entorno local. Hay algunos plugins que pueden elevar tu experiencia de depuración. -- [tracy/tracy](/awesome-plugins/tracy) - Esta es un manejador de errores completo que se puede usar con Flight. Tiene una serie de paneles que pueden ayudarte a depurar tu aplicación. También es muy fácil de extender y agregar tus propios paneles. -- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado con el manejador de errores [Tracy](/awesome-plugins/tracy), este plugin agrega unos pocos paneles extra para ayudar con la depuración específicamente para proyectos Flight. +- [tracy/tracy](/awesome-plugins/tracy) - Esta es una manejadora de errores completa que se puede usar con Flight. Tiene una serie de paneles que pueden ayudarte a depurar tu aplicación. También es muy fácil de extender y agregar tus propios paneles. +- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado con el manejador de errores [Tracy](/awesome-plugins/tracy), este plugin agrega algunos paneles extra para ayudar con la depuración específicamente para proyectos Flight. ## Bases de Datos -Las Bases de Datos son el núcleo de la mayoría de las aplicaciones. Así es como almacenas y recuperas datos. Algunas bibliotecas de bases de datos son simplemente wrappers para escribir consultas y otras son ORMs completos. +Las bases de datos son el núcleo de la mayoría de las aplicaciones. Así es como almacenas y recuperas datos. Algunas bibliotecas de bases de datos son simplemente envolturas para escribir consultas y otras son ORMs completos. -- oficial [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper oficial de PDO de Flight que forma parte del núcleo. Este es un wrapper simple para ayudar a simplificar el proceso de escribir consultas y ejecutarlas. No es un ORM. +- oficial [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Envoltura oficial de PDO de Flight que forma parte del núcleo. Esta es una envoltura simple para ayudar a simplificar el proceso de escribir consultas y ejecutarlas. No es un ORM. - oficial [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord oficial de Flight. Gran biblioteca pequeña para recuperar y almacenar datos fácilmente en tu base de datos. -- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para rastrear todos los cambios de base de datos para tu proyecto. +- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para mantener un seguimiento de todos los cambios de base de datos para tu proyecto. ## Encriptación -La Encriptación es crucial para cualquier aplicación que almacene datos sensibles. Encriptar y desencriptar los datos no es terriblemente difícil, pero almacenar correctamente la clave de encriptación [puede](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [ser](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difícil](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Lo más importante es nunca almacenar tu clave de encriptación en un directorio público o cometerla en tu repositorio de código. +La encriptación es crucial para cualquier aplicación que almacene datos sensibles. Encriptar y desencriptar los datos no es terriblemente difícil, pero almacenar correctamente la clave de encriptación [puede](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [ser](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difícil](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Lo más importante es nunca almacenar tu clave de encriptación en un directorio público o cometerla en tu repositorio de código. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Esta es una biblioteca que se puede usar para encriptar y desencriptar datos. Ponerse en marcha es bastante simple para comenzar a encriptar y desencriptar datos. @@ -67,23 +73,23 @@ Las colas de trabajos son realmente útiles para procesar tareas de manera asín ## Sesión -Las Sesiones no son realmente útiles para APIs, pero para construir una aplicación web, las sesiones pueden ser cruciales para mantener el estado e información de inicio de sesión. +Las sesiones no son realmente útiles para las API, pero para construir una aplicación web, las sesiones pueden ser cruciales para mantener el estado e información de inicio de sesión. -- oficial [flightphp/session](/awesome-plugins/session) - Biblioteca oficial de Sesión de Flight. Esta es una biblioteca de sesión simple que se puede usar para almacenar y recuperar datos de sesión. Usa el manejo de sesiones integrado de PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - Gestor de Sesiones PHP (no bloqueante, flash, segmento, encriptación de sesión). Usa PHP open_ssl para encriptación/desencriptación opcional de datos de sesión. +- oficial [flightphp/session](/awesome-plugins/session) - Biblioteca oficial de Sesión de Flight. Esta es una biblioteca de sesión simple que se puede usar para almacenar y recuperar datos de sesión. Usa el manejo de sesiones incorporado de PHP. +- [Ghostff/Session](/awesome-plugins/ghost-session) - Gestor de Sesión PHP (no bloqueante, flash, segmento, encriptación de sesión). Usa PHP open_ssl para encriptación/desencriptación opcional de datos de sesión. ## Plantillas -La Plantillación es el núcleo de cualquier aplicación web con una UI. Hay una serie de motores de plantillas que se pueden usar con Flight. +Las plantillas son el núcleo de cualquier aplicación web con una UI. Hay una serie de motores de plantillas que se pueden usar con Flight. - deprecado [flightphp/core View](/learn#views) - Este es un motor de plantillas muy básico que forma parte del núcleo. No se recomienda usarlo si tienes más de un par de páginas en tu proyecto. -- [latte/latte](/awesome-plugins/latte) - Latte es un motor de plantillas completo que es muy fácil de usar y se siente más cercano a la sintaxis PHP que Twig o Smarty. También es muy fácil de extender y agregar tus propios filtros y funciones. +- [latte/latte](/awesome-plugins/latte) - Latte es un motor de plantillas completo que es muy fácil de usar y se siente más cercano a la sintaxis de PHP que Twig o Smarty. También es muy fácil de extender y agregar tus propios filtros y funciones. ## Integración con WordPress -¿Quieres usar Flight en tu proyecto WordPress? ¡Hay un plugin práctico para eso! +¿Quieres usar Flight en tu proyecto de WordPress? ¡Hay un plugin práctico para eso! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Este plugin de WordPress te permite ejecutar Flight justo al lado de WordPress. Es perfecto para agregar APIs personalizadas, microservicios o incluso aplicaciones completas a tu sitio WordPress usando el framework Flight. ¡Súper útil si quieres lo mejor de ambos mundos! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Este plugin de WordPress te permite ejecutar Flight justo al lado de WordPress. Es perfecto para agregar APIs personalizadas, microservicios o incluso aplicaciones completas a tu sitio de WordPress usando el framework Flight. Súper útil si quieres lo mejor de ambos mundos! ## Contribuir diff --git a/content/v3/es/examples.md b/content/v3/es/examples.md index 0cc2555e..9fdf6c70 100644 --- a/content/v3/es/examples.md +++ b/content/v3/es/examples.md @@ -1,36 +1,37 @@ -# ¿Necesitas un comienzo rápido? +# ¿Necesitas un inicio rápido? Tienes dos opciones para comenzar con un nuevo proyecto de Flight: -- [Plantilla Completa Skeleton](https://github.com/flightphp/skeleton): Un ejemplo más completo con controladores y vistas. -- [Plantilla Skeleton en un Solo Archivo](https://github.com/flightphp/skeleton-simple): Un solo archivo que incluye todo lo que necesitas para ejecutar tu aplicación en un solo archivo sencillo. +- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Un ejemplo más completo con controladores y vistas. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Un solo archivo que incluye todo lo que necesitas para ejecutar tu aplicación en un archivo simple. -Ejemplos contribuidos por la comunidad: +Ejemplos aportados por la comunidad: -- [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP con directorios de Laravel, con herramientas PHP + GH Actions +- [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP con directorios de Laravel, con herramientas de PHP + GH Actions - [fleact](https://github.com/flightphp/fleact) - Un kit de inicio de FlightPHP con integración de ReactJS. - [flastro](https://github.com/flightphp/flastro) - Un kit de inicio de FlightPHP con integración de Astro. -- [velt](https://github.com/flightphp/velt) - Velt es una plantilla de inicio rápida y fácil de Svelte con un backend de FlightPHP. +- [velt](https://github.com/flightphp/velt) - Velt es una plantilla de inicio rápida y fácil para Svelte con un backend de FlightPHP. ## ¿Necesitas algo de inspiración? -Aunque estos no están oficialmente patrocinados por el equipo de Flight, ¡podrían darte ideas sobre cómo estructurar tus propios proyectos construidos con Flight! - -- [Decay](https://github.com/boxybird/decay) - Flight v3 con HTMX y SleekDB ¡todo sobre zombis! ([Demo](https://decay.andrewrhyand.com)) -- [Blog de Ejemplo de Flight](https://github.com/n0nag0n/flightphp-blog) - Flight v3 con Middleware, Controladores, Active Record y Latte. -- [API RESTful CRUD de Flight](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Proyecto simple de API CRUD utilizando el marco Flight, que proporciona una estructura básica para que los nuevos usuarios configuren rápidamente una aplicación PHP con operaciones CRUD y conectividad a la base de datos. El proyecto demuestra cómo usar Flight para el desarrollo de API RESTful, convirtiéndolo en una herramienta de aprendizaje ideal para principiantes y un útil kit de inicio para desarrolladores más experimentados. -- [Sistema de Gestión Escolar de Flight](https://github.com/krmu/FlightPHP_School) - Flight v3 -- [Paste Bin con Comentarios](https://github.com/n0nag0n/commie2) - Flight v3 -- [Aplicación Básica Skeleton](https://github.com/markhughes/flight-skeleton) -- [Ejemplo de Wiki](https://github.com/Skayo/FlightWiki) -- [La Aplicación del Marco PHP IT-Innovator](https://github.com/itinnovator/myphp-app) -- [LittleEducationalCMS (Español)](https://github.com/casgin/LittleEducationalCMS) -- [API de Páginas Amarillas Italianas](https://github.com/chiccomagnus/PGAPI) -- [Sistema de Gestión de Contenidos Genérico (con....muy poca documentación)](https://github.com/recepuncu/cms) -- [Un pequeño marco PHP basado en Flight y medoo.](https://github.com/ycrao/tinyme) -- [Ejemplo de Aplicación MVC](https://github.com/paddypei/Flight-MVC) -- [Modelo de vuelo listo para producción](https://github.com/madcoda9000/SecStore) - Marco de autenticación listo para producción que le ahorra semanas de desarrollo. Ofrece seguridad de nivel empresarial: 2FA/TOTP, integración con LDAP, SSO de Azure, limitación de velocidad inteligente, huellas digitales de sesión, protección contra ataques de fuerza bruta, panel de análisis de seguridad, registro de auditoría completo y control de acceso granular basado en roles. +Aunque estos no están patrocinados oficialmente por el equipo de Flight, podrían darte ideas sobre cómo estructurar tus propios proyectos construidos con Flight! + +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental es una aplicación web de alquiler de autos de una sola página, amigable con dispositivos móviles, construida con PHP (FlightPHP), JavaScript y MySQL. Soporta registro de usuarios, navegación y reserva de autos, mientras que los administradores pueden gestionar autos, usuarios y reservas. La aplicación cuenta con una API REST, autenticación JWT y un diseño responsivo para una experiencia de alquiler moderna. +- [Decay](https://github.com/boxybird/decay) - Flight v3 con HTMX y SleekDB, todo sobre zombis! ([Demo](https://decay.andrewrhyand.com)) +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 con Middleware, Controladores, Active Record y Latte. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Proyecto de API CRUD simple utilizando el framework Flight, que proporciona una estructura básica para que los nuevos usuarios configuren rápidamente una aplicación PHP con operaciones CRUD y conectividad a la base de datos. El proyecto demuestra cómo usar Flight para el desarrollo de API RESTful, lo que lo convierte en una herramienta de aprendizaje ideal para principiantes y un kit de inicio útil para desarrolladores más experimentados. +- [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 +- [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 +- [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) +- [Example Wiki](https://github.com/Skayo/FlightWiki) +- [The IT-Innovator PHP Framework Application](https://github.com/itinnovator/myphp-app) +- [LittleEducationalCMS (Spanish)](https://github.com/casgin/LittleEducationalCMS) +- [Italian Yellow Pages API](https://github.com/chiccomagnus/PGAPI) +- [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) +- [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) +- [Example MVC Application](https://github.com/paddypei/Flight-MVC) +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework de autenticación listo para producción que te ahorra semanas de desarrollo. Características de seguridad de grado empresarial: 2FA/TOTP, integración LDAP, SSO de Azure, limitación de velocidad inteligente, huella dactilar de sesión, protección contra fuerza bruta, panel de análisis de seguridad, registro de auditoría completo y control de acceso basado en roles granular. ## ¿Quieres compartir tu propio ejemplo? -Si tienes un proyecto que deseas compartir, ¡envía una solicitud de extracción para agregarlo a esta lista! \ No newline at end of file +Si tienes un proyecto que quieres compartir, ¡por favor envía una solicitud de pull para agregarlo a esta lista! \ No newline at end of file diff --git a/content/v3/es/learn/requests.md b/content/v3/es/learn/requests.md index c5a38a05..8fd20d40 100644 --- a/content/v3/es/learn/requests.md +++ b/content/v3/es/learn/requests.md @@ -8,21 +8,21 @@ Flight encapsula la solicitud HTTP en un solo objeto, que se puede acceder hacie $request = Flight::request(); ``` -## Entendiendo +## Comprensión -Las solicitudes HTTP son uno de los aspectos principales a entender sobre el ciclo de vida de HTTP. Un usuario realiza una acción en un navegador web o un cliente HTTP, y envían una serie de encabezados, cuerpo, URL, etc. a tu proyecto. Puedes capturar estos encabezados (el idioma del navegador, qué tipo de compresión pueden manejar, el agente de usuario, etc.) y capturar el cuerpo y la URL que se envía a tu aplicación Flight. Estas solicitudes son esenciales para que tu app entienda qué hacer a continuación. +Las solicitudes HTTP son uno de los aspectos centrales para entender sobre el ciclo de vida de HTTP. Un usuario realiza una acción en un navegador web o un cliente HTTP, y envían una serie de encabezados, cuerpo, URL, etc. a su proyecto. Puede capturar estos encabezados (el idioma del navegador, qué tipo de compresión pueden manejar, el agente de usuario, etc.) y capturar el cuerpo y la URL que se envía a su aplicación Flight. Estas solicitudes son esenciales para que su app entienda qué hacer a continuación. -## Uso Básico +## Uso básico -PHP tiene varios super globals incluyendo `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` y `$_COOKIE`. Flight abstrae estos en prácticas [Collections](/learn/collections). Puedes acceder a las propiedades `query`, `data`, `cookies` y `files` como arrays o objetos. +PHP tiene varios super globals incluyendo `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` y `$_COOKIE`. Flight abstrae estos en colecciones prácticas [Collections](/learn/collections). Puede acceder a las propiedades `query`, `data`, `cookies` y `files` como arrays u objetos. -> **Nota:** Se **DESACONSEJA EN ALTO GRADO** usar estos super globals en tu proyecto y deben ser referenciados a través del objeto `request()`. +> **Nota:** Se **DESACONSEJA EN GRAN MEDIDA** usar estos super globals en su proyecto y deben referenciarse a través del objeto `request()`. > **Nota:** No hay abstracción disponible para `$_ENV`. ### `$_GET` -Puedes acceder al array `$_GET` a través de la propiedad `query`: +Puede acceder al array `$_GET` a través de la propiedad `query`: ```php // GET /search?keyword=something @@ -30,14 +30,14 @@ Flight::route('/search', function(){ $keyword = Flight::request()->query['keyword']; // o $keyword = Flight::request()->query->keyword; - echo "Estás buscando: $keyword"; + echo "You are searching for: $keyword"; // consultar una base de datos o algo más con el $keyword }); ``` ### `$_POST` -Puedes acceder al array `$_POST` a través de la propiedad `data`: +Puede acceder al array `$_POST` a través de la propiedad `data`: ```php Flight::route('POST /submit', function(){ @@ -46,14 +46,14 @@ Flight::route('POST /submit', function(){ // o $name = Flight::request()->data->name; $email = Flight::request()->data->email; - echo "Enviaste: $name, $email"; + echo "You submitted: $name, $email"; // guardar en una base de datos o algo más con el $name y $email }); ``` ### `$_COOKIE` -Puedes acceder al array `$_COOKIE` a través de la propiedad `cookies`: +Puede acceder al array `$_COOKIE` a través de la propiedad `cookies`: ```php Flight::route('GET /login', function(){ @@ -68,7 +68,7 @@ Flight::route('GET /login', function(){ }); ``` -Para ayuda sobre cómo establecer nuevos valores de cookies, consulta [overclokk/cookie](/awesome-plugins/php-cookie) +Para obtener ayuda sobre cómo establecer nuevos valores de cookies, vea [overclokk/cookie](/awesome-plugins/php-cookie) ### `$_SERVER` @@ -81,37 +81,37 @@ $host = Flight::request()->getVar('HTTP_HOST'); ### `$_FILES` -Puedes acceder a los archivos subidos a través de la propiedad `files`: +Puede acceder a los archivos subidos a través de la propiedad `files`: ```php -// acceso directo a la propiedad $_FILES. Ver abajo para el enfoque recomendado +// acceso crudo a la propiedad $_FILES. Vea abajo para el enfoque recomendado $uploadedFile = Flight::request()->files['myFile']; // o $uploadedFile = Flight::request()->files->myFile; ``` -Consulta [Uploaded File Handler](/learn/uploaded-file) para más información. +Vea [Uploaded File Handler](/learn/uploaded-file) para más información. -#### Procesamiento de Subidas de Archivos +#### Procesamiento de subidas de archivos _v3.12.0_ -Puedes procesar subidas de archivos usando el framework con algunos métodos de ayuda. Básicamente se reduce a extraer los datos del archivo de la solicitud y moverlo a una nueva ubicación. +Puede procesar subidas de archivos usando el framework con algunos métodos de ayuda. Básicamente se reduce a extraer los datos del archivo de la solicitud y moverlo a una nueva ubicación. ```php Flight::route('POST /upload', function(){ - // Si tenías un campo de entrada como + // Si tenía un campo de entrada como $uploadedFileData = Flight::request()->getUploadedFiles(); $uploadedFile = $uploadedFileData['myFile']; $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); }); ``` -Si tienes múltiples archivos subidos, puedes iterar a través de ellos: +Si tiene múltiples archivos subidos, puede iterar a través de ellos: ```php Flight::route('POST /upload', function(){ - // Si tenías un campo de entrada como + // Si tenía un campo de entrada como $uploadedFiles = Flight::request()->getUploadedFiles()['myFiles']; foreach ($uploadedFiles as $uploadedFile) { $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); @@ -119,11 +119,11 @@ Flight::route('POST /upload', function(){ }); ``` -> **Nota de Seguridad:** Siempre valida y sanitiza la entrada del usuario, especialmente al tratar con subidas de archivos. Siempre valida el tipo de extensiones que permitirás subir, pero también debes validar los "magic bytes" del archivo para asegurarte de que realmente es el tipo de archivo que el usuario afirma que es. Hay [artículos](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [y](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [bibliotecas](https://github.com/RikudouSage/MimeTypeDetector) disponibles para ayudar con esto. +> **Nota de seguridad:** Siempre valide y sanitice la entrada del usuario, especialmente al tratar con subidas de archivos. Siempre valide el tipo de extensiones que permitirá subir, pero también debe validar los "magic bytes" del archivo para asegurar que realmente sea el tipo de archivo que el usuario afirma que es. Hay [artículos](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [y](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [bibliotecas](https://github.com/RikudouSage/MimeTypeDetector) disponibles para ayudar con esto. -### Cuerpo de la Solicitud +### Cuerpo de la solicitud -Para obtener el cuerpo crudo de la solicitud HTTP, por ejemplo al tratar con solicitudes POST/PUT, puedes hacer: +Para obtener el cuerpo crudo de la solicitud HTTP, por ejemplo al tratar con solicitudes POST/PUT, puede hacer: ```php Flight::route('POST /users/xml', function(){ @@ -134,32 +134,32 @@ Flight::route('POST /users/xml', function(){ ### Cuerpo JSON -Si recibes una solicitud con el tipo de contenido `application/json` y los datos de ejemplo `{"id": 123}`, estará disponible desde la propiedad `data`: +Si recibe una solicitud con el tipo de contenido `application/json` y los datos de ejemplo `{"id": 123}`, estará disponible desde la propiedad `data`: ```php $id = Flight::request()->data->id; ``` -### Encabezados de la Solicitud +### Encabezados de la solicitud -Puedes acceder a los encabezados de la solicitud usando el método `getHeader()` o `getHeaders()`: +Puede acceder a los encabezados de la solicitud usando el método `getHeader()` o `getHeaders()`: ```php -// Tal vez necesites el encabezado Authorization +// Tal vez necesite el encabezado Authorization $host = Flight::request()->getHeader('Authorization'); // o $host = Flight::request()->header('Authorization'); -// Si necesitas obtener todos los encabezados +// Si necesita obtener todos los encabezados $headers = Flight::request()->getHeaders(); // o $headers = Flight::request()->headers(); ``` -### Método de la Solicitud +### Método de la solicitud -Puedes acceder al método de la solicitud usando la propiedad `method` o el método `getMethod()`: +Puede acceder al método de la solicitud usando la propiedad `method` o el método `getMethod()`: ```php $method = Flight::request()->method; // realmente poblado por getMethod() @@ -168,7 +168,7 @@ $method = Flight::request()->getMethod(); **Nota:** El método `getMethod()` primero extrae el método de `$_SERVER['REQUEST_METHOD']`, luego puede ser sobrescrito por `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` si existe o `$_REQUEST['_method']` si existe. -## Propiedades del Objeto de Solicitud +## Propiedades del objeto de solicitud El objeto de solicitud proporciona las siguientes propiedades: @@ -193,49 +193,49 @@ El objeto de solicitud proporciona las siguientes propiedades: - **host** - El nombre de host de la solicitud - **servername** - El SERVER_NAME de `$_SERVER` -## Métodos de Ayuda +## Métodos de ayuda -Hay un par de métodos de ayuda para ensamblar partes de una URL o tratar con ciertos encabezados. +Hay algunos métodos de ayuda para ensamblar partes de una URL o tratar con ciertos encabezados. -### URL Completa +### URL completa -Puedes acceder a la URL completa de la solicitud usando el método `getFullUrl()`: +Puede acceder a la URL completa de la solicitud usando el método `getFullUrl()`: ```php $url = Flight::request()->getFullUrl(); // https://example.com/some/path?foo=bar ``` -### URL Base +### URL base -Puedes acceder a la URL base usando el método `getBaseUrl()`: +Puede acceder a la URL base usando el método `getBaseUrl()`: ```php // http://example.com/path/to/something/cool?query=yes+thanks $url = Flight::request()->getBaseUrl(); // https://example.com -// Nota, sin barra final. +// Note, no trailing slash. ``` -## Análisis de Consultas +## Análisis de consultas -Puedes pasar una URL al método `parseQuery()` para analizar la cadena de consulta en un array asociativo: +Puede pasar una URL al método `parseQuery()` para analizar la cadena de consulta en un array asociativo: ```php $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` -## Negociación de Tipos de Contenido Aceptados +## Negociación de tipos de aceptación de contenido _v3.17.2_ -Puedes usar el método `negotiateContentType()` para determinar el mejor tipo de contenido para responder basado en el encabezado `Accept` enviado por el cliente. +Puede usar el método `negotiateContentType()` para determinar el mejor tipo de contenido para responder basado en el encabezado `Accept` enviado por el cliente. ```php // Ejemplo de encabezado Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 -// Lo de abajo define lo que soportas. +// Lo de abajo define lo que soporta. $availableTypes = ['application/json', 'application/xml']; $typeToServe = Flight::request()->negotiateContentType($availableTypes); if ($typeToServe === 'application/json') { @@ -243,23 +243,23 @@ if ($typeToServe === 'application/json') { } elseif ($typeToServe === 'application/xml') { // Servir respuesta XML } else { - // Por defecto a algo más o lanzar un error + // Por defecto algo más o lanzar un error } ``` > **Nota:** Si ninguno de los tipos disponibles se encuentra en el encabezado `Accept`, el método retornará `null`. Si no hay encabezado `Accept` definido, el método retornará el primer tipo en el array `$availableTypes`. -## Ver También -- [Routing](/learn/routing) - Ver cómo mapear rutas a controladores y renderizar vistas. +## Ver también +- [Routing](/learn/routing) - Vea cómo mapear rutas a controladores y renderizar vistas. - [Responses](/learn/responses) - Cómo personalizar respuestas HTTP. -- [Why a Framework?](/learn/why-frameworks) - Cómo encajan las solicitudes en el panorama general. +- [Why a Framework?](/learn/why-frameworks) - Cómo las solicitudes encajan en el panorama general. - [Collections](/learn/collections) - Trabajando con colecciones de datos. - [Uploaded File Handler](/learn/uploaded-file) - Manejo de subidas de archivos. -## Solución de Problemas -- `request()->ip` y `request()->proxy_ip` pueden ser diferentes si tu servidor web está detrás de un proxy, balanceador de carga, etc. +## Solución de problemas +- `request()->ip` y `request()->proxy_ip` pueden ser diferentes si su servidor web está detrás de un proxy, balanceador de carga, etc. -## Registro de Cambios +## Registro de cambios - v3.17.2 - Agregado negotiateContentType() -- v3.12.0 - Agregada la capacidad para manejar subidas de archivos a través del objeto de solicitud. +- v3.12.0 - Agregada capacidad para manejar subidas de archivos a través del objeto de solicitud. - v1.0 - Lanzamiento inicial. \ No newline at end of file diff --git a/content/v3/es/learn/routing.md b/content/v3/es/learn/routing.md index b4d2ba7a..3d7db630 100644 --- a/content/v3/es/learn/routing.md +++ b/content/v3/es/learn/routing.md @@ -4,9 +4,9 @@ El enrutamiento en Flight PHP mapea patrones de URL a funciones de devolución de llamada o métodos de clase, permitiendo un manejo rápido y simple de solicitudes. Está diseñado para un overhead mínimo, un uso amigable para principiantes y extensibilidad sin dependencias externas. ## Comprensión -El enrutamiento es el mecanismo central que conecta las solicitudes HTTP con la lógica de su aplicación en Flight. Al definir rutas, especifica cómo diferentes URLs activan código específico, ya sea a través de funciones, métodos de clase o acciones de controladores. El sistema de enrutamiento de Flight es flexible, soporta patrones básicos, parámetros con nombre, expresiones regulares y características avanzadas como inyección de dependencias y enrutamiento de recursos. Este enfoque mantiene su código organizado y fácil de mantener, mientras permanece rápido y simple para principiantes y extensible para usuarios avanzados. +El enrutamiento es el mecanismo central que conecta las solicitudes HTTP con la lógica de tu aplicación en Flight. Al definir rutas, especificas cómo diferentes URLs activan código específico, ya sea a través de funciones, métodos de clase o acciones de controladores. El sistema de enrutamiento de Flight es flexible, soporta patrones básicos, parámetros con nombre, expresiones regulares y características avanzadas como inyección de dependencias y enrutamiento con recursos. Este enfoque mantiene tu código organizado y fácil de mantener, mientras permanece rápido y simple para principiantes y extensible para usuarios avanzados. -> **Nota:** ¿Quieres entender más sobre el enrutamiento? Revisa la página ["por qué un framework?"](/learn/why-frameworks) para una explicación más detallada. +> **Nota:** ¿Quieres entender más sobre enrutamiento? Consulta la página ["¿por qué un framework?"](/learn/why-frameworks) para una explicación más detallada. ## Uso Básico @@ -110,12 +110,12 @@ Flight::route('GET|POST /', function () { ### Manejo Especial para Solicitudes HEAD y OPTIONS -Flight proporciona manejo integrado para solicitudes HTTP `HEAD` y `OPTIONS`: +Flight proporciona un manejo integrado para solicitudes HTTP `HEAD` y `OPTIONS`: #### Solicitudes HEAD -- Las **solicitudes HEAD** se tratan igual que las solicitudes `GET`, pero Flight automáticamente elimina el cuerpo de la respuesta antes de enviarlo al cliente. -- Esto significa que puedes definir una ruta para `GET`, y las solicitudes HEAD a la misma URL devolverán solo encabezados (sin contenido), como se espera en los estándares HTTP. +- Las **solicitudes HEAD** se tratan igual que las solicitudes `GET`, pero Flight elimina automáticamente el cuerpo de la respuesta antes de enviarla al cliente. +- Esto significa que puedes definir una ruta para `GET`, y las solicitudes HEAD a la misma URL devolverán solo encabezados (sin contenido), como se espera según los estándares HTTP. ```php Flight::route('GET /info', function() { @@ -128,7 +128,7 @@ Flight::route('GET /info', function() { Las solicitudes `OPTIONS` son manejadas automáticamente por Flight para cualquier ruta definida. - Cuando se recibe una solicitud OPTIONS, Flight responde con un estado `204 No Content` y un encabezado `Allow` que lista todos los métodos HTTP soportados para esa ruta. -- No necesitas definir una ruta separada para OPTIONS a menos que quieras un comportamiento personalizado o modificar la respuesta. +- No necesitas definir una ruta separada para OPTIONS. ```php // Para una ruta definida como: @@ -142,7 +142,7 @@ Flight::route('GET|POST /users', function() { /* ... */ }); ### Usando el Objeto Router -Adicionalmente, puedes obtener el objeto Router que tiene algunos métodos auxiliares para que uses: +Además, puedes obtener el objeto Router que tiene algunos métodos auxiliares para usar: ```php @@ -175,7 +175,7 @@ Flight::route('/user/[0-9]+', function () { Aunque este método está disponible, se recomienda usar parámetros con nombre, o parámetros con nombre con expresiones regulares, ya que son más legibles y fáciles de mantener. ### Parámetros con Nombre -Puedes especificar parámetros con nombre en tus rutas que se pasarán a tu función de devolución de llamada. **Esto es más para la legibilidad de la ruta que para cualquier otra cosa. Por favor, ve la sección a continuación sobre la advertencia importante.** +Puedes especificar parámetros con nombre en tus rutas que se pasarán a tu función de devolución de llamada. **Esto es más para la legibilidad de la ruta que para cualquier otra cosa. Por favor, ve la sección a continuación sobre una advertencia importante.** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -192,11 +192,11 @@ Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { }); ``` -> **Nota:** Coincidir grupos regex `()` con parámetros posicionales no está soportado. Ej: `:'\(` +> **Nota:** La coincidencia de grupos regex `()` con parámetros posicionales no está soportada. Ej: `:'\(` #### Advertencia Importante -Aunque en el ejemplo anterior, parece que `@name` está directamente ligado a la variable `$name`, no es así. El orden de los parámetros en la función de devolución de llamada es lo que determina qué se pasa a ella. Si cambiaras el orden de los parámetros en la función de devolución de llamada, las variables también se cambiarían. Aquí hay un ejemplo: +Aunque en el ejemplo anterior, parece que `@name` está directamente ligado a la variable `$name`, no lo está. El orden de los parámetros en la función de devolución de llamada es lo que determina qué se pasa a ella. Si cambiaras el orden de los parámetros en la función de devolución de llamada, las variables también se cambiarían. Aquí hay un ejemplo: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -205,7 +205,7 @@ Flight::route('/@name/@id', function (string $id, string $name) { ``` Y si fueras a la siguiente URL: `/bob/123`, la salida sería `hello, 123 (bob)!`. -_Por favor ten cuidado_ cuando estés configurando tus rutas y tus funciones de devolución de llamada! +_¡Por favor ten cuidado_ cuando configures tus rutas y tus funciones de devolución de llamada! ### Parámetros Opcionales Puedes especificar parámetros con nombre que sean opcionales para la coincidencia envolviendo segmentos en paréntesis. @@ -297,7 +297,7 @@ Flight::map('methodNotFound', function(Route $route) { ## Uso Avanzado ### Inyección de Dependencias en Rutas -Si quieres usar inyección de dependencias a través de un contenedor (PSR-11, PHP-DI, Dice, etc.), el único tipo de rutas donde eso está disponible es ya sea creando directamente el objeto tú mismo y usando el contenedor para crear tu objeto o puedes usar strings para definir la clase y el método a llamar. Puedes ir a la página de [Inyección de Dependencias](/learn/dependency-injection-container) para más información. +Si quieres usar inyección de dependencias a través de un contenedor (PSR-11, PHP-DI, Dice, etc.), el único tipo de rutas donde eso está disponible es creando directamente el objeto tú mismo y usando el contenedor para crear tu objeto o puedes usar cadenas para definir la clase y el método a llamar. Puedes ir a la página de [Inyección de Dependencias](/learn/dependency-injection-container) para más información. Aquí hay un ejemplo rápido: @@ -326,7 +326,7 @@ class Greeting // Ve la página de Inyección de Dependencias para más información sobre PSR-11 $dice = new \Dice\Dice(); -// No olvides reasignar la variable con '$dice = '!!!!! +// ¡No olvides reasignar la variable con '$dice = '!!!!! $dice = $dice->addRule('flight\database\PdoWrapper', [ 'shared' => true, 'constructParams' => [ @@ -372,7 +372,7 @@ Flight::route('/user/*', function () { Ahora se recomienda usar [middleware](/learn/middleware) para manejar casos de uso complejos como este. ### Alias de Ruta -Al asignar un alias a una ruta, puedes llamar después a ese alias en tu app dinámicamente para que se genere más tarde en tu código (ej: un enlace en una plantilla HTML, o generando una URL de redirección). +Al asignar un alias a una ruta, puedes llamar más tarde ese alias en tu aplicación dinámicamente para que se genere después en tu código (ej: un enlace en una plantilla HTML, o generando una URL de redirección). ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); @@ -393,10 +393,10 @@ class UserController { ``` -Esto es especialmente útil si tu URL sucede cambiar. En el ejemplo anterior, digamos que users se movió a `/admin/users/@id` en su lugar. +Esto es especialmente útil si tu URL cambia. En el ejemplo anterior, supongamos que users se movió a `/admin/users/@id` en su lugar. Con el alias en su lugar para la ruta, ya no necesitas encontrar todas las URLs antiguas en tu código y cambiarlas porque el alias ahora devolverá `/admin/users/5` como en el ejemplo anterior. -El alias de ruta aún funciona en grupos también: +El alias de ruta todavía funciona en grupos también: ```php Flight::group('/users', function() { @@ -429,7 +429,7 @@ Flight::route('/', function() { // Contiene el contenido de cualquier '*' usado en el patrón de URL $route->splat; - // Muestra la ruta de URL....si realmente la necesitas + // Muestra la ruta de la url....si realmente la necesitas $route->pattern; // Muestra qué middleware está asignado a esto @@ -440,7 +440,7 @@ Flight::route('/', function() { }); ``` -> **Nota:** La propiedad `executedRoute` solo se establecerá después de que una ruta haya sido ejecutada. Si intentas acceder a ella antes de que una ruta haya sido ejecutada, será `NULL`. También puedes usar executedRoute en [middleware](/learn/middleware)! +> **Nota:** La propiedad `executedRoute` solo se establecerá después de que una ruta haya sido ejecutada. Si intentas acceder a ella antes de que una ruta haya sido ejecutada, será `NULL`. También puedes usar executedRoute en [middleware](/learn/middleware) ¡también! #### Pasar `true` a la definición de ruta ```php @@ -457,7 +457,7 @@ Flight::route('/', function(\flight\net\Route $route) { // Contiene el contenido de cualquier '*' usado en el patrón de URL $route->splat; - // Muestra la ruta de URL....si realmente la necesitas + // Muestra la ruta de la url....si realmente la necesitas $route->pattern; // Muestra qué middleware está asignado a esto @@ -548,7 +548,7 @@ Flight::group('/api/v1', function () { Ver más detalles en la página de [middleware de grupo](/learn/middleware#grouping-middleware). -### Enrutamiento de Recursos +### Enrutamiento con Recursos Puedes crear un conjunto de rutas para un recurso usando el método `resource`. Esto creará un conjunto de rutas para un recurso que sigue las convenciones RESTful. Para crear un recurso, haz lo siguiente: @@ -557,7 +557,7 @@ Para crear un recurso, haz lo siguiente: Flight::resource('/users', UsersController::class); ``` -Y lo que sucederá en el fondo es que creará las siguientes rutas: +Y lo que sucederá en segundo plano es que creará las siguientes rutas: ```php [ @@ -612,16 +612,16 @@ class UsersController Hay algunas opciones para configurar las rutas de recursos. -##### Base de Alias +##### Alias Base Puedes configurar el `aliasBase`. Por defecto, el alias es la última parte de la URL especificada. -Por ejemplo `/users/` resultaría en un `aliasBase` de `users`. Cuando se crean estas rutas, los alias son `users.index`, `users.create`, etc. Si quieres cambiar el alias, establece el `aliasBase` al valor que quieras. +Por ejemplo, `/users/` resultaría en un `aliasBase` de `users`. Cuando se crean estas rutas, los alias son `users.index`, `users.create`, etc. Si quieres cambiar el alias, establece el `aliasBase` al valor que quieras. ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); ``` -##### Only y Except +##### Solo y Excepto También puedes especificar qué rutas quieres crear usando las opciones `only` y `except`. @@ -649,13 +649,13 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid Ahora puedes transmitir respuestas al cliente usando `stream()` o `streamWithHeaders()`. Esto es útil para enviar archivos grandes, procesos de larga duración o generar respuestas grandes. -Transmitir una ruta se maneja un poco diferente que una ruta regular. +Transmitir una ruta se maneja un poco diferente a una ruta regular. > **Nota:** Las respuestas en streaming solo están disponibles si tienes [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) establecido en `false`. #### Streaming con Encabezados Manuales -Puedes transmitir una respuesta al cliente usando el método `stream()` en una ruta. Si haces esto, debes establecer todos los encabezados a mano antes de que salgas cualquier cosa al cliente. +Puedes transmitir una respuesta al cliente usando el método `stream()` en una ruta. Si haces esto, debes establecer todos los encabezados a mano antes de que salgas algo al cliente. Esto se hace con la función php `header()` o el método `Flight::response()->setRealHeader()`. ```php @@ -667,7 +667,7 @@ Flight::route('/@filename', function($filename) { $fileNameSafe = basename($filename); // Si tienes encabezados adicionales para establecer aquí después de que la ruta se haya ejecutado - // debes definirlos antes de que se haga eco de cualquier cosa. + // debes definirlos antes de que nada se haga eco. // Deben ser todos una llamada cruda a la función header() o // una llamada a Flight::response()->setRealHeader() header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); @@ -728,22 +728,22 @@ Flight::route('/stream-users', function() { ``` ## Ver También -- [Middleware](/learn/middleware) - Usando middleware con rutas para autenticación, logging, etc. +- [Middleware](/learn/middleware) - Usando middleware con rutas para autenticación, registro, etc. - [Inyección de Dependencias](/learn/dependency-injection-container) - Simplificando la creación y gestión de objetos en rutas. - [¿Por qué un Framework?](/learn/why-frameworks) - Entendiendo los beneficios de usar un framework como Flight. - [Extensión](/learn/extending) - Cómo extender Flight con tu propia funcionalidad incluyendo el método `notFound`. - [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - Función PHP para coincidencia de expresiones regulares. ## Solución de Problemas -- Los parámetros de ruta se coinciden por orden, no por nombre. Asegúrate de que el orden de los parámetros de devolución de llamada coincida con la definición de ruta. +- Los parámetros de ruta se coinciden por orden, no por nombre. Asegúrate de que el orden de los parámetros de la devolución de llamada coincida con la definición de la ruta. - Usar `Flight::get()` no define una ruta; usa `Flight::route('GET /...')` para enrutamiento o el contexto del objeto Router en grupos (ej. `$router->get(...)`). -- La propiedad executedRoute solo se establece después de que una ruta se ejecute; es NULL antes de la ejecución. -- El streaming requiere que la funcionalidad de buffering de salida legacy de Flight esté deshabilitada (`flight.v2.output_buffering = false`). +- La propiedad executedRoute solo se establece después de que una ruta se ejecuta; es NULL antes de la ejecución. +- El streaming requiere que la funcionalidad de búfer de salida legacy de Flight esté deshabilitada (`flight.v2.output_buffering = false`). - Para inyección de dependencias, solo ciertas definiciones de ruta soportan instanciación basada en contenedor. ### 404 No Encontrado o Comportamiento de Ruta Inesperado -Si estás viendo un error 404 No Encontrado (pero juras por tu vida que realmente está ahí y no es un error tipográfico) esto en realidad podría ser un problema con que devuelves un valor en tu punto final de ruta en lugar de solo hacer eco de él. La razón para esto es intencional pero podría sorprender a algunos desarrolladores. +Si estás viendo un error 404 No Encontrado (pero juras por tu vida que realmente está ahí y no es un error tipográfico), esto en realidad podría ser un problema con que devuelves un valor en tu punto final de ruta en lugar de solo hacer eco de él. La razón para esto es intencional pero podría sorprender a algunos desarrolladores. ```php Flight::route('/hello', function(){ @@ -761,5 +761,5 @@ La razón para esto es por un mecanismo especial incorporado en el router que ma Puedes ver el comportamiento documentado en la sección de [Enrutamiento](/learn/routing#passing). ## Registro de Cambios -- v3: Agregado enrutamiento de recursos, alias de ruta y soporte de streaming, grupos de rutas y soporte de middleware. -- v1: La vasta mayoría de características básicas disponibles. \ No newline at end of file +- v3: Agregado enrutamiento con recursos, alias de ruta y soporte para streaming, grupos de ruta y soporte para middleware. +- v1: La gran mayoría de características básicas disponibles. \ No newline at end of file diff --git a/content/v3/fr/awesome-plugins/async.md b/content/v3/fr/awesome-plugins/async.md new file mode 100644 index 00000000..0a2cf628 --- /dev/null +++ b/content/v3/fr/awesome-plugins/async.md @@ -0,0 +1,212 @@ +# Async + +Async est un petit package pour le framework Flight qui vous permet d'exécuter vos applications Flight dans des serveurs et des runtimes asynchrones comme Swoole, AdapterMan, ReactPHP, Amp, RoadRunner, Workerman, etc. Par défaut, il inclut des adaptateurs pour Swoole et AdapterMan. + +L'objectif : développer et déboguer avec PHP-FPM (ou le serveur intégré) et passer à Swoole (ou un autre pilote asynchrone) pour la production avec des changements minimaux. + +## Exigences + +- PHP 7.4 ou supérieur +- Framework Flight 3.16.1 ou supérieur +- [Extension Swoole](https://www.openswoole.com) + +## Installation + +Installez via Composer : + +```bash +composer require flightphp/async +``` + +Si vous prévoyez d'exécuter avec Swoole, installez l'extension : + +```bash +# en utilisant pecl +pecl install swoole +# ou openswoole +pecl install openswoole + +# ou avec un gestionnaire de paquets (exemple Debian/Ubuntu) +sudo apt-get install php-swoole +``` + +## Exemple rapide avec Swoole + +Voici ci-dessous une configuration minimale qui montre comment supporter à la fois PHP-FPM (ou le serveur intégré) et Swoole en utilisant le même code source. + +Fichiers dont vous aurez besoin dans votre projet : + +- index.php +- swoole_server.php +- SwooleServerDriver.php + +### index.php + +Ce fichier est un simple interrupteur qui force l'application à s'exécuter en mode PHP pour le développement. + +```php +// index.php +route('/', function() use ($app) { + $app->json(['hello' => 'world']); +}); + +if (!defined('NOT_SWOOLE')) { + // Require the SwooleServerDriver class when running in Swoole mode. + require_once __DIR__ . '/SwooleServerDriver.php'; + + Swoole\Runtime::enableCoroutine(); + $Swoole_Server = new SwooleServerDriver('127.0.0.1', 9501, $app); + $Swoole_Server->start(); +} else { + $app->start(); +} +``` + +### SwooleServerDriver.php + +Un pilote concis montrant comment relier les requêtes Swoole à Flight en utilisant AsyncBridge et les adaptateurs Swoole. + +```php +// SwooleServerDriver.php +Swoole = new SwooleServer($host, $port); + $this->app = $app; + + $this->setDefault(); + $this->bindWorkerEvents(); + $this->bindHttpEvent(); + } + + protected function setDefault() { + $this->Swoole->set([ + 'daemonize' => false, + 'dispatch_mode' => 1, + 'max_request' => 8000, + 'open_tcp_nodelay' => true, + 'reload_async' => true, + 'max_wait_time' => 60, + 'enable_reuse_port' => true, + 'enable_coroutine' => true, + 'http_compression' => false, + 'enable_static_handler' => true, + 'document_root' => __DIR__, + 'static_handler_locations' => ['/css', '/js', '/images', '/.well-known'], + 'buffer_output_size' => 4 * 1024 * 1024, + 'worker_num' => 4, + ]); + + $app = $this->app; + $app->map('stop', function (?int $code = null) use ($app) { + if ($code !== null) { + $app->response()->status($code); + } + }); + } + + protected function bindHttpEvent() { + $app = $this->app; + $AsyncBridge = new AsyncBridge($app); + + $this->Swoole->on('Start', function(SwooleServer $server) { + echo "Swoole http server is started at http://127.0.0.1:9501\n"; + }); + + $this->Swoole->on('Request', function (SwooleRequest $request, SwooleResponse $response) use ($AsyncBridge) { + $SwooleAsyncRequest = new SwooleAsyncRequest($request); + $SwooleAsyncResponse = new SwooleAsyncResponse($response); + + $AsyncBridge->processRequest($SwooleAsyncRequest, $SwooleAsyncResponse); + + $response->end(); + gc_collect_cycles(); + }); + } + + protected function bindWorkerEvents() { + $createPools = function() { + // create worker-specific connection pools here + }; + $closePools = function() { + // close pools / cleanup here + }; + $this->Swoole->on('WorkerStart', $createPools); + $this->Swoole->on('WorkerStop', $closePools); + $this->Swoole->on('WorkerError', $closePools); + } + + public function start() { + $this->Swoole->start(); + } +} +``` + +## Exécution du serveur + +- Développement (serveur intégré PHP / PHP-FPM) : + - php -S localhost:8000 (ou ajoutez -t public/ si votre index est dans public/) +- Production (Swoole) : + - php swoole_server.php + +Astuce : Pour la production, utilisez un proxy inverse (Nginx) devant Swoole pour gérer TLS, les fichiers statiques et l'équilibrage de charge. + +## Notes de configuration + +Le pilote Swoole expose plusieurs options de configuration : +- worker_num : nombre de processus workers +- max_request : requêtes par worker avant redémarrage +- enable_coroutine : utilisation des coroutines pour la concurrence +- buffer_output_size : taille du tampon de sortie + +Ajustez ces paramètres en fonction des ressources de votre hôte et des schémas de trafic. + +## Gestion des erreurs + +AsyncBridge traduit les erreurs Flight en réponses HTTP appropriées. Vous pouvez également ajouter une gestion d'erreurs au niveau des routes : + +```php +$app->route('/*', function() use ($app) { + try { + // route logic + } catch (Exception $e) { + $app->response()->status(500); + $app->json(['error' => $e->getMessage()]); + } +}); +``` + +## AdapterMan et autres runtimes + +[AdapterMan](https://github.com/joanhey/adapterman) est supporté en tant qu'adaptateur de runtime alternatif. Le package est conçu pour être adaptable — ajouter ou utiliser d'autres adaptateurs suit généralement le même schéma : convertir la requête/réponse du serveur en requête/réponse Flight via AsyncBridge et les adaptateurs spécifiques au runtime. \ No newline at end of file diff --git a/content/v3/fr/awesome-plugins/awesome_plugins.md b/content/v3/fr/awesome-plugins/awesome_plugins.md index a808bd53..797523c3 100644 --- a/content/v3/fr/awesome-plugins/awesome_plugins.md +++ b/content/v3/fr/awesome-plugins/awesome_plugins.md @@ -1,22 +1,28 @@ -# Plugins Incroyables +# Plugins Géniaux -Flight est incroyablement extensible. Il existe un certain nombre de plugins qui peuvent être utilisés pour ajouter des fonctionnalités à votre application Flight. Certains sont officiellement pris en charge par l'équipe Flight et d'autres sont des bibliothèques micro/lite pour vous aider à démarrer. +Flight est incroyablement extensible. Il existe un certain nombre de plugins qui peuvent être utilisés pour ajouter des fonctionnalités à votre application Flight. Certains sont officiellement supportés par l'équipe Flight et d'autres sont des bibliothèques micro/lite pour vous aider à démarrer. ## Documentation API La documentation API est cruciale pour toute API. Elle aide les développeurs à comprendre comment interagir avec votre API et ce qu'ils peuvent attendre en retour. Il existe quelques outils disponibles pour vous aider à générer la documentation API pour vos projets Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Article de blog écrit par Daniel Schreiber sur la façon d'utiliser la spécification OpenAPI avec FlightPHP pour construire votre API en adoptant une approche API-first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI est un excellent outil pour vous aider à générer la documentation API pour vos projets Flight. Il est très facile à utiliser et peut être personnalisé selon vos besoins. Il s'agit de la bibliothèque PHP pour vous aider à générer la documentation Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Article de blog écrit par Daniel Schreiber sur la façon d'utiliser la spécification OpenAPI avec FlightPHP pour construire votre API en adoptant une approche API first. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI est un excellent outil pour vous aider à générer la documentation API pour vos projets Flight. Il est très facile à utiliser et peut être personnalisé selon vos besoins. C'est la bibliothèque PHP pour vous aider à générer la documentation Swagger. ## Surveillance des Performances des Applications (APM) La surveillance des performances des applications (APM) est cruciale pour toute application. Elle vous aide à comprendre comment votre application performe et où se trouvent les goulots d'étranglement. Il existe un certain nombre d'outils APM qui peuvent être utilisés avec Flight. - officiel [flightphp/apm](/awesome-plugins/apm) - Flight APM est une bibliothèque APM simple qui peut être utilisée pour surveiller vos applications Flight. Elle peut être utilisée pour surveiller les performances de votre application et vous aider à identifier les goulots d'étranglement. +## Asynchrone + +Flight est déjà un framework rapide, mais lui ajouter un turbo le rend encore plus amusant (et challenging) ! + +- [flightphp/async](/awesome-plugins/async) - Bibliothèque officielle Flight Async. Cette bibliothèque est une façon simple d'ajouter un traitement asynchrone à votre application. Elle utilise Swoole/Openswoole en arrière-plan pour fournir une façon simple et efficace d'exécuter des tâches de manière asynchrone. + ## Autorisation/Permissions -L'autorisation et les permissions sont cruciales pour toute application qui nécessite des contrôles en place pour déterminer qui peut accéder à quoi. +L'autorisation et les permissions sont cruciales pour toute application qui nécessite des contrôles sur qui peut accéder à quoi. - officiel [flightphp/permissions](/awesome-plugins/permissions) - Bibliothèque officielle Flight Permissions. Cette bibliothèque est une façon simple d'ajouter des permissions au niveau utilisateur et application à votre application. @@ -34,7 +40,7 @@ Les applications CLI sont une excellente façon d'interagir avec votre applicati ## Cookies -Les cookies sont une excellente façon de stocker de petites quantités de données côté client. Ils peuvent être utilisés pour stocker les préférences utilisateur, les paramètres de l'application, et plus encore. +Les cookies sont une excellente façon de stocker de petites quantités de données côté client. Ils peuvent être utilisés pour stocker les préférences utilisateur, les paramètres d'application, et plus encore. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie est une bibliothèque PHP qui fournit une façon simple et efficace de gérer les cookies. @@ -42,14 +48,14 @@ Les cookies sont une excellente façon de stocker de petites quantités de donn Le débogage est crucial lorsque vous développez dans votre environnement local. Il existe quelques plugins qui peuvent améliorer votre expérience de débogage. -- [tracy/tracy](/awesome-plugins/tracy) - Il s'agit d'un gestionnaire d'erreurs complet qui peut être utilisé avec Flight. Il dispose d'un certain nombre de panneaux qui peuvent vous aider à déboguer votre application. Il est également très facile à étendre et à ajouter vos propres panneaux. +- [tracy/tracy](/awesome-plugins/tracy) - C'est un gestionnaire d'erreurs complet qui peut être utilisé avec Flight. Il dispose d'un certain nombre de panneaux qui peuvent vous aider à déboguer votre application. Il est également très facile à étendre et à ajouter vos propres panneaux. - officiel [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Utilisé avec le gestionnaire d'erreurs [Tracy](/awesome-plugins/tracy), ce plugin ajoute quelques panneaux supplémentaires pour aider au débogage spécifiquement pour les projets Flight. ## Bases de Données Les bases de données sont au cœur de la plupart des applications. C'est ainsi que vous stockez et récupérez les données. Certaines bibliothèques de bases de données sont simplement des wrappers pour écrire des requêtes et d'autres sont des ORMs complets. -- officiel [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO officiel Flight qui fait partie du cœur. Il s'agit d'un wrapper simple pour aider à simplifier le processus d'écriture et d'exécution des requêtes. Ce n'est pas un ORM. +- officiel [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO officiel Flight qui fait partie du cœur. C'est un wrapper simple pour aider à simplifier le processus d'écriture et d'exécution des requêtes. Ce n'est pas un ORM. - officiel [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord officiel Flight. Excellente petite bibliothèque pour récupérer et stocker facilement des données dans votre base de données. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin pour suivre toutes les modifications de base de données pour votre projet. @@ -57,7 +63,7 @@ Les bases de données sont au cœur de la plupart des applications. C'est ainsi Le chiffrement est crucial pour toute application qui stocke des données sensibles. Chiffrer et déchiffrer les données n'est pas terriblement difficile, mais stocker correctement la clé de chiffrement [peut](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [être](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difficile](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). La chose la plus importante est de ne jamais stocker votre clé de chiffrement dans un répertoire public ou de l'engager dans votre dépôt de code. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Il s'agit d'une bibliothèque qui peut être utilisée pour chiffrer et déchiffrer des données. Se mettre en route est assez simple pour commencer à chiffrer et déchiffrer des données. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - C'est une bibliothèque qui peut être utilisée pour chiffrer et déchiffrer des données. Se mettre en route est assez simple pour commencer à chiffrer et déchiffrer des données. ## File d'Attente de Tâches @@ -67,24 +73,24 @@ Les files d'attente de tâches sont vraiment utiles pour traiter les tâches de ## Session -Les sessions ne sont pas vraiment utiles pour les API mais pour construire une application web, les sessions peuvent être cruciales pour maintenir l'état et les informations de connexion. +Les sessions ne sont pas vraiment utiles pour les API, mais pour construire une application web, les sessions peuvent être cruciales pour maintenir l'état et les informations de connexion. -- officiel [flightphp/session](/awesome-plugins/session) - Bibliothèque officielle Flight Session. Il s'agit d'une bibliothèque de session simple qui peut être utilisée pour stocker et récupérer les données de session. Elle utilise la gestion de session intégrée de PHP. +- officiel [flightphp/session](/awesome-plugins/session) - Bibliothèque officielle Flight Session. C'est une bibliothèque de session simple qui peut être utilisée pour stocker et récupérer les données de session. Elle utilise la gestion de session intégrée de PHP. - [Ghostff/Session](/awesome-plugins/ghost-session) - Gestionnaire de Session PHP (non-bloquant, flash, segment, chiffrement de session). Utilise PHP open_ssl pour le chiffrement/déchiffrement optionnel des données de session. ## Modélisation La modélisation est au cœur de toute application web avec une interface utilisateur. Il existe un certain nombre de moteurs de modélisation qui peuvent être utilisés avec Flight. -- déprécié [flightphp/core View](/learn#views) - Il s'agit d'un moteur de modélisation très basique qui fait partie du cœur. Il n'est pas recommandé de l'utiliser si vous avez plus de quelques pages dans votre projet. -- [latte/latte](/awesome-plugins/latte) - Latte est un moteur de modélisation complet qui est très facile à utiliser et se rapproche plus d'une syntaxe PHP que Twig ou Smarty. Il est également très facile à étendre et à ajouter vos propres filtres et fonctions. +- déprécié [flightphp/core View](/learn#views) - C'est un moteur de modélisation très basique qui fait partie du cœur. Il n'est pas recommandé de l'utiliser si vous avez plus de quelques pages dans votre projet. +- [latte/latte](/awesome-plugins/latte) - Latte est un moteur de modélisation complet qui est très facile à utiliser et se rapproche plus de la syntaxe PHP que Twig ou Smarty. Il est également très facile à étendre et à ajouter vos propres filtres et fonctions. ## Intégration WordPress Vous voulez utiliser Flight dans votre projet WordPress ? Il y a un plugin pratique pour cela ! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Ce plugin WordPress vous permet d'exécuter Flight directement aux côtés de WordPress. Il est parfait pour ajouter des API personnalisées, des microservices, ou même des applications complètes à votre site WordPress en utilisant le framework Flight. Super utile si vous voulez le meilleur des deux mondes ! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Ce plugin WordPress vous permet d'exécuter Flight directement aux côtés de WordPress. C'est parfait pour ajouter des API personnalisées, des microservices, ou même des applications complètes à votre site WordPress en utilisant le framework Flight. Super utile si vous voulez le meilleur des deux mondes ! ## Contribution -Vous avez un plugin que vous aimeriez partager ? Soumettez une demande de tirage pour l'ajouter à la liste ! \ No newline at end of file +Vous avez un plugin que vous aimeriez partager ? Soumettez une pull request pour l'ajouter à la liste ! \ No newline at end of file diff --git a/content/v3/fr/examples.md b/content/v3/fr/examples.md index bf40d6c7..f8de6a4c 100644 --- a/content/v3/fr/examples.md +++ b/content/v3/fr/examples.md @@ -1,11 +1,11 @@ # Besoin d'un démarrage rapide ? -Vous avez deux options pour commencer un nouveau projet Flight : +Vous avez deux options pour démarrer un nouveau projet Flight : -- [Boilerplate Complet](https://github.com/flightphp/skeleton) : Un exemple plus complet avec des contrôleurs et des vues. -- [Boilerplate à Fichier Unique](https://github.com/flightphp/skeleton-simple) : Un fichier unique qui comprend tout ce dont vous avez besoin pour exécuter votre application dans un seul fichier simple. +- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton) : Un exemple plus complet avec des contrôleurs et des vues. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple) : Un fichier unique qui inclut tout ce dont vous avez besoin pour exécuter votre application dans un seul fichier simple. -Exemples fournis par la communauté : +Exemples contributés par la communauté : - [flightravel](https://github.com/fadrian06-templates/flighravel) : FlightPHP avec des répertoires Laravel, avec des outils PHP + GH Actions - [fleact](https://github.com/flightphp/fleact) - Un kit de démarrage FlightPHP avec intégration ReactJS. @@ -14,23 +14,24 @@ Exemples fournis par la communauté : ## Besoin d'inspiration ? -Bien que ceux-ci ne soient pas officiellement sponsorisés par l'équipe Flight, ils pourraient vous donner des idées sur la façon de structurer vos propres projets construits avec Flight ! +Bien que ces exemples ne soient pas officiellement sponsorisés par l'équipe Flight, ils pourraient vous donner des idées sur la façon de structurer vos propres projets construits avec Flight ! +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental est une application web de location de voitures monopage, adaptée aux mobiles, construite avec PHP (FlightPHP), JavaScript et MySQL. Elle prend en charge l'inscription des utilisateurs, la navigation et la réservation de voitures, tandis que les administrateurs peuvent gérer les voitures, les utilisateurs et les réservations. L'application propose une API REST, une authentification JWT et un design responsive pour une expérience de location moderne. - [Decay](https://github.com/boxybird/decay) - Flight v3 avec HTMX et SleekDB, tout sur les zombies ! ([Démo](https://decay.andrewrhyand.com)) -- [Blog d'exemple Flight](https://github.com/n0nag0n/flightphp-blog) - Flight v3 avec Middleware, Contrôleurs, Active Record et Latte. -- [Flight CRUD API RESTful](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Projet API CRUD simple utilisant le framework Flight, qui fournit une structure de base pour que les nouveaux utilisateurs puissent rapidement configurer une application PHP avec des opérations CRUD et une connectivité à la base de données. Le projet démontre comment utiliser Flight pour le développement d'API RESTful, en faisant un outil d'apprentissage idéal pour les débutants et un kit de démarrage utile pour les développeurs plus expérimentés. -- [Système de Gestion d'École Flight](https://github.com/krmu/FlightPHP_School) - Flight v3 -- [Paste Bin avec Commentaires](https://github.com/n0nag0n/commie2) - Flight v3 -- [Application de Base Skeleton](https://github.com/markhughes/flight-skeleton) -- [Wiki d'Exemple](https://github.com/Skayo/FlightWiki) -- [L'Application du Framework PHP IT-Innovator](https://github.com/itinnovator/myphp-app) +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 avec Middleware, Controllers, Active Record et Latte. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Projet d'API CRUD simple utilisant le framework Flight, qui fournit une structure de base pour que les nouveaux utilisateurs configurent rapidement une application PHP avec des opérations CRUD et une connectivité à la base de données. Le projet démontre comment utiliser Flight pour le développement d'API RESTful, ce qui en fait un outil d'apprentissage idéal pour les débutants et un kit de démarrage utile pour les développeurs plus expérimentés. +- [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 +- [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 +- [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) +- [Example Wiki](https://github.com/Skayo/FlightWiki) +- [The IT-Innovator PHP Framework Application](https://github.com/itinnovator/myphp-app) - [LittleEducationalCMS (Espagnol)](https://github.com/casgin/LittleEducationalCMS) -- [API des Pages Jaunes Italiennes](https://github.com/chiccomagnus/PGAPI) -- [Système de Gestion de Contenu Générique (avec....très peu de documentation)](https://github.com/recepuncu/cms) -- [Un petit framework php basé sur Flight et medoo.](https://github.com/ycrao/tinyme) -- [Application MVC Exemple](https://github.com/paddypei/Flight-MVC) -- [Préparation de vol prête pour la production](https://github.com/madcoda9000/SecStore) - Framework d'authentification prêt pour la production qui vous fait gagner des semaines de développement. Sécurité de niveau entreprise : 2FA/TOTP, intégration LDAP, SSO Azure, limitation intelligente du débit, empreinte digitale de session, protection contre les attaques par force brute, tableau de bord d'analyse de sécurité, journalisation d'audit complète et contrôle d'accès précis basé sur les rôles. +- [Italian Yellow Pages API](https://github.com/chiccomagnus/PGAPI) +- [Generic Content Management System (avec....très peu de documentation)](https://github.com/recepuncu/cms) +- [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) +- [Example MVC Application](https://github.com/paddypei/Flight-MVC) +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework d'authentification prêt pour la production qui vous fait économiser des semaines de développement. Fonctionnalités de sécurité de niveau entreprise : 2FA/TOTP, intégration LDAP, SSO Azure, limitation de taux intelligente, empreinte de session, protection contre les attaques par force brute, tableau de bord d'analyse de sécurité, journalisation d'audit complète et contrôle d'accès basé sur les rôles granulaire. ## Voulez-vous partager votre propre exemple ? -Si vous avez un projet que vous souhaitez partager, veuillez soumettre une demande de tirage pour l'ajouter à cette liste ! \ No newline at end of file +Si vous avez un projet que vous souhaitez partager, veuillez soumettre une pull request pour l'ajouter à cette liste ! \ No newline at end of file diff --git a/content/v3/fr/learn/requests.md b/content/v3/fr/learn/requests.md index 4ca2e569..b8476f9a 100644 --- a/content/v3/fr/learn/requests.md +++ b/content/v3/fr/learn/requests.md @@ -11,19 +11,19 @@ $request = Flight::request(); ## Compréhension -Les requêtes HTTP sont l'un des aspects fondamentaux à comprendre concernant le cycle de vie HTTP. Un utilisateur effectue une action dans un navigateur web ou un client HTTP, et ils envoient une série d'en-têtes, un corps, une URL, etc. vers votre projet. Vous pouvez capturer ces en-têtes (la langue du navigateur, le type de compression qu'ils peuvent gérer, l'agent utilisateur, etc.) et capturer le corps et l'URL qui sont envoyés à votre application Flight. Ces requêtes sont essentielles pour que votre application comprenne quoi faire ensuite. +Les requêtes HTTP sont l'un des aspects fondamentaux à comprendre concernant le cycle de vie HTTP. Un utilisateur effectue une action dans un navigateur web ou un client HTTP, et ils envoient une série d'en-têtes, de corps, d'URL, etc. vers votre projet. Vous pouvez capturer ces en-têtes (le langage du navigateur, le type de compression qu'ils peuvent gérer, l'agent utilisateur, etc.) et capturer le corps et l'URL qui sont envoyés à votre application Flight. Ces requêtes sont essentielles pour que votre application comprenne quoi faire ensuite. ## Utilisation de base -PHP possède plusieurs super-globales incluant `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES`, et `$_COOKIE`. Flight abstrait ces éléments en [Collections](/learn/collections) pratiques. Vous pouvez accéder aux propriétés `query`, `data`, `cookies`, et `files` en tant que tableaux ou objets. +PHP possède plusieurs super globales incluant `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES`, et `$_COOKIE`. Flight abstrait ces éléments en [Collections](/learn/collections) pratiques. Vous pouvez accéder aux propriétés `query`, `data`, `cookies`, et `files` en tant qu'arrays ou objets. -> **Note :** Il est **TRÈS** déconseillé d'utiliser ces super-globales dans votre projet et elles doivent être référencées via l'objet `request()`. +> **Note :** Il est **FORTEMENT** déconseillé d'utiliser ces super globales dans votre projet et elles doivent être référencées via l'objet `request()`. > **Note :** Il n'y a pas d'abstraction disponible pour `$_ENV`. ### `$_GET` -Vous pouvez accéder au tableau `$_GET` via la propriété `query` : +Vous pouvez accéder à l'array `$_GET` via la propriété `query` : ```php // GET /search?keyword=something @@ -38,7 +38,7 @@ Flight::route('/search', function(){ ### `$_POST` -Vous pouvez accéder au tableau `$_POST` via la propriété `data` : +Vous pouvez accéder à l'array `$_POST` via la propriété `data` : ```php Flight::route('POST /submit', function(){ @@ -54,14 +54,14 @@ Flight::route('POST /submit', function(){ ### `$_COOKIE` -Vous pouvez accéder au tableau `$_COOKIE` via la propriété `cookies` : +Vous pouvez accéder à l'array `$_COOKIE` via la propriété `cookies` : ```php Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; // ou $savedLogin = Flight::request()->cookies->myLoginCookie; - // vérifier s'il est vraiment sauvegardé ou non et s'il l'est, les connecter automatiquement + // vérifier s'il est vraiment sauvegardé ou non et si oui, les connecter automatiquement if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -73,7 +73,7 @@ Pour de l'aide sur la définition de nouvelles valeurs de cookies, voir [overclo ### `$_SERVER` -Il existe un raccourci pour accéder au tableau `$_SERVER` via la méthode `getVar()` : +Il existe un raccourci disponible pour accéder à l'array `$_SERVER` via la méthode `getVar()` : ```php @@ -120,7 +120,7 @@ Flight::route('POST /upload', function(){ }); ``` -> **Note de sécurité :** Validez et nettoyez toujours les entrées utilisateur, surtout lors du traitement des téléchargements de fichiers. Validez toujours le type d'extensions que vous autorisez à être téléchargées, mais vous devriez également valider les "octets magiques" du fichier pour vous assurer qu'il s'agit réellement du type de fichier que l'utilisateur prétend qu'il est. Il existe des [articles](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [et](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [bibliothèques](https://github.com/RikudouSage/MimeTypeDetector) disponibles pour vous aider avec cela. +> **Note de sécurité :** Validez et nettoyez toujours les entrées utilisateur, surtout lors du traitement des téléchargements de fichiers. Validez toujours le type d'extensions que vous autorisez à être téléchargées, mais vous devriez également valider les "octets magiques" du fichier pour vous assurer qu'il s'agit réellement du type de fichier que l'utilisateur prétend. Il existe des [articles](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [et](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [bibliothèques](https://github.com/RikudouSage/MimeTypeDetector) disponibles pour vous aider avec cela. ### Corps de la requête @@ -137,19 +137,19 @@ Flight::route('POST /users/xml', function(){ ### Corps JSON Si vous recevez une requête avec le type de contenu `application/json` et les données d'exemple `{"id": 123}` -elles seront disponibles via la propriété `data` : +elle sera disponible via la propriété `data` : ```php $id = Flight::request()->data->id; ``` -### En-têtes de requête +### En-têtes de la requête -Vous pouvez accéder aux en-têtes de requête en utilisant la méthode `getHeader()` ou `getHeaders()` : +Vous pouvez accéder aux en-têtes de la requête en utilisant la méthode `getHeader()` ou `getHeaders()` : ```php -// Peut-être avez-vous besoin de l'en-tête Authorization +// Peut-être que vous avez besoin de l'en-tête Authorization $host = Flight::request()->getHeader('Authorization'); // ou $host = Flight::request()->header('Authorization'); @@ -160,16 +160,16 @@ $headers = Flight::request()->getHeaders(); $headers = Flight::request()->headers(); ``` -### Méthode de requête +### Méthode de la requête -Vous pouvez accéder à la méthode de requête en utilisant la propriété `method` ou la méthode `getMethod()` : +Vous pouvez accéder à la méthode de la requête en utilisant la propriété `method` ou la méthode `getMethod()` : ```php -$method = Flight::request()->method; // en fait peuplée par getMethod() +$method = Flight::request()->method; // en réalité peuplé par getMethod() $method = Flight::request()->getMethod(); ``` -**Note :** La méthode `getMethod()` récupère d'abord la méthode à partir de `$_SERVER['REQUEST_METHOD']`, puis elle peut être écrasée +**Note :** La méthode `getMethod()` récupère d'abord la méthode depuis `$_SERVER['REQUEST_METHOD']`, puis elle peut être écrasée par `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` si elle existe ou `$_REQUEST['_method']` si elle existe. ## Propriétés de l'objet requête @@ -179,27 +179,27 @@ L'objet requête fournit les propriétés suivantes : - **body** - Le corps brut de la requête HTTP - **url** - L'URL demandée - **base** - Le sous-répertoire parent de l'URL -- **method** - La méthode de requête (GET, POST, PUT, DELETE) +- **method** - La méthode de la requête (GET, POST, PUT, DELETE) - **referrer** - L'URL de référence -- **ip** - Adresse IP du client +- **ip** - L'adresse IP du client - **ajax** - Si la requête est une requête AJAX - **scheme** - Le protocole du serveur (http, https) -- **user_agent** - Informations du navigateur +- **user_agent** - Les informations du navigateur - **type** - Le type de contenu - **length** - La longueur du contenu -- **query** - Paramètres de la chaîne de requête -- **data** - Données de publication ou données JSON -- **cookies** - Données de cookies -- **files** - Fichiers téléchargés +- **query** - Les paramètres de la chaîne de requête +- **data** - Les données POST ou les données JSON +- **cookies** - Les données des cookies +- **files** - Les fichiers téléchargés - **secure** - Si la connexion est sécurisée -- **accept** - Paramètres d'acceptation HTTP -- **proxy_ip** - Adresse IP proxy du client. Parcourt le tableau `$_SERVER` pour `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` dans cet ordre. +- **accept** - Les paramètres HTTP accept +- **proxy_ip** - L'adresse IP proxy du client. Parcourt l'array `$_SERVER` pour `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` dans cet ordre. - **host** - Le nom d'hôte de la requête -- **servername** - Le SERVER_NAME à partir de `$_SERVER` +- **servername** - Le SERVER_NAME depuis `$_SERVER` ## Méthodes d'aide -Il existe quelques méthodes d'aide pour assembler des parties d'une URL ou gérer certains en-têtes. +Il existe quelques méthodes d'aide pour assembler des parties d'une URL, ou gérer certains en-têtes. ### URL complète @@ -222,14 +222,14 @@ $url = Flight::request()->getBaseUrl(); ## Analyse de requête -Vous pouvez passer une URL à la méthode `parseQuery()` pour analyser la chaîne de requête en un tableau associatif : +Vous pouvez passer une URL à la méthode `parseQuery()` pour analyser la chaîne de requête en un array associatif : ```php $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` -## Négociation des types d'acceptation de contenu +## Négociation des types de contenu acceptés _v3.17.2_ @@ -238,7 +238,7 @@ Vous pouvez utiliser la méthode `negotiateContentType()` pour déterminer le me ```php // Exemple d'en-tête Accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 -// Ci-dessous, définissez ce que vous supportez. +// Le code ci-dessous définit ce que vous supportez. $availableTypes = ['application/json', 'application/xml']; $typeToServe = Flight::request()->negotiateContentType($availableTypes); if ($typeToServe === 'application/json') { @@ -246,18 +246,18 @@ if ($typeToServe === 'application/json') { } elseif ($typeToServe === 'application/xml') { // Servir une réponse XML } else { - // Par défaut, utiliser autre chose ou lever une erreur + // Par défaut, utiliser quelque chose d'autre ou lever une erreur } ``` -> **Note :** Si aucun des types disponibles n'est trouvé dans l'en-tête `Accept`, la méthode retournera `null`. S'il n'y a pas d'en-tête `Accept` défini, la méthode retournera le premier type dans le tableau `$availableTypes`. +> **Note :** Si aucun des types disponibles n'est trouvé dans l'en-tête `Accept`, la méthode renverra `null`. Si aucun en-tête `Accept` n'est défini, la méthode renverra le premier type dans le array `$availableTypes`. ## Voir aussi -- [Routing](/learn/routing) - Voir comment mapper des routes vers des contrôleurs et rendre des vues. +- [Routing](/learn/routing) - Voir comment mapper les routes aux contrôleurs et rendre les vues. - [Responses](/learn/responses) - Comment personnaliser les réponses HTTP. - [Why a Framework?](/learn/why-frameworks) - Comment les requêtes s'intègrent dans le tableau global. - [Collections](/learn/collections) - Travailler avec des collections de données. -- [Uploaded File Handler](/learn/uploaded-file) - Gestion des téléchargements de fichiers. +- [Uploaded File Handler](/learn/uploaded-file) - Gérer les téléchargements de fichiers. ## Dépannage - `request()->ip` et `request()->proxy_ip` peuvent être différents si votre serveur web est derrière un proxy, un équilibreur de charge, etc. diff --git a/content/v3/fr/learn/routing.md b/content/v3/fr/learn/routing.md index fab39a6a..115dc787 100644 --- a/content/v3/fr/learn/routing.md +++ b/content/v3/fr/learn/routing.md @@ -1,17 +1,17 @@ # Routage ## Aperçu -Le routage dans Flight PHP mappe les motifs d'URL sur des fonctions de rappel ou des méthodes de classe, permettant une gestion rapide et simple des requêtes. Il est conçu pour un impact minimal, une utilisation conviviale pour les débutants, et une extensibilité sans dépendances externes. +Le routage dans Flight PHP mappe les motifs d'URL sur des fonctions de rappel ou des méthodes de classe, permettant une gestion rapide et simple des requêtes. Il est conçu pour un overhead minimal, une utilisation conviviale pour les débutants, et une extensibilité sans dépendances externes. ## Comprendre -Le routage est le mécanisme central qui connecte les requêtes HTTP à la logique de votre application dans Flight. En définissant des routes, vous spécifiez comment différentes URL déclenchent du code spécifique, que ce soit via des fonctions, des méthodes de classe, ou des actions de contrôleur. Le système de routage de Flight est flexible, supportant des motifs de base, des paramètres nommés, des expressions régulières, et des fonctionnalités avancées comme l'injection de dépendances et le routage de ressources. Cette approche garde votre code organisé et facile à maintenir, tout en restant rapide et simple pour les débutants et extensible pour les utilisateurs avancés. +Le routage est le mécanisme central qui connecte les requêtes HTTP à la logique de votre application dans Flight. En définissant des routes, vous spécifiez comment différentes URL déclenchent du code spécifique, que ce soit par des fonctions, des méthodes de classe ou des actions de contrôleur. Le système de routage de Flight est flexible, supportant des motifs basiques, des paramètres nommés, des expressions régulières, et des fonctionnalités avancées comme l'injection de dépendances et le routage de ressources. Cette approche garde votre code organisé et facile à maintenir, tout en restant rapide et simple pour les débutants et extensible pour les utilisateurs avancés. -> **Note :** Vous voulez en savoir plus sur le routage ? Consultez la page ["why a framework?](/learn/why-frameworks)" pour une explication plus détaillée. +> **Note :** Vous voulez en savoir plus sur le routage ? Consultez la page ["pourquoi un framework ?"]( /learn/why-frameworks) pour une explication plus approfondie. ## Utilisation de base ### Définir une route simple -Le routage de base dans Flight se fait en associant un motif d'URL à une fonction de rappel ou à un tableau contenant une classe et une méthode. +Le routage de base dans Flight se fait en associant un motif d'URL à une fonction de rappel ou à un tableau d'une classe et d'une méthode. ```php Flight::route('/', function(){ @@ -22,7 +22,7 @@ Flight::route('/', function(){ > Les routes sont associées dans l'ordre où elles sont définies. La première route qui correspond à une requête sera invoquée. ### Utiliser des fonctions comme rappels -Le rappel peut être n'importe quel objet invocable. Vous pouvez donc utiliser une fonction régulière : +Le rappel peut être n'importe quel objet qui est invocable. Vous pouvez donc utiliser une fonction régulière : ```php function hello() { @@ -77,11 +77,11 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **Note :** Par défaut, lorsque un contrôleur est appelé dans le framework, la classe `flight\Engine` est toujours injectée sauf si vous spécifiez autrement via un [conteneur d'injection de dépendances](/learn/dependency-injection-container) +> **Note :** Par défaut, lorsqu'un contrôleur est appelé dans le framework, la classe `flight\Engine` est toujours injectée sauf si vous spécifiez via un [conteneur d'injection de dépendances](/learn/dependency-injection-container) ### Routage spécifique à la méthode -Par défaut, les motifs de route correspondent à toutes les méthodes de requête. Vous pouvez répondre à des méthodes spécifiques en plaçant un identifiant avant l'URL. +Par défaut, les motifs de route sont associés à toutes les méthodes de requête. Vous pouvez répondre à des méthodes spécifiques en plaçant un identifiant avant l'URL. ```php Flight::route('GET /', function () { @@ -115,7 +115,7 @@ Flight fournit une gestion intégrée pour les requêtes HTTP `HEAD` et `OPTIONS #### Requêtes HEAD - Les **requêtes HEAD** sont traitées comme des requêtes `GET`, mais Flight supprime automatiquement le corps de la réponse avant de l'envoyer au client. -- Cela signifie que vous pouvez définir une route pour `GET`, et les requêtes HEAD vers la même URL ne renverront que les en-têtes (pas de contenu), comme attendu par les normes HTTP. +- Cela signifie que vous pouvez définir une route pour `GET`, et les requêtes HEAD vers la même URL ne renverront que les en-têtes (pas de contenu), comme attendu par les standards HTTP. ```php Flight::route('GET /info', function() { @@ -128,7 +128,7 @@ Flight::route('GET /info', function() { Les requêtes `OPTIONS` sont automatiquement gérées par Flight pour toute route définie. - Lorsqu'une requête OPTIONS est reçue, Flight répond avec un statut `204 No Content` et un en-tête `Allow` listant toutes les méthodes HTTP supportées pour cette route. -- Vous n'avez pas besoin de définir une route séparée pour OPTIONS sauf si vous voulez un comportement personnalisé ou modifier la réponse. +- Vous n'avez pas besoin de définir une route séparée pour OPTIONS. ```php // Pour une route définie comme : @@ -140,9 +140,9 @@ Flight::route('GET|POST /users', function() { /* ... */ }); // Allow: GET, POST, HEAD, OPTIONS ``` -### Utiliser l'objet Routeur +### Utiliser l'objet Router -De plus, vous pouvez récupérer l'objet Routeur qui dispose de méthodes d'assistance pour vous : +De plus, vous pouvez obtenir l'objet Router qui dispose de méthodes d'aide pour votre utilisation : ```php @@ -196,7 +196,7 @@ Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { #### Avertissement important -Bien que dans l'exemple ci-dessus, il semble que `@name` soit directement lié à la variable `$name`, ce n'est pas le cas. L'ordre des paramètres dans la fonction de rappel détermine ce qui lui est passé. Si vous inversiez l'ordre des paramètres dans la fonction de rappel, les variables seraient inversées également. Voici un exemple : +Bien que dans l'exemple ci-dessus, il semble que `@name` soit directement lié à la variable `$name`, ce n'est pas le cas. L'ordre des paramètres dans la fonction de rappel détermine ce qui lui est passé. Si vous inversiez l'ordre des paramètres dans la fonction de rappel, les variables seraient également inversées. Voici un exemple : ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -208,7 +208,7 @@ Et si vous alliez à l'URL suivante : `/bob/123`, la sortie serait `hello, 123 ( _Soyez prudent_ lorsque vous configurez vos routes et vos fonctions de rappel ! ### Paramètres optionnels -Vous pouvez spécifier des paramètres nommés qui sont optionnels pour la correspondance en enveloppant des segments entre parenthèses. +Vous pouvez spécifier des paramètres nommés qui sont optionnels pour la correspondance en enveloppant les segments entre parenthèses. ```php Flight::route( @@ -223,10 +223,10 @@ Flight::route( ); ``` -Tout paramètre optionnel qui n'est pas correspondant sera passé comme `NULL`. +Tout paramètre optionnel qui n'est pas associé sera passé en tant que `NULL`. ### Routage avec joker -La correspondance n'est faite que sur des segments d'URL individuels. Si vous voulez correspondre à plusieurs segments, vous pouvez utiliser le joker `*`. +La correspondance n'est faite que sur des segments d'URL individuels. Si vous voulez associer plusieurs segments, vous pouvez utiliser le joker `*`. ```php Flight::route('/blog/*', function () { @@ -245,7 +245,7 @@ Flight::route('*', function () { ### Gestionnaire 404 Non trouvé Par défaut, si une URL ne peut pas être trouvée, Flight enverra une réponse `HTTP 404 Not Found` qui est très simple et basique. -Si vous voulez une réponse 404 plus personnalisée, vous pouvez [mapper](/learn/extending) votre propre méthode `notFound` : +Si vous voulez avoir une réponse 404 plus personnalisée, vous pouvez [mapper](/learn/extending) votre propre méthode `notFound` : ```php Flight::map('notFound', function() { @@ -269,7 +269,7 @@ Flight::map('notFound', function() { Par défaut, si une URL est trouvée mais que la méthode n'est pas autorisée, Flight enverra une réponse `HTTP 405 Method Not Allowed` qui est très simple et basique (Ex : Method Not Allowed. Allowed Methods are: GET, POST). Elle inclura également un en-tête `Allow` avec les méthodes autorisées pour cette URL. -Si vous voulez une réponse 405 plus personnalisée, vous pouvez [mapper](/learn/extending) votre propre méthode `methodNotFound` : +Si vous voulez avoir une réponse 405 plus personnalisée, vous pouvez [mapper](/learn/extending) votre propre méthode `methodNotFound` : ```php use flight\net\Route; @@ -323,10 +323,10 @@ class Greeting // index.php // Configurez le conteneur avec les paramètres dont vous avez besoin -// Consultez la page Injection de dépendances pour plus d'informations sur PSR-11 +// Voir la page Injection de dépendances pour plus d'informations sur PSR-11 $dice = new \Dice\Dice(); -// N'oubliez pas de réassigner la variable avec '$dice = '!!!!! +// N'oubliez pas de réassigner la variable avec '$dice = '!!!!! $dice = $dice->addRule('flight\database\PdoWrapper', [ 'shared' => true, 'constructParams' => [ @@ -359,13 +359,13 @@ Vous pouvez passer l'exécution à la route correspondante suivante en retournan Flight::route('/user/@name', function (string $name) { // Vérifiez une condition if ($name !== "Bob") { - // Continuez à la route suivante + // Continuez vers la route suivante return true; } }); Flight::route('/user/*', function () { - // Ceci sera appelé + // Cela sera appelé }); ``` @@ -393,10 +393,10 @@ class UserController { ``` -Ceci est particulièrement utile si votre URL change. Dans l'exemple ci-dessus, supposons que les utilisateurs ont été déplacés vers `/admin/users/@id` au lieu de cela. +Ceci est particulièrement utile si votre URL change. Dans l'exemple ci-dessus, supposons que users ait été déplacé vers `/admin/users/@id` à la place. Avec l'aliasing en place pour la route, vous n'avez plus besoin de trouver toutes les anciennes URL dans votre code et de les changer car l'alias renverra maintenant `/admin/users/5` comme dans l'exemple ci-dessus. -L'aliasing de route fonctionne encore dans les groupes également : +L'aliasing de route fonctionne encore dans les groupes : ```php Flight::group('/users', function() { @@ -407,7 +407,7 @@ Flight::group('/users', function() { ``` ### Inspection des informations de route -Si vous voulez inspecter les informations de la route correspondante, il y a 2 façons de faire cela : +Si vous voulez inspecter les informations de la route correspondante, il y a 2 façons de faire ceci : 1. Vous pouvez utiliser une propriété `executedRoute` sur l'objet `Flight::router()`. 2. Vous pouvez demander que l'objet route soit passé à votre rappel en passant `true` comme troisième paramètre dans la méthode route. L'objet route sera toujours le dernier paramètre passé à votre fonction de rappel. @@ -417,7 +417,7 @@ Si vous voulez inspecter les informations de la route correspondante, il y a 2 f Flight::route('/', function() { $route = Flight::router()->executedRoute; // Faites quelque chose avec $route - // Tableau des méthodes HTTP correspondantes + // Tableau des méthodes HTTP associées $route->methods; // Tableau des paramètres nommés @@ -440,12 +440,12 @@ Flight::route('/', function() { }); ``` -> **Note :** La propriété `executedRoute` ne sera définie qu'après qu'une route ait été exécutée. Si vous essayez d'y accéder avant qu'une route ait été exécutée, elle sera `NULL`. Vous pouvez également utiliser executedRoute dans [middleware](/learn/middleware) ! +> **Note :** La propriété `executedRoute` ne sera définie qu'après qu'une route ait été exécutée. Si vous essayez d'y accéder avant qu'une route ait été exécutée, elle sera `NULL`. Vous pouvez aussi utiliser executedRoute dans [middleware](/learn/middleware) ! #### Passer `true` à la définition de route ```php Flight::route('/', function(\flight\net\Route $route) { - // Tableau des méthodes HTTP correspondantes + // Tableau des méthodes HTTP associées $route->methods; // Tableau des paramètres nommés @@ -465,7 +465,7 @@ Flight::route('/', function(\flight\net\Route $route) { // Montre l'alias assigné à cette route $route->alias; -}, true);// <-- Ce paramètre true est ce qui fait que cela arrive +}, true);// <-- Ce paramètre true est ce qui rend cela possible ``` ### Groupement de routes et Middleware @@ -489,7 +489,7 @@ Vous pouvez même imbriquer des groupes de groupes : ```php Flight::group('/api', function () { Flight::group('/v1', function () { - // Flight::get() obtient des variables, cela ne définit pas une route ! Voir le contexte d'objet ci-dessous + // Flight::get() obtient des variables, cela ne définit pas une route ! Voir le contexte objet ci-dessous Flight::route('GET /users', function () { // Correspond à GET /api/v1/users }); @@ -504,7 +504,7 @@ Flight::group('/api', function () { }); Flight::group('/v2', function () { - // Flight::get() obtient des variables, cela ne définit pas une route ! Voir le contexte d'objet ci-dessous + // Flight::get() obtient des variables, cela ne définit pas une route ! Voir le contexte objet ci-dessous Flight::route('GET /users', function () { // Correspond à GET /api/v2/users }); @@ -512,7 +512,7 @@ Flight::group('/api', function () { }); ``` -#### Groupement avec contexte d'objet +#### Groupement avec contexte objet Vous pouvez toujours utiliser le groupement de routes avec l'objet `Engine` de la manière suivante : @@ -546,7 +546,7 @@ Flight::group('/api/v1', function () { }, [ MyAuthMiddleware::class ]); // ou [ new MyAuthMiddleware() ] si vous voulez utiliser une instance ``` -Voir plus de détails sur la page [middleware de groupe](/learn/middleware#grouping-middleware). +Voir plus de détails sur la page [group middleware](/learn/middleware#grouping-middleware). ### Routage de ressources Vous pouvez créer un ensemble de routes pour une ressource en utilisant la méthode `resource`. Cela créera un ensemble de routes pour une ressource qui suit les conventions RESTful. @@ -606,16 +606,16 @@ class UsersController } ``` -> **Note** : Vous pouvez voir les routes nouvellement ajoutées avec `runway` en exécutant `php runway routes`. +> **Note** : Vous pouvez visualiser les routes nouvellement ajoutées avec `runway` en exécutant `php runway routes`. #### Personnalisation des routes de ressources Il y a quelques options pour configurer les routes de ressources. -##### Base d'alias +##### Alias de base -Vous pouvez configurer la `aliasBase`. Par défaut, l'alias est la dernière partie de l'URL spécifiée. -Par exemple, `/users/` résulterait en une `aliasBase` de `users`. Lorsque ces routes sont créées, les alias sont `users.index`, `users.create`, etc. Si vous voulez changer l'alias, définissez la `aliasBase` à la valeur que vous voulez. +Vous pouvez configurer l'`aliasBase`. Par défaut, l'alias est la dernière partie de l'URL spécifiée. +Par exemple, `/users/` résulterait en un `aliasBase` de `users`. Lorsque ces routes sont créées, les alias sont `users.index`, `users.create`, etc. Si vous voulez changer l'alias, définissez l'`aliasBase` à la valeur que vous voulez. ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); @@ -648,10 +648,10 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid ### Réponses en streaming Vous pouvez maintenant diffuser des réponses au client en utilisant `stream()` ou `streamWithHeaders()`. -Ceci est utile pour envoyer de gros fichiers, des processus à longue durée, ou générer de grandes réponses. -Le streaming d'une route est géré un peu différemment d'une route régulière. +Ceci est utile pour envoyer de grands fichiers, des processus à longue durée, ou générer de grandes réponses. +Le streaming d'une route est géré un peu différemment qu'une route régulière. -> **Note :** Les réponses en streaming ne sont disponibles que si vous avez [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) défini sur `false`. +> **Note :** Les réponses en streaming ne sont disponibles que si vous avez [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) défini à `false`. #### Stream avec en-têtes manuels @@ -686,7 +686,7 @@ Flight::route('/@filename', function($filename) { // ou $response->setRealHeader('Content-Length: '.filesize($filePath)); - // Diffusez le fichier au client pendant qu'il est lu + // Diffusez le fichier au client au fur et à mesure qu'il est lu readfile($filePath); // C'est la ligne magique ici @@ -719,7 +719,7 @@ Flight::route('/stream-users', function() { } echo '}'; -// C'est comme ça que vous définirez les en-têtes avant de commencer le streaming. +// C'est ainsi que vous définirez les en-têtes avant de commencer le streaming. })->streamWithHeaders([ 'Content-Type' => 'application/json', 'Content-Disposition' => 'attachment; filename="users.json"', @@ -736,15 +736,15 @@ Flight::route('/stream-users', function() { - [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - Fonction PHP pour la correspondance d'expressions régulières. ## Dépannage -- Les paramètres de route sont correspondus par ordre, pas par nom. Assurez-vous que l'ordre des paramètres du rappel correspond à la définition de la route. -- Utiliser `Flight::get()` ne définit pas une route ; utilisez `Flight::route('GET /...')` pour le routage ou le contexte d'objet Routeur dans les groupes (ex. `$router->get(...)`). +- Les paramètres de route sont associés par ordre, pas par nom. Assurez-vous que l'ordre des paramètres du rappel correspond à la définition de la route. +- Utiliser `Flight::get()` ne définit pas une route ; utilisez `Flight::route('GET /...')` pour le routage ou le contexte objet Router dans les groupes (ex. `$router->get(...)`). - La propriété executedRoute n'est définie qu'après l'exécution d'une route ; elle est NULL avant l'exécution. -- Le streaming nécessite que la fonctionnalité de mise en tampon de sortie legacy de Flight soit désactivée (`flight.v2.output_buffering = false`). +- Le streaming nécessite que la fonctionnalité de tampon de sortie legacy de Flight soit désactivée (`flight.v2.output_buffering = false`). - Pour l'injection de dépendances, seules certaines définitions de routes supportent l'instanciation basée sur conteneur. ### 404 Non trouvé ou comportement de route inattendu -Si vous voyez une erreur 404 Non trouvé (mais vous jurez sur votre vie que c'est vraiment là et que ce n'est pas une faute de frappe), cela pourrait en fait être un problème avec le fait que vous retournez une valeur dans votre point de terminaison de route au lieu de juste l'échoer. La raison de cela est intentionnelle mais pourrait surprendre certains développeurs. +Si vous voyez une erreur 404 Non trouvé (mais vous jurez sur votre vie que c'est vraiment là et que ce n'est pas une faute de frappe), cela pourrait en fait être un problème avec le fait que vous retournez une valeur dans votre point de terminaison de route au lieu de simplement l'échoer. La raison de cela est intentionnelle mais pourrait surprendre certains développeurs. ```php Flight::route('/hello', function(){ @@ -758,9 +758,9 @@ Flight::route('/hello', function(){ }); ``` -La raison de cela est due à un mécanisme spécial intégré au routeur qui gère la sortie de retour comme un signal pour "aller à la route suivante". +La raison de cela est en raison d'un mécanisme spécial intégré au routeur qui gère la sortie de retour comme un signal pour "aller à la route suivante". Vous pouvez voir le comportement documenté dans la section [Routage](/learn/routing#passing). -## Journal des changements -- v3 : Ajout du routage de ressources, de l'aliasing de route, et du support de streaming, des groupes de routes, et du support de middleware. +## Journal des modifications +- v3 : Ajout du routage de ressources, de l'aliasing de route, et du support de streaming, groupes de routes, et support de middleware. - v1 : La grande majorité des fonctionnalités de base disponibles. \ No newline at end of file diff --git a/content/v3/id/awesome-plugins/async.md b/content/v3/id/awesome-plugins/async.md new file mode 100644 index 00000000..9e11cf96 --- /dev/null +++ b/content/v3/id/awesome-plugins/async.md @@ -0,0 +1,212 @@ +# Async + +Async adalah paket kecil untuk framework Flight yang memungkinkan Anda menjalankan aplikasi Flight di dalam server dan runtime asinkron seperti Swoole, AdapterMan, ReactPHP, Amp, RoadRunner, Workerman, dll. Secara default, ia menyertakan adapter untuk Swoole dan AdapterMan. + +Tujuan: mengembangkan dan mendebug dengan PHP-FPM (atau server bawaan) dan beralih ke Swoole (atau driver asinkron lainnya) untuk produksi dengan perubahan minimal. + +## Persyaratan + +- PHP 7.4 atau lebih tinggi +- Framework Flight 3.16.1 atau lebih tinggi +- [Ekstensi Swoole](https://www.openswoole.com) + +## Instalasi + +Instal melalui composer: + +```bash +composer require flightphp/async +``` + +Jika Anda berencana menjalankan dengan Swoole, instal ekstensi tersebut: + +```bash +# menggunakan pecl +pecl install swoole +# atau openswoole +pecl install openswoole + +# atau dengan pengelola paket (contoh Debian/Ubuntu) +sudo apt-get install php-swoole +``` + +## Contoh Cepat Swoole + +Berikut adalah pengaturan minimal yang menunjukkan cara mendukung baik PHP-FPM (atau server bawaan) maupun Swoole menggunakan kode dasar yang sama. + +File yang Anda butuhkan dalam proyek Anda: + +- index.php +- swoole_server.php +- SwooleServerDriver.php + +### index.php + +File ini adalah saklar sederhana yang memaksa aplikasi berjalan dalam mode PHP untuk pengembangan. + +```php +// index.php +route('/', function() use ($app) { + $app->json(['hello' => 'world']); +}); + +if (!defined('NOT_SWOOLE')) { + // Require kelas SwooleServerDriver ketika berjalan dalam mode Swoole. + require_once __DIR__ . '/SwooleServerDriver.php'; + + Swoole\Runtime::enableCoroutine(); + $Swoole_Server = new SwooleServerDriver('127.0.0.1', 9501, $app); + $Swoole_Server->start(); +} else { + $app->start(); +} +``` + +### SwooleServerDriver.php + +Driver ringkas yang menunjukkan cara menjembatani permintaan Swoole ke Flight menggunakan AsyncBridge dan adapter Swoole. + +```php +// SwooleServerDriver.php +Swoole = new SwooleServer($host, $port); + $this->app = $app; + + $this->setDefault(); + $this->bindWorkerEvents(); + $this->bindHttpEvent(); + } + + protected function setDefault() { + $this->Swoole->set([ + 'daemonize' => false, + 'dispatch_mode' => 1, + 'max_request' => 8000, + 'open_tcp_nodelay' => true, + 'reload_async' => true, + 'max_wait_time' => 60, + 'enable_reuse_port' => true, + 'enable_coroutine' => true, + 'http_compression' => false, + 'enable_static_handler' => true, + 'document_root' => __DIR__, + 'static_handler_locations' => ['/css', '/js', '/images', '/.well-known'], + 'buffer_output_size' => 4 * 1024 * 1024, + 'worker_num' => 4, + ]); + + $app = $this->app; + $app->map('stop', function (?int $code = null) use ($app) { + if ($code !== null) { + $app->response()->status($code); + } + }); + } + + protected function bindHttpEvent() { + $app = $this->app; + $AsyncBridge = new AsyncBridge($app); + + $this->Swoole->on('Start', function(SwooleServer $server) { + echo "Swoole http server is started at http://127.0.0.1:9501\n"; + }); + + $this->Swoole->on('Request', function (SwooleRequest $request, SwooleResponse $response) use ($AsyncBridge) { + $SwooleAsyncRequest = new SwooleAsyncRequest($request); + $SwooleAsyncResponse = new SwooleAsyncResponse($response); + + $AsyncBridge->processRequest($SwooleAsyncRequest, $SwooleAsyncResponse); + + $response->end(); + gc_collect_cycles(); + }); + } + + protected function bindWorkerEvents() { + $createPools = function() { + // create worker-specific connection pools here + }; + $closePools = function() { + // close pools / cleanup here + }; + $this->Swoole->on('WorkerStart', $createPools); + $this->Swoole->on('WorkerStop', $closePools); + $this->Swoole->on('WorkerError', $closePools); + } + + public function start() { + $this->Swoole->start(); + } +} +``` + +## Menjalankan Server + +- Pengembangan (server bawaan PHP / PHP-FPM): + - php -S localhost:8000 (atau tambahkan -t public/ jika index Anda berada di public/) +- Produksi (Swoole): + - php swoole_server.php + +Tips: Untuk penggunaan produksi, gunakan proxy terbalik (Nginx) di depan Swoole untuk menangani TLS, file statis, dan penyeimbangan beban. + +## Catatan Konfigurasi + +Driver Swoole mengekspos beberapa opsi konfigurasi: +- worker_num: jumlah proses pekerja +- max_request: permintaan per pekerja sebelum restart +- enable_coroutine: gunakan coroutine untuk konkurensi +- buffer_output_size: ukuran buffer output + +Sesuaikan ini dengan sumber daya host dan pola lalu lintas Anda. + +## Penanganan Kesalahan + +AsyncBridge menerjemahkan kesalahan Flight menjadi respons HTTP yang tepat. Anda juga dapat menambahkan penanganan kesalahan pada tingkat rute: + +```php +$app->route('/*', function() use ($app) { + try { + // logika rute + } catch (Exception $e) { + $app->response()->status(500); + $app->json(['error' => $e->getMessage()]); + } +}); +``` + +## AdapterMan dan Runtime Lainnya + +[AdapterMan](https://github.com/joanhey/adapterman) didukung sebagai adapter runtime alternatif. Paket ini dirancang untuk dapat diadaptasi — menambahkan atau menggunakan adapter lain umumnya mengikuti pola yang sama: mengonversi permintaan/respons server menjadi permintaan/respons Flight melalui AsyncBridge dan adapter khusus runtime. \ No newline at end of file diff --git a/content/v3/id/awesome-plugins/awesome_plugins.md b/content/v3/id/awesome-plugins/awesome_plugins.md index 4728e5f6..bcd880f4 100644 --- a/content/v3/id/awesome-plugins/awesome_plugins.md +++ b/content/v3/id/awesome-plugins/awesome_plugins.md @@ -1,6 +1,6 @@ # Plugin Hebat -Flight sangat dapat diperluas. Ada sejumlah plugin yang dapat digunakan untuk menambahkan fungsionalitas ke aplikasi Flight Anda. Beberapa didukung secara resmi oleh Tim Flight dan yang lain adalah pustaka mikro/lite untuk membantu Anda memulai. +Flight sangat dapat diperluas. Ada sejumlah plugin yang dapat digunakan untuk menambahkan fungsionalitas ke aplikasi Flight Anda. Beberapa didukung secara resmi oleh Tim Flight dan yang lainnya adalah pustaka mikro/lite untuk membantu Anda memulai. ## Dokumentasi API @@ -11,20 +11,26 @@ Dokumentasi API sangat penting untuk API apa pun. Ini membantu pengembang memaha ## Pemantauan Kinerja Aplikasi (APM) -Pemantauan Kinerja Aplikasi (APM) sangat penting untuk aplikasi apa pun. Ini membantu Anda memahami bagaimana aplikasi Anda berkinerja dan di mana titik kesempatan terletak. Ada sejumlah alat APM yang dapat digunakan dengan Flight. -- resmi [flightphp/apm](/awesome-plugins/apm) - Flight APM adalah pustaka APM sederhana yang dapat digunakan untuk memantau aplikasi Flight Anda. Ini dapat digunakan untuk memantau kinerja aplikasi Anda dan membantu Anda mengidentifikasi titik kesempatan. +Pemantauan Kinerja Aplikasi (APM) sangat penting untuk aplikasi apa pun. Ini membantu Anda memahami bagaimana aplikasi Anda berkinerja dan di mana titik penyumbatannya. Ada sejumlah alat APM yang dapat digunakan dengan Flight. +- resmi [flightphp/apm](/awesome-plugins/apm) - Flight APM adalah pustaka APM sederhana yang dapat digunakan untuk memantau aplikasi Flight Anda. Ini dapat digunakan untuk memantau kinerja aplikasi Anda dan membantu Anda mengidentifikasi titik penyumbatan. + +## Async + +Flight sudah merupakan framework yang cepat, tetapi menambahkan mesin turbo padanya membuat semuanya lebih menyenangkan (dan menantang)! + +- [flightphp/async](/awesome-plugins/async) - Pustaka Async Flight resmi. Pustaka ini adalah cara sederhana untuk menambahkan pemrosesan asinkron ke aplikasi Anda. Ini menggunakan Swoole/Openswoole di balik layar untuk menyediakan cara sederhana dan efektif untuk menjalankan tugas secara asinkron. ## Otorisasi/Izin -Otorisasi dan Izin sangat penting untuk aplikasi apa pun yang memerlukan kontrol untuk menentukan siapa yang dapat mengakses apa. +Otorisasi dan Izin sangat penting untuk aplikasi apa pun yang memerlukan kontrol untuk siapa yang dapat mengakses apa. -- resmi [flightphp/permissions](/awesome-plugins/permissions) - Pustaka Izin Flight Resmi. Pustaka ini adalah cara sederhana untuk menambahkan izin tingkat pengguna dan aplikasi ke aplikasi Anda. +- resmi [flightphp/permissions](/awesome-plugins/permissions) - Pustaka Permissions Flight resmi. Pustaka ini adalah cara sederhana untuk menambahkan izin tingkat pengguna dan aplikasi ke aplikasi Anda. -## Penyimpanan Sementara +## Penyimpanan Cache -Penyimpanan sementara adalah cara hebat untuk mempercepat aplikasi Anda. Ada sejumlah pustaka penyimpanan sementara yang dapat digunakan dengan Flight. +Penyimpanan cache adalah cara hebat untuk mempercepat aplikasi Anda. Ada sejumlah pustaka caching yang dapat digunakan dengan Flight. -- resmi [flightphp/cache](/awesome-plugins/php-file-cache) - Kelas penyimpanan sementara dalam file PHP yang ringan, sederhana, dan mandiri +- resmi [flightphp/cache](/awesome-plugins/php-file-cache) - Kelas caching in-file PHP yang ringan, sederhana, dan standalone ## CLI @@ -32,36 +38,36 @@ Aplikasi CLI adalah cara hebat untuk berinteraksi dengan aplikasi Anda. Anda dap - resmi [flightphp/runway](/awesome-plugins/runway) - Runway adalah aplikasi CLI yang membantu Anda mengelola aplikasi Flight Anda. -## Cookie +## Cookies -Cookie adalah cara hebat untuk menyimpan bit data kecil di sisi klien. Mereka dapat digunakan untuk menyimpan preferensi pengguna, pengaturan aplikasi, dan banyak lagi. +Cookies adalah cara hebat untuk menyimpan bit data kecil di sisi klien. Mereka dapat digunakan untuk menyimpan preferensi pengguna, pengaturan aplikasi, dan banyak lagi. -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie adalah pustaka PHP yang menyediakan cara sederhana dan efektif untuk mengelola cookie. +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie adalah pustaka PHP yang menyediakan cara sederhana dan efektif untuk mengelola cookies. ## Debugging -Debugging sangat penting saat Anda mengembangkan di lingkungan lokal Anda. Ada beberapa plugin yang dapat meningkatkan pengalaman debugging Anda. +Debugging sangat penting ketika Anda mengembangkan di lingkungan lokal Anda. Ada beberapa plugin yang dapat meningkatkan pengalaman debugging Anda. -- [tracy/tracy](/awesome-plugins/tracy) - Ini adalah penanganan kesalahan lengkap yang dapat digunakan dengan Flight. Ini memiliki sejumlah panel yang dapat membantu Anda debugging aplikasi Anda. Ini juga sangat mudah diperluas dan menambahkan panel Anda sendiri. -- resmi [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Digunakan dengan penanganan kesalahan [Tracy](/awesome-plugins/tracy), plugin ini menambahkan beberapa panel tambahan untuk membantu debugging khusus untuk proyek Flight. +- [tracy/tracy](/awesome-plugins/tracy) - Ini adalah penanganan kesalahan lengkap yang dapat digunakan dengan Flight. Ini memiliki sejumlah panel yang dapat membantu Anda mendebug aplikasi Anda. Ini juga sangat mudah untuk diperluas dan menambahkan panel Anda sendiri. +- resmi [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Digunakan dengan penanganan kesalahan [Tracy](/awesome-plugins/tracy), plugin ini menambahkan beberapa panel ekstra untuk membantu debugging khusus untuk proyek Flight. -## Basis Data +## Database -Basis data adalah inti dari sebagian besar aplikasi. Inilah cara Anda menyimpan dan mengambil data. Beberapa pustaka basis data hanyalah pembungkus untuk menulis kueri dan beberapa adalah ORM lengkap. +Database adalah inti dari sebagian besar aplikasi. Ini adalah cara Anda menyimpan dan mengambil data. Beberapa pustaka database hanyalah wrapper untuk menulis query dan beberapa adalah ORM lengkap. -- resmi [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Pembungkus PDO Flight Resmi yang merupakan bagian dari inti. Ini adalah pembungkus sederhana untuk membantu menyederhanakan proses penulisan kueri dan mengeksekusinya. Ini bukan ORM. -- resmi [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord Flight Resmi. Pustaka kecil yang hebat untuk dengan mudah mengambil dan menyimpan data di basis data Anda. -- [byjg/php-migration](/awesome-plugins/migrations) - Plugin untuk melacak semua perubahan basis data untuk proyek Anda. +- resmi [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO Flight resmi yang merupakan bagian dari inti. Ini adalah wrapper sederhana untuk membantu menyederhanakan proses penulisan query dan mengeksekusinya. Ini bukan ORM. +- resmi [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord Flight resmi. Pustaka kecil yang hebat untuk dengan mudah mengambil dan menyimpan data di database Anda. +- [byjg/php-migration](/awesome-plugins/migrations) - Plugin untuk melacak semua perubahan database untuk proyek Anda. ## Enkripsi -Enkripsi sangat penting untuk aplikasi apa pun yang menyimpan data sensitif. Mengenkripsi dan mendekripsi data tidak terlalu sulit, tetapi menyimpan kunci enkripsi dengan benar [bisa](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [menjadi](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [sulit](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Hal terpenting adalah jangan pernah menyimpan kunci enkripsi Anda di direktori publik atau mengommitnya ke repositori kode Anda. +Enkripsi sangat penting untuk aplikasi apa pun yang menyimpan data sensitif. Mengenkripsi dan mendekripsi data tidak terlalu sulit, tetapi menyimpan kunci enkripsi dengan benar [bisa](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [menjadi](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [sulit](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Hal yang paling penting adalah jangan pernah menyimpan kunci enkripsi Anda di direktori publik atau mengommitnya ke repositori kode Anda. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Ini adalah pustaka yang dapat digunakan untuk mengenkripsi dan mendekripsi data. Memulai dan menjalankannya cukup sederhana untuk mulai mengenkripsi dan mendekripsi data. ## Antrian Pekerjaan -Antrian pekerjaan sangat membantu untuk memproses tugas secara asinkron. Ini bisa berupa mengirim email, memproses gambar, atau apa pun yang tidak perlu dilakukan secara real-time. +Antrian pekerjaan sangat membantu untuk memproses tugas secara asinkron. Ini bisa mengirim email, memproses gambar, atau apa pun yang tidak perlu dilakukan secara real-time. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue adalah pustaka yang dapat digunakan untuk memproses pekerjaan secara asinkron. Ini dapat digunakan dengan beanstalkd, MySQL/MariaDB, SQLite, dan PostgreSQL. @@ -69,15 +75,15 @@ Antrian pekerjaan sangat membantu untuk memproses tugas secara asinkron. Ini bis Sesi tidak terlalu berguna untuk API tetapi untuk membangun aplikasi web, sesi bisa sangat penting untuk mempertahankan status dan informasi login. -- resmi [flightphp/session](/awesome-plugins/session) - Pustaka Sesi Flight Resmi. Ini adalah pustaka sesi sederhana yang dapat digunakan untuk menyimpan dan mengambil data sesi. Ini menggunakan penanganan sesi bawaan PHP. +- resmi [flightphp/session](/awesome-plugins/session) - Pustaka Sesi Flight resmi. Ini adalah pustaka sesi sederhana yang dapat digunakan untuk menyimpan dan mengambil data sesi. Ini menggunakan penanganan sesi bawaan PHP. - [Ghostff/Session](/awesome-plugins/ghost-session) - Manajer Sesi PHP (non-blocking, flash, segment, enkripsi sesi). Menggunakan PHP open_ssl untuk enkripsi/dekripsi data sesi opsional. ## Templating Templating adalah inti dari aplikasi web apa pun dengan UI. Ada sejumlah mesin templating yang dapat digunakan dengan Flight. -- deprecated [flightphp/core View](/learn#views) - Ini adalah mesin templating dasar yang merupakan bagian dari inti. Tidak disarankan digunakan jika Anda memiliki lebih dari beberapa halaman di proyek Anda. -- [latte/latte](/awesome-plugins/latte) - Latte adalah mesin templating lengkap yang sangat mudah digunakan dan terasa lebih dekat dengan sintaks PHP daripada Twig atau Smarty. Ini juga sangat mudah diperluas dan menambahkan filter dan fungsi Anda sendiri. +- deprecated [flightphp/core View](/learn#views) - Ini adalah mesin templating dasar yang merupakan bagian dari inti. Tidak disarankan untuk digunakan jika Anda memiliki lebih dari beberapa halaman di proyek Anda. +- [latte/latte](/awesome-plugins/latte) - Latte adalah mesin templating lengkap yang sangat mudah digunakan dan terasa lebih dekat dengan sintaks PHP daripada Twig atau Smarty. Ini juga sangat mudah untuk diperluas dan menambahkan filter dan fungsi Anda sendiri. ## Integrasi WordPress @@ -85,6 +91,6 @@ Ingin menggunakan Flight di proyek WordPress Anda? Ada plugin yang berguna untuk - [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Plugin WordPress ini memungkinkan Anda menjalankan Flight tepat di samping WordPress. Ini sempurna untuk menambahkan API khusus, microservices, atau bahkan aplikasi lengkap ke situs WordPress Anda menggunakan framework Flight. Sangat berguna jika Anda ingin yang terbaik dari kedua dunia! -## Berkontribusi +## Kontribusi -Punya plugin yang ingin Anda bagikan? Ajukan permintaan tarik untuk menambahkannya ke daftar! \ No newline at end of file +Punya plugin yang ingin Anda bagikan? Kirimkan pull request untuk menambahkannya ke daftar! \ No newline at end of file diff --git a/content/v3/id/examples.md b/content/v3/id/examples.md index 42ee7d65..f5ccc3e4 100644 --- a/content/v3/id/examples.md +++ b/content/v3/id/examples.md @@ -1,36 +1,37 @@ -# Butuh permulaan yang cepat? +# Butuh mulai cepat? Anda memiliki dua opsi untuk memulai proyek Flight baru: -- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Contoh yang lebih lengkap dengan pengontrol dan tampilan. -- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Satu file yang mencakup semua yang Anda butuhkan untuk menjalankan aplikasi Anda dalam satu file sederhana. +- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Contoh yang lebih lengkap dengan controller dan view. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Satu file tunggal yang mencakup semua yang Anda butuhkan untuk menjalankan aplikasi Anda dalam satu file sederhana. Contoh yang disumbangkan oleh komunitas: - [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP dengan direktori Laravel, dengan alat PHP + GH Actions -- [fleact](https://github.com/flightphp/fleact) - Kit pemula FlightPHP dengan integrasi ReactJS. -- [flastro](https://github.com/flightphp/flastro) - Kit pemula FlightPHP dengan integrasi Astro. -- [velt](https://github.com/flightphp/velt) - Velt adalah templat pemula Svelte yang cepat dan mudah dengan backend FlightPHP. +- [fleact](https://github.com/flightphp/fleact) - Kit starter FlightPHP dengan integrasi ReactJS. +- [flastro](https://github.com/flightphp/flastro) - Kit starter FlightPHP dengan integrasi Astro. +- [velt](https://github.com/flightphp/velt) - Velt adalah template starter Svelte yang cepat dan mudah dengan backend FlightPHP. -## Butuh Beberapa Inspirasi? +## Butuh Inspirasi? Meskipun ini tidak secara resmi disponsori oleh Tim Flight, ini bisa memberi Anda ide tentang cara menyusun proyek Anda sendiri yang dibangun dengan Flight! +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental adalah aplikasi web penyewaan mobil satu halaman yang ramah seluler, dibangun dengan PHP (FlightPHP), JavaScript, dan MySQL. Ini mendukung pendaftaran pengguna, penelusuran, dan pemesanan mobil, sementara admin dapat mengelola mobil, pengguna, dan pemesanan. Aplikasi ini memiliki REST API, autentikasi JWT, dan desain responsif untuk pengalaman penyewaan modern. - [Decay](https://github.com/boxybird/decay) - Flight v3 dengan HTMX dan SleekDB semuanya tentang zombie! ([Demo](https://decay.andrewrhyand.com)) -- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 dengan Middleware, Pengontrol, Active Record, dan Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Proyek API CRUD sederhana menggunakan framework Flight, yang menyediakan struktur dasar bagi pengguna baru untuk dengan cepat menyiapkan aplikasi PHP dengan operasi CRUD dan konektivitas database. Proyek ini mendemonstrasikan cara menggunakan Flight untuk pengembangan API RESTful, menjadikannya alat belajar yang ideal untuk pemula dan kit pemula yang berguna bagi pengembang yang lebih berpengalaman. +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 dengan Middleware, Controllers, Active Record, dan Latte. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Proyek API CRUD sederhana menggunakan framework Flight, yang menyediakan struktur dasar bagi pengguna baru untuk dengan cepat menyiapkan aplikasi PHP dengan operasi CRUD dan konektivitas database. Proyek ini mendemonstrasikan cara menggunakan Flight untuk pengembangan RESTful API, menjadikannya alat pembelajaran ideal bagi pemula dan kit starter yang berguna bagi pengembang yang lebih berpengalaman. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) - [Example Wiki](https://github.com/Skayo/FlightWiki) - [The IT-Innovator PHP Framework Application](https://github.com/itinnovator/myphp-app) -- [LittleEducationalCMS (Spanyol)](https://github.com/casgin/LittleEducationalCMS) -- [API Halaman Kuning Italia](https://github.com/chiccomagnus/PGAPI) -- [Sistem Manajemen Konten Generik (dengan....sangat sedikit dokumentasi)](https://github.com/recepuncu/cms) -- [Framework php kecil yang berbasis pada Flight dan medoo.](https://github.com/ycrao/tinyme) -- [Contoh Aplikasi MVC](https://github.com/paddypei/Flight-MVC) -- [Flight Boilerplate Siap Produksi](https://github.com/madcoda9000/SecStore) - Kerangka kerja autentikasi siap produksi yang menghemat waktu pengembangan Anda selama berminggu-minggu. Dilengkapi keamanan tingkat perusahaan: 2FA/TOTP, integrasi LDAP, Azure SSO, pembatasan kecepatan cerdas, sidik jari sesi, perlindungan brute-force, dasbor analitik keamanan, pencatatan audit komprehensif, dan kontrol akses berbasis peran yang terperinci. +- [LittleEducationalCMS (Spanish)](https://github.com/casgin/LittleEducationalCMS) +- [Italian Yellow Pages API](https://github.com/chiccomagnus/PGAPI) +- [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) +- [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) +- [Example MVC Application](https://github.com/paddypei/Flight-MVC) +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework autentikasi siap produksi yang menghemat minggu pengembangan Anda. Fitur keamanan tingkat enterprise: 2FA/TOTP, integrasi LDAP, Azure SSO, pembatasan tingkat cerdas, fingerprinting sesi, perlindungan brute-force, dasbor analitik keamanan, logging audit komprehensif, dan kontrol akses berbasis peran granular. -## Ingin Membagikan Contoh Anda Sendiri? +## Ingin Berbagi Contoh Anda Sendiri? -Jika Anda memiliki proyek yang ingin Anda bagikan, silakan kirim permintaan tarik untuk menambahkannya ke daftar ini! \ No newline at end of file +Jika Anda memiliki proyek yang ingin dibagikan, silakan kirimkan pull request untuk menambahkannya ke daftar ini! \ No newline at end of file diff --git a/content/v3/id/learn/requests.md b/content/v3/id/learn/requests.md index 16a510e2..1ceef70f 100644 --- a/content/v3/id/learn/requests.md +++ b/content/v3/id/learn/requests.md @@ -10,13 +10,13 @@ $request = Flight::request(); ## Pemahaman -Permintaan HTTP adalah salah satu aspek inti yang perlu dipahami tentang siklus hidup HTTP. Pengguna melakukan aksi pada browser web atau klien HTTP, dan mereka mengirim serangkaian header, body, URL, dll ke proyek Anda. Anda dapat menangkap header ini (bahasa browser, jenis kompresi yang dapat ditangani, agen pengguna, dll) dan menangkap body serta URL yang dikirim ke aplikasi Flight Anda. Permintaan ini sangat penting bagi aplikasi Anda untuk memahami apa yang harus dilakukan selanjutnya. +Permintaan HTTP adalah salah satu aspek inti yang perlu dipahami tentang siklus hidup HTTP. Pengguna melakukan tindakan pada peramban web atau klien HTTP, dan mereka mengirim serangkaian header, body, URL, dll ke proyek Anda. Anda dapat menangkap header ini (bahasa peramban, jenis kompresi yang dapat ditangani, agen pengguna, dll) dan menangkap body serta URL yang dikirim ke aplikasi Flight Anda. Permintaan ini sangat penting agar aplikasi Anda memahami apa yang harus dilakukan selanjutnya. ## Penggunaan Dasar PHP memiliki beberapa super global termasuk `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES`, dan `$_COOKIE`. Flight mengabstraksikan ini menjadi [Collections](/learn/collections) yang berguna. Anda dapat mengakses properti `query`, `data`, `cookies`, dan `files` sebagai array atau objek. -> **Catatan:** Sangat **TIDAK DISARANKAN** untuk menggunakan super global ini di proyek Anda dan seharusnya dirujuk melalui objek `request()`. +> **Catatan:** Sangat **TIDAK DISARANKAN** menggunakan super global ini dalam proyek Anda dan seharusnya dirujuk melalui objek `request()`. > **Catatan:** Tidak ada abstraksi yang tersedia untuk `$_ENV`. @@ -28,7 +28,7 @@ Anda dapat mengakses array `$_GET` melalui properti `query`: // GET /search?keyword=something Flight::route('/search', function(){ $keyword = Flight::request()->query['keyword']; - // or + // atau $keyword = Flight::request()->query->keyword; echo "Anda sedang mencari: $keyword"; // query database atau sesuatu yang lain dengan $keyword @@ -43,7 +43,7 @@ Anda dapat mengakses array `$_POST` melalui properti `data`: Flight::route('POST /submit', function(){ $name = Flight::request()->data['name']; $email = Flight::request()->data['email']; - // or + // atau $name = Flight::request()->data->name; $email = Flight::request()->data->email; echo "Anda mengirimkan: $name, $email"; @@ -58,9 +58,9 @@ Anda dapat mengakses array `$_COOKIE` melalui properti `cookies`: ```php Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; - // or + // atau $savedLogin = Flight::request()->cookies->myLoginCookie; - // periksa apakah benar-benar disimpan atau tidak dan jika ya, login otomatis + // periksa apakah benar-benar tersimpan atau tidak dan jika ya, login otomatis mereka if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -68,7 +68,7 @@ Flight::route('GET /login', function(){ }); ``` -Untuk bantuan tentang pengaturan nilai cookie baru, lihat [overclokk/cookie](/awesome-plugins/php-cookie) +Untuk bantuan dalam mengatur nilai cookie baru, lihat [overclokk/cookie](/awesome-plugins/php-cookie) ### `$_SERVER` @@ -86,7 +86,7 @@ Anda dapat mengakses file yang diunggah melalui properti `files`: ```php // akses mentah ke properti $_FILES. Lihat di bawah untuk pendekatan yang direkomendasikan $uploadedFile = Flight::request()->files['myFile']; -// or +// atau $uploadedFile = Flight::request()->files->myFile; ``` @@ -96,7 +96,7 @@ Lihat [Uploaded File Handler](/learn/uploaded-file) untuk info lebih lanjut. _v3.12.0_ -Anda dapat memproses unggahan file menggunakan framework dengan beberapa metode pembantu. Pada dasarnya, ini merangkum menarik data file dari permintaan, dan memindahkannya ke lokasi baru. +Anda dapat memproses unggahan file menggunakan framework dengan beberapa metode bantu. Ini pada dasarnya berarti menarik data file dari permintaan, dan memindahkannya ke lokasi baru. ```php Flight::route('POST /upload', function(){ @@ -119,11 +119,11 @@ Flight::route('POST /upload', function(){ }); ``` -> **Catatan Keamanan:** Selalu validasi dan sanitasi input pengguna, terutama saat berurusan dengan unggahan file. Selalu validasi jenis ekstensi yang akan diizinkan untuk diunggah, tetapi Anda juga harus memvalidasi "magic bytes" dari file untuk memastikan itu benar-benar jenis file yang diklaim pengguna. Ada [artikel](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [dan](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [library](https://github.com/RikudouSage/MimeTypeDetector) yang tersedia untuk membantu dengan ini. +> **Catatan Keamanan:** Selalu validasi dan sanitasi input pengguna, terutama saat menangani unggahan file. Selalu validasi jenis ekstensi yang akan diizinkan diunggah, tetapi Anda juga harus memvalidasi "magic bytes" file untuk memastikan itu benar-benar jenis file yang diklaim pengguna. Ada [artikel](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [dan](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [library](https://github.com/RikudouSage/MimeTypeDetector) yang tersedia untuk membantu dengan ini. ### Body Permintaan -Untuk mendapatkan body permintaan HTTP mentah, misalnya saat berurusan dengan permintaan POST/PUT, +Untuk mendapatkan body permintaan HTTP mentah, misalnya saat menangani permintaan POST/PUT, Anda dapat melakukan: ```php @@ -150,12 +150,12 @@ Anda dapat mengakses header permintaan menggunakan metode `getHeader()` atau `ge // Mungkin Anda membutuhkan header Authorization $host = Flight::request()->getHeader('Authorization'); -// or +// atau $host = Flight::request()->header('Authorization'); // Jika Anda perlu mengambil semua header $headers = Flight::request()->getHeaders(); -// or +// atau $headers = Flight::request()->headers(); ``` @@ -183,11 +183,11 @@ Objek permintaan menyediakan properti berikut: - **ip** - Alamat IP klien - **ajax** - Apakah permintaan adalah permintaan AJAX - **scheme** - Protokol server (http, https) -- **user_agent** - Informasi browser +- **user_agent** - Informasi peramban - **type** - Jenis konten - **length** - Panjang konten - **query** - Parameter string query -- **data** - Data post atau data JSON +- **data** - Data POST atau data JSON - **cookies** - Data cookie - **files** - File yang diunggah - **secure** - Apakah koneksi aman @@ -196,9 +196,9 @@ Objek permintaan menyediakan properti berikut: - **host** - Nama host permintaan - **servername** - SERVER_NAME dari `$_SERVER` -## Metode Pembantu +## Metode Bantu -Ada beberapa metode pembantu untuk menyusun bagian dari URL, atau berurusan dengan header tertentu. +Ada beberapa metode bantu untuk menyusun bagian-bagian URL, atau menangani header tertentu. ### URL Lengkap @@ -208,7 +208,6 @@ Anda dapat mengakses URL permintaan lengkap menggunakan metode `getFullUrl()`: $url = Flight::request()->getFullUrl(); // https://example.com/some/path?foo=bar ``` - ### URL Dasar Anda dapat mengakses URL dasar menggunakan metode `getBaseUrl()`: @@ -246,16 +245,16 @@ if ($typeToServe === 'application/json') { } elseif ($typeToServe === 'application/xml') { // Layani respons XML } else { - // Default ke sesuatu yang lain atau lempar error + // Default ke sesuatu yang lain atau lempar kesalahan } ``` -> **Catatan:** Jika tidak ada jenis yang tersedia yang ditemukan dalam header `Accept`, metode akan mengembalikan `null`. Jika tidak ada header `Accept` yang didefinisikan, metode akan mengembalikan jenis pertama dalam array `$availableTypes`. +> **Catatan:** Jika tidak ada jenis yang tersedia ditemukan dalam header `Accept`, metode akan mengembalikan `null`. Jika tidak ada header `Accept` yang didefinisikan, metode akan mengembalikan jenis pertama dalam array `$availableTypes`. ## Lihat Juga -- [Routing](/learn/routing) - Lihat cara memetakan rute ke controller dan render tampilan. +- [Routing](/learn/routing) - Lihat cara memetakan rute ke controller dan merender tampilan. - [Responses](/learn/responses) - Cara menyesuaikan respons HTTP. -- [Mengapa Framework?](/learn/why-frameworks) - Bagaimana permintaan cocok ke dalam gambaran besar. +- [Why a Framework?](/learn/why-frameworks) - Bagaimana permintaan cocok ke dalam gambaran besar. - [Collections](/learn/collections) - Bekerja dengan kumpulan data. - [Uploaded File Handler](/learn/uploaded-file) - Menangani unggahan file. @@ -264,5 +263,5 @@ if ($typeToServe === 'application/json') { ## Changelog - v3.17.2 - Menambahkan negotiateContentType() -- v3.12.0 - Menambahkan kemampuan untuk menangani unggahan file melalui objek permintaan. +- v3.12.0 - Menambahkan kemampuan menangani unggahan file melalui objek request. - v1.0 - Rilis awal. \ No newline at end of file diff --git a/content/v3/id/learn/routing.md b/content/v3/id/learn/routing.md index bfcf3a82..a3765c9c 100644 --- a/content/v3/id/learn/routing.md +++ b/content/v3/id/learn/routing.md @@ -1,17 +1,17 @@ # Routing -## Overview -Routing di Flight PHP memetakan pola URL ke fungsi callback atau metode kelas, memungkinkan penanganan permintaan yang cepat dan sederhana. Ini dirancang untuk overhead minimal, penggunaan yang ramah pemula, dan keterluangan tanpa ketergantungan eksternal. +## Gambaran Umum +Routing di Flight PHP memetakan pola URL ke fungsi callback atau metode kelas, memungkinkan penanganan permintaan yang cepat dan sederhana. Ini dirancang untuk overhead minimal, penggunaan yang ramah pemula, dan kemampuan ekstensi tanpa ketergantungan eksternal. -## Understanding -Routing adalah mekanisme inti yang menghubungkan permintaan HTTP ke logika aplikasi Anda di Flight. Dengan mendefinisikan rute, Anda menentukan bagaimana URL yang berbeda memicu kode spesifik, baik melalui fungsi, metode kelas, atau aksi pengontrol. Sistem routing Flight fleksibel, mendukung pola dasar, parameter bernama, ekspresi reguler, dan fitur lanjutan seperti injeksi dependensi dan routing sumber daya. Pendekatan ini menjaga kode Anda terorganisir dan mudah dipelihara, sambil tetap cepat dan sederhana untuk pemula serta dapat dikembangkan untuk pengguna lanjutan. +## Pemahaman +Routing adalah mekanisme inti yang menghubungkan permintaan HTTP ke logika aplikasi Anda di Flight. Dengan mendefinisikan rute, Anda menentukan bagaimana URL yang berbeda memicu kode spesifik, baik melalui fungsi, metode kelas, atau aksi pengontrol. Sistem routing Flight fleksibel, mendukung pola dasar, parameter bernama, ekspresi reguler, dan fitur lanjutan seperti injeksi dependensi dan routing sumber daya. Pendekatan ini menjaga kode Anda tetap terorganisir dan mudah dipelihara, sambil tetap cepat dan sederhana untuk pemula serta dapat diekstensikan untuk pengguna lanjutan. > **Catatan:** Ingin memahami lebih lanjut tentang routing? Lihat halaman ["why a framework?"](/learn/why-frameworks) untuk penjelasan yang lebih mendalam. -## Basic Usage +## Penggunaan Dasar ### Mendefinisikan Rute Sederhana -Routing dasar di Flight dilakukan dengan mencocokkan pola URL dengan fungsi callback atau array kelas dan metode. +Routing dasar di Flight dilakukan dengan mencocokkan pola URL dengan fungsi callback atau array dari kelas dan metode. ```php Flight::route('/', function(){ @@ -22,7 +22,7 @@ Flight::route('/', function(){ > Rute dicocokkan sesuai urutan yang didefinisikan. Rute pertama yang cocok dengan permintaan akan dipanggil. ### Menggunakan Fungsi sebagai Callback -Callback dapat berupa objek apa pun yang dapat dipanggil. Jadi Anda dapat menggunakan fungsi biasa: +Callback bisa berupa objek apa pun yang dapat dipanggil. Jadi Anda bisa menggunakan fungsi biasa: ```php function hello() { @@ -33,7 +33,7 @@ Flight::route('/', 'hello'); ``` ### Menggunakan Kelas dan Metode sebagai Pengontrol -Anda juga dapat menggunakan metode (statis atau tidak) dari sebuah kelas: +Anda juga bisa menggunakan metode (statis atau tidak) dari kelas: ```php class GreetingController { @@ -44,14 +44,14 @@ class GreetingController { Flight::route('/', [ 'GreetingController','hello' ]); // or -Flight::route('/', [ GreetingController::class, 'hello' ]); // metode yang disukai +Flight::route('/', [ GreetingController::class, 'hello' ]); // preferred method // or Flight::route('/', [ 'GreetingController::hello' ]); // or Flight::route('/', [ 'GreetingController->hello' ]); ``` -Atau dengan membuat objek terlebih dahulu dan kemudian memanggil metode: +Atau dengan membuat objek terlebih dahulu lalu memanggil metodenya: ```php use flight\Engine; @@ -77,12 +77,11 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **Catatan:** Secara default, ketika pengontrol dipanggil dalam framework, kelas `flight\Engine` selalu disuntikkan kecuali Anda menentukannya melalui [dependency injection container](/learn/dependency-injection-container) +> **Catatan:** Secara default, ketika pengontrol dipanggil dalam kerangka kerja, kelas `flight\Engine` selalu diinjeksi kecuali Anda menentukannya melalui [container injeksi dependensi](/learn/dependency-injection-container) -### Routing Khusus Metode +### Routing Spesifik Metode -Secara default, pola rute dicocokkan dengan semua metode permintaan. Anda dapat merespons -ke metode spesifik dengan menempatkan pengenal sebelum URL. +Secara default, pola rute dicocokkan dengan semua metode permintaan. Anda bisa merespons metode spesifik dengan menempatkan pengenal sebelum URL. ```php Flight::route('GET /', function () { @@ -101,7 +100,7 @@ Flight::put('/', function() { /* code */ }); Flight::delete('/', function() { /* code */ }); ``` -Anda juga dapat memetakan beberapa metode ke satu callback dengan menggunakan delimiter `|`: +Anda juga bisa memetakan beberapa metode ke satu callback dengan menggunakan pemisah `|`: ```php Flight::route('GET|POST /', function () { @@ -115,8 +114,8 @@ Flight menyediakan penanganan bawaan untuk permintaan HTTP `HEAD` dan `OPTIONS`: #### Permintaan HEAD -- **Permintaan HEAD** diperlakukan seperti permintaan `GET`, tetapi Flight secara otomatis menghapus badan respons sebelum mengirimkannya ke klien. -- Ini berarti Anda dapat mendefinisikan rute untuk `GET`, dan permintaan HEAD ke URL yang sama akan mengembalikan hanya header (tanpa konten), sesuai standar HTTP. +- **Permintaan HEAD** diperlakukan seperti permintaan `GET`, tetapi Flight secara otomatis menghapus isi respons sebelum mengirimkannya ke klien. +- Ini berarti Anda bisa mendefinisikan rute untuk `GET`, dan permintaan HEAD ke URL yang sama akan mengembalikan hanya header (tanpa konten), sesuai standar HTTP. ```php Flight::route('GET /info', function() { @@ -129,7 +128,7 @@ Flight::route('GET /info', function() { Permintaan `OPTIONS` ditangani secara otomatis oleh Flight untuk rute apa pun yang didefinisikan. - Ketika permintaan OPTIONS diterima, Flight merespons dengan status `204 No Content` dan header `Allow` yang mencantumkan semua metode HTTP yang didukung untuk rute tersebut. -- Anda tidak perlu mendefinisikan rute terpisah untuk OPTIONS kecuali Anda ingin perilaku kustom atau memodifikasi respons. +- Anda tidak perlu mendefinisikan rute terpisah untuk OPTIONS. ```php // For a route defined as: @@ -143,7 +142,7 @@ Flight::route('GET|POST /users', function() { /* ... */ }); ### Menggunakan Objek Router -Selain itu, Anda dapat mengambil objek Router yang memiliki beberapa metode pembantu untuk digunakan: +Selain itu, Anda bisa mengambil objek Router yang memiliki beberapa metode pembantu untuk digunakan: ```php @@ -165,7 +164,7 @@ $router->patch('/users/@id', function() { /* code */}); ``` ### Ekspresi Regulasi (Regex) -Anda dapat menggunakan ekspresi reguler di rute Anda: +Anda bisa menggunakan ekspresi reguler di rute Anda: ```php Flight::route('/user/[0-9]+', function () { @@ -173,13 +172,10 @@ Flight::route('/user/[0-9]+', function () { }); ``` -Meskipun metode ini tersedia, disarankan untuk menggunakan parameter bernama, atau -parameter bernama dengan ekspresi reguler, karena lebih mudah dibaca dan dipelihara. +Meskipun metode ini tersedia, disarankan untuk menggunakan parameter bernama, atau parameter bernama dengan ekspresi reguler, karena lebih mudah dibaca dan dipelihara. ### Parameter Bernama -Anda dapat menentukan parameter bernama di rute Anda yang akan diteruskan ke -fungsi callback Anda. **Ini lebih untuk keterbacaan rute daripada yang lain. -Silakan lihat bagian di bawah tentang peringatan penting.** +Anda bisa menentukan parameter bernama di rute Anda yang akan diteruskan ke fungsi callback Anda. **Ini lebih untuk keterbacaan rute daripada hal lain. Lihat bagian di bawah tentang peringatan penting.** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -187,8 +183,7 @@ Flight::route('/@name/@id', function (string $name, string $id) { }); ``` -Anda juga dapat menyertakan ekspresi reguler dengan parameter bernama Anda dengan menggunakan -delimiter `:`: +Anda juga bisa menyertakan ekspresi reguler dengan parameter bernama Anda dengan menggunakan pemisah `:`: ```php Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { @@ -201,7 +196,7 @@ Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { #### Peringatan Penting -Meskipun dalam contoh di atas, tampaknya `@name` langsung terkait dengan variabel `$name`, sebenarnya tidak. Urutan parameter dalam fungsi callback yang menentukan apa yang diteruskan ke dalamnya. Jika Anda menukar urutan parameter dalam fungsi callback, variabel juga akan ditukar. Berikut adalah contoh: +Meskipun dalam contoh di atas, tampaknya `@name` langsung terkait dengan variabel `$name`, sebenarnya bukan. Urutan parameter dalam fungsi callback yang menentukan apa yang diteruskan kepadanya. Jika Anda menukar urutan parameter dalam fungsi callback, variabel juga akan bertukar. Berikut contohnya: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -210,11 +205,10 @@ Flight::route('/@name/@id', function (string $id, string $name) { ``` Dan jika Anda mengunjungi URL berikut: `/bob/123`, outputnya akan menjadi `hello, 123 (bob)!`. -_Harap berhati-hati_ saat menyiapkan rute dan fungsi callback Anda! +_Please be careful_ ketika Anda menyiapkan rute dan fungsi callback Anda! ### Parameter Opsional -Anda dapat menentukan parameter bernama yang opsional untuk pencocokan dengan membungkus -segmen dalam tanda kurung. +Anda bisa menentukan parameter bernama yang opsional untuk pencocokan dengan membungkus segmen dalam tanda kurung. ```php Flight::route( @@ -232,8 +226,7 @@ Flight::route( Parameter opsional apa pun yang tidak cocok akan diteruskan sebagai `NULL`. ### Routing Wildcard -Pencocokan hanya dilakukan pada segmen URL individu. Jika Anda ingin mencocokkan beberapa -segmen, Anda dapat menggunakan wildcard `*`. +Pencocokan hanya dilakukan pada segmen URL individu. Jika Anda ingin mencocokkan beberapa segmen, Anda bisa menggunakan wildcard `*`. ```php Flight::route('/blog/*', function () { @@ -241,7 +234,7 @@ Flight::route('/blog/*', function () { }); ``` -Untuk merutekan semua permintaan ke satu callback, Anda dapat melakukannya: +Untuk merutekan semua permintaan ke satu callback, Anda bisa lakukan: ```php Flight::route('*', function () { @@ -249,10 +242,10 @@ Flight::route('*', function () { }); ``` -### Penanganan 404 Not Found +### Penanganan 404 Tidak Ditemukan Secara default, jika URL tidak ditemukan, Flight akan mengirim respons `HTTP 404 Not Found` yang sangat sederhana dan polos. -Jika Anda ingin respons 404 yang lebih disesuaikan, Anda dapat [memetakan](/learn/extending) metode `notFound` sendiri: +Jika Anda ingin respons 404 yang lebih disesuaikan, Anda bisa [memetakan](/learn/extending) metode `notFound` sendiri: ```php Flight::map('notFound', function() { @@ -276,7 +269,7 @@ Flight::map('notFound', function() { Secara default, jika URL ditemukan tetapi metode tidak diizinkan, Flight akan mengirim respons `HTTP 405 Method Not Allowed` yang sangat sederhana dan polos (Contoh: Method Not Allowed. Allowed Methods are: GET, POST). Ini juga akan menyertakan header `Allow` dengan metode yang diizinkan untuk URL tersebut. -Jika Anda ingin respons 405 yang lebih disesuaikan, Anda dapat [memetakan](/learn/extending) metode `methodNotFound` sendiri: +Jika Anda ingin respons 405 yang lebih disesuaikan, Anda bisa [memetakan](/learn/extending) metode `methodNotFound` sendiri: ```php use flight\net\Route; @@ -301,16 +294,12 @@ Flight::map('methodNotFound', function(Route $route) { }); ``` -## Advanced Usage +## Penggunaan Lanjutan ### Injeksi Dependensi di Rute -Jika Anda ingin menggunakan injeksi dependensi melalui wadah (PSR-11, PHP-DI, Dice, dll), -satu-satunya jenis rute di mana itu tersedia adalah dengan membuat objek secara langsung sendiri -dan menggunakan wadah untuk membuat objek Anda atau Anda dapat menggunakan string untuk mendefinisikan kelas dan -metode yang akan dipanggil. Anda dapat membaca halaman [Dependency Injection](/learn/dependency-injection-container) untuk -informasi lebih lanjut. +Jika Anda ingin menggunakan injeksi dependensi melalui container (PSR-11, PHP-DI, Dice, dll), satu-satunya jenis rute di mana itu tersedia adalah dengan membuat objek secara langsung sendiri dan menggunakan container untuk membuat objek Anda atau Anda bisa menggunakan string untuk mendefinisikan kelas dan metode yang akan dipanggil. Anda bisa pergi ke halaman [Dependency Injection](/learn/dependency-injection-container) untuk informasi lebih lanjut. -Berikut adalah contoh cepat: +Berikut contoh cepat: ```php @@ -362,10 +351,9 @@ Flight::route('/hello/@id', 'Greeting::hello'); Flight::start(); ``` -### Meneruskan Eksekusi ke Rute Berikutnya +### Mengalihkan Eksekusi ke Rute Berikutnya Deprecated -Anda dapat meneruskan eksekusi ke rute pencocokan berikutnya dengan mengembalikan `true` dari -fungsi callback Anda. +Anda bisa mengalihkan eksekusi ke rute pencocokan berikutnya dengan mengembalikan `true` dari fungsi callback Anda. ```php Flight::route('/user/@name', function (string $name) { @@ -384,7 +372,7 @@ Flight::route('/user/*', function () { Sekarang disarankan untuk menggunakan [middleware](/learn/middleware) untuk menangani kasus penggunaan kompleks seperti ini. ### Alias Rute -Dengan menetapkan alias ke rute, Anda dapat memanggil alias tersebut di aplikasi Anda secara dinamis untuk dihasilkan nanti di kode Anda (contoh: tautan di template HTML, atau menghasilkan URL pengalihan). +Dengan menetapkan alias ke rute, Anda bisa memanggil alias tersebut di aplikasi Anda secara dinamis untuk dihasilkan nanti di kode Anda (contoh: tautan di template HTML, atau menghasilkan URL redirect). ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); @@ -405,7 +393,7 @@ class UserController { ``` -Ini sangat membantu jika URL Anda berubah. Dalam contoh di atas, misalkan pengguna dipindahkan ke `/admin/users/@id` sebagai gantinya. +Ini sangat membantu jika URL Anda berubah. Dalam contoh di atas, katakanlah bahwa users dipindahkan ke `/admin/users/@id` sebagai gantinya. Dengan aliasing di tempat untuk rute, Anda tidak lagi perlu mencari semua URL lama di kode Anda dan mengubahnya karena alias sekarang akan mengembalikan `/admin/users/5` seperti dalam contoh di atas. Alias rute masih berfungsi dalam grup juga: @@ -419,10 +407,10 @@ Flight::group('/users', function() { ``` ### Memeriksa Informasi Rute -Jika Anda ingin memeriksa informasi rute pencocokan, ada 2 cara yang bisa Anda lakukan: +Jika Anda ingin memeriksa informasi rute pencocokan, ada 2 cara Anda bisa lakukan ini: -1. Anda dapat menggunakan properti `executedRoute` pada objek `Flight::router()`. -2. Anda dapat meminta objek rute diteruskan ke callback Anda dengan meneruskan `true` sebagai parameter ketiga dalam metode rute. Objek rute selalu menjadi parameter terakhir yang diteruskan ke fungsi callback Anda. +1. Anda bisa menggunakan properti `executedRoute` pada objek `Flight::router()`. +2. Anda bisa meminta objek rute diteruskan ke callback Anda dengan meneruskan `true` sebagai parameter ketiga dalam metode rute. Objek rute akan selalu menjadi parameter terakhir yang diteruskan ke fungsi callback Anda. #### `executedRoute` ```php @@ -452,7 +440,7 @@ Flight::route('/', function() { }); ``` -> **Catatan:** Properti `executedRoute` hanya akan diatur setelah rute dieksekusi. Jika Anda mencoba mengaksesnya sebelum rute dieksekusi, itu akan menjadi `NULL`. Anda juga dapat menggunakan executedRoute di [middleware](/learn/middleware) juga! +> **Catatan:** Properti `executedRoute` hanya akan ditetapkan setelah rute dieksekusi. Jika Anda mencoba mengaksesnya sebelum rute dieksekusi, itu akan menjadi `NULL`. Anda juga bisa menggunakan executedRoute di [middleware](/learn/middleware) juga! #### Meneruskan `true` ke definisi rute ```php @@ -482,7 +470,7 @@ Flight::route('/', function(\flight\net\Route $route) { ### Pengelompokan Rute dan Middleware Mungkin ada saatnya Anda ingin mengelompokkan rute terkait bersama (seperti `/api/v1`). -Anda dapat melakukan ini dengan menggunakan metode `group`: +Anda bisa lakukan ini dengan menggunakan metode `group`: ```php Flight::group('/api/v1', function () { @@ -496,7 +484,7 @@ Flight::group('/api/v1', function () { }); ``` -Anda bahkan dapat menumpuk grup dari grup: +Anda bahkan bisa menumpuk grup dari grup: ```php Flight::group('/api', function () { @@ -526,7 +514,7 @@ Flight::group('/api', function () { #### Pengelompokan dengan Konteks Objek -Anda masih dapat menggunakan pengelompokan rute dengan objek `Engine` dengan cara berikut: +Anda masih bisa menggunakan pengelompokan rute dengan objek `Engine` dengan cara berikut: ```php $app = Flight::app(); @@ -548,7 +536,7 @@ $app->group('/api/v1', function (Router $router) { #### Pengelompokan dengan Middleware -Anda juga dapat menetapkan middleware ke grup rute: +Anda juga bisa menetapkan middleware ke grup rute: ```php Flight::group('/api/v1', function () { @@ -561,8 +549,7 @@ Flight::group('/api/v1', function () { Lihat detail lebih lanjut di halaman [group middleware](/learn/middleware#grouping-middleware). ### Routing Sumber Daya -Anda dapat membuat set rute untuk sumber daya menggunakan metode `resource`. Ini akan membuat -set rute untuk sumber daya yang mengikuti konvensi RESTful. +Anda bisa membuat set rute untuk sumber daya menggunakan metode `resource`. Ini akan membuat set rute untuk sumber daya yang mengikuti konvensi RESTful. Untuk membuat sumber daya, lakukan hal berikut: @@ -619,18 +606,16 @@ class UsersController } ``` -> **Catatan**: Anda dapat melihat rute yang baru ditambahkan dengan `runway` dengan menjalankan `php runway routes`. +> **Catatan**: Anda bisa melihat rute yang baru ditambahkan dengan `runway` dengan menjalankan `php runway routes`. #### Menyesuaikan Rute Sumber Daya Ada beberapa opsi untuk mengonfigurasi rute sumber daya. -##### Alias Base +##### Alias Dasar -Anda dapat mengonfigurasi `aliasBase`. Secara default alias adalah bagian terakhir dari URL yang ditentukan. -Misalnya `/users/` akan menghasilkan `aliasBase` dari `users`. Ketika rute ini dibuat, -aliasnya adalah `users.index`, `users.create`, dll. Jika Anda ingin mengubah alias, atur `aliasBase` -ke nilai yang Anda inginkan. +Anda bisa mengonfigurasi `aliasBase`. Secara default alias adalah bagian terakhir dari URL yang ditentukan. +Misalnya `/users/` akan menghasilkan `aliasBase` dari `users`. Ketika rute ini dibuat, aliasnya adalah `users.index`, `users.create`, dll. Jika Anda ingin mengubah alias, tetapkan `aliasBase` ke nilai yang Anda inginkan. ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); @@ -638,7 +623,7 @@ Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); ##### Only dan Except -Anda juga dapat menentukan rute mana yang ingin Anda buat dengan menggunakan opsi `only` dan `except`. +Anda juga bisa menentukan rute mana yang ingin Anda buat dengan menggunakan opsi `only` dan `except`. ```php // Whitelist only these methods and blacklist the rest @@ -650,11 +635,11 @@ Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` -Ini pada dasarnya opsi whitelisting dan blacklisting sehingga Anda dapat menentukan rute mana yang ingin Anda buat. +Ini pada dasarnya opsi whitelisting dan blacklisting sehingga Anda bisa menentukan rute mana yang ingin Anda buat. ##### Middleware -Anda juga dapat menentukan middleware yang akan dijalankan pada setiap rute yang dibuat oleh metode `resource`. +Anda juga bisa menentukan middleware yang akan dijalankan pada setiap rute yang dibuat oleh metode `resource`. ```php Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]); @@ -662,16 +647,16 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid ### Respons Streaming -Anda sekarang dapat streaming respons ke klien menggunakan `stream()` atau `streamWithHeaders()`. -Ini berguna untuk mengirim file besar, proses yang berjalan lama, atau menghasilkan respons besar. +Anda sekarang bisa melakukan streaming respons ke klien menggunakan `stream()` atau `streamWithHeaders()`. +Ini berguna untuk mengirim file besar, proses jangka panjang, atau menghasilkan respons besar. Streaming rute ditangani sedikit berbeda daripada rute biasa. > **Catatan:** Respons streaming hanya tersedia jika Anda memiliki [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) yang diatur ke `false`. #### Stream dengan Header Manual -Anda dapat streaming respons ke klien dengan menggunakan metode `stream()` pada rute. Jika Anda -melakukan ini, Anda harus mengatur semua header secara manual sebelum Anda mengeluarkan apa pun ke klien. +Anda bisa melakukan streaming respons ke klien dengan menggunakan metode `stream()` pada rute. Jika Anda +melakukan ini, Anda harus menetapkan semua header secara manual sebelum Anda mengoutput apa pun ke klien. Ini dilakukan dengan fungsi php `header()` atau metode `Flight::response()->setRealHeader()`. ```php @@ -710,7 +695,7 @@ Flight::route('/@filename', function($filename) { #### Stream dengan Header -Anda juga dapat menggunakan metode `streamWithHeaders()` untuk mengatur header sebelum Anda mulai streaming. +Anda juga bisa menggunakan metode `streamWithHeaders()` untuk menetapkan header sebelum Anda mulai streaming. ```php Flight::route('/stream-users', function() { @@ -743,24 +728,23 @@ Flight::route('/stream-users', function() { ]); ``` -## See Also +## Lihat Juga - [Middleware](/learn/middleware) - Menggunakan middleware dengan rute untuk autentikasi, logging, dll. - [Dependency Injection](/learn/dependency-injection-container) - Menyederhanakan pembuatan dan pengelolaan objek di rute. -- [Why a Framework?](/learn/why-frameworks) - Memahami manfaat menggunakan framework seperti Flight. -- [Extending](/learn/extending) - Cara memperluas Flight dengan fungsionalitas sendiri termasuk metode `notFound`. +- [Why a Framework?](/learn/why-frameworks) - Memahami manfaat menggunakan kerangka kerja seperti Flight. +- [Extending](/learn/extending) - Cara memperluas Flight dengan fungsionalitas Anda sendiri termasuk metode `notFound`. - [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - Fungsi PHP untuk pencocokan ekspresi reguler. -## Troubleshooting +## Pemecahan Masalah - Parameter rute dicocokkan berdasarkan urutan, bukan nama. Pastikan urutan parameter callback cocok dengan definisi rute. - Menggunakan `Flight::get()` tidak mendefinisikan rute; gunakan `Flight::route('GET /...')` untuk routing atau konteks objek Router di grup (misalnya `$router->get(...)`). -- Properti executedRoute hanya diatur setelah rute dieksekusi; itu NULL sebelum eksekusi. -- Streaming memerlukan fungsionalitas output buffering Flight lama dinonaktifkan (`flight.v2.output_buffering = false`). -- Untuk injeksi dependensi, hanya definisi rute tertentu yang mendukung instansiasi berbasis wadah. +- Properti executedRoute hanya ditetapkan setelah rute dieksekusi; itu NULL sebelum eksekusi. +- Streaming memerlukan fungsi buffering output Flight legacy dinonaktifkan (`flight.v2.output_buffering = false`). +- Untuk injeksi dependensi, hanya definisi rute tertentu yang mendukung instansiasi berbasis container. -### 404 Not Found atau Perilaku Rute yang Tidak Terduga +### 404 Tidak Ditemukan atau Perilaku Rute Tak Terduga -Jika Anda melihat kesalahan 404 Not Found (tetapi Anda bersumpah dengan hidup Anda bahwa itu benar-benar ada dan bukan kesalahan ketik) ini sebenarnya bisa menjadi masalah -dengan Anda mengembalikan nilai di endpoint rute Anda daripada hanya mencetaknya. Alasan untuk ini disengaja tetapi bisa menyelinap pada beberapa pengembang. +Jika Anda melihat kesalahan 404 Tidak Ditemukan (tapi Anda bersumpah dengan hidup Anda bahwa itu benar-benar ada dan bukan kesalahan ketik) ini sebenarnya bisa menjadi masalah dengan Anda mengembalikan nilai di endpoint rute Anda daripada hanya mencetaknya. Alasan untuk ini disengaja tapi bisa menyelinap pada beberapa pengembang. ```php Flight::route('/hello', function(){ @@ -775,8 +759,8 @@ Flight::route('/hello', function(){ ``` Alasan untuk ini adalah karena mekanisme khusus yang dibangun ke dalam router yang menangani output return sebagai sinyal untuk "pergi ke rute berikutnya". -Anda dapat melihat perilaku yang didokumentasikan di bagian [Routing](/learn/routing#passing). +Anda bisa melihat perilaku yang didokumentasikan di bagian [Routing](/learn/routing#passing). ## Changelog - v3: Menambahkan routing sumber daya, alias rute, dan dukungan streaming, grup rute, dan dukungan middleware. -- v1: Mayoritas fitur dasar tersedia. \ No newline at end of file +- v1: Sebagian besar fitur dasar tersedia. \ No newline at end of file diff --git a/content/v3/ja/awesome-plugins/async.md b/content/v3/ja/awesome-plugins/async.md new file mode 100644 index 00000000..4e3d316a --- /dev/null +++ b/content/v3/ja/awesome-plugins/async.md @@ -0,0 +1,212 @@ +# Async + +Async は、Flight フレームワーク用の小さなパッケージで、Swoole、AdapterMan、ReactPHP、Amp、RoadRunner、Workerman などの非同期サーバーおよびランタイム内で Flight アプリを実行できるようにします。デフォルトで Swoole と AdapterMan のアダプターが含まれています。 + +目標:PHP-FPM(または組み込みサーバー)で開発およびデバッグを行い、本番環境では最小限の変更で Swoole(または他の非同期ドライバー)に切り替えることです。 + +## 要件 + +- PHP 7.4 以上 +- Flight フレームワーク 3.16.1 以上 +- [Swoole 拡張](https://www.openswoole.com) + +## インストール + +Composer を使用してインストールします: + +```bash +composer require flightphp/async +``` + +Swoole で実行する予定の場合、拡張をインストールします: + +```bash +# pecl を使用 +pecl install swoole +# または openswoole +pecl install openswoole + +# またはパッケージマネージャー(Debian/Ubuntu の例) +sudo apt-get install php-swoole +``` + +## Swoole の簡単な例 + +以下は、PHP-FPM(または組み込みサーバー)と Swoole の両方を同じコードベースでサポートする方法を示す最小限のセットアップです。 + +プロジェクトで必要なファイル: + +- index.php +- swoole_server.php +- SwooleServerDriver.php + +### index.php + +このファイルは、開発時にアプリを PHP モードで実行するように強制するシンプルなスイッチです。 + +```php +// index.php +route('/', function() use ($app) { + $app->json(['hello' => 'world']); +}); + +if (!defined('NOT_SWOOLE')) { + // Swoole モードで実行する場合に SwooleServerDriver クラスを require します。 + require_once __DIR__ . '/SwooleServerDriver.php'; + + Swoole\Runtime::enableCoroutine(); + $Swoole_Server = new SwooleServerDriver('127.0.0.1', 9501, $app); + $Swoole_Server->start(); +} else { + $app->start(); +} +``` + +### SwooleServerDriver.php + +AsyncBridge と Swoole アダプターを使用して Swoole リクエストを Flight にブリッジする方法を示す簡潔なドライバーです。 + +```php +// SwooleServerDriver.php +Swoole = new SwooleServer($host, $port); + $this->app = $app; + + $this->setDefault(); + $this->bindWorkerEvents(); + $this->bindHttpEvent(); + } + + protected function setDefault() { + $this->Swoole->set([ + 'daemonize' => false, + 'dispatch_mode' => 1, + 'max_request' => 8000, + 'open_tcp_nodelay' => true, + 'reload_async' => true, + 'max_wait_time' => 60, + 'enable_reuse_port' => true, + 'enable_coroutine' => true, + 'http_compression' => false, + 'enable_static_handler' => true, + 'document_root' => __DIR__, + 'static_handler_locations' => ['/css', '/js', '/images', '/.well-known'], + 'buffer_output_size' => 4 * 1024 * 1024, + 'worker_num' => 4, + ]); + + $app = $this->app; + $app->map('stop', function (?int $code = null) use ($app) { + if ($code !== null) { + $app->response()->status($code); + } + }); + } + + protected function bindHttpEvent() { + $app = $this->app; + $AsyncBridge = new AsyncBridge($app); + + $this->Swoole->on('Start', function(SwooleServer $server) { + echo "Swoole http server is started at http://127.0.0.1:9501\n"; + }); + + $this->Swoole->on('Request', function (SwooleRequest $request, SwooleResponse $response) use ($AsyncBridge) { + $SwooleAsyncRequest = new SwooleAsyncRequest($request); + $SwooleAsyncResponse = new SwooleAsyncResponse($response); + + $AsyncBridge->processRequest($SwooleAsyncRequest, $SwooleAsyncResponse); + + $response->end(); + gc_collect_cycles(); + }); + } + + protected function bindWorkerEvents() { + $createPools = function() { + // ここでワーカー固有の接続プールを作成します + }; + $closePools = function() { + // ここでプールを閉じてクリーンアップします + }; + $this->Swoole->on('WorkerStart', $createPools); + $this->Swoole->on('WorkerStop', $closePools); + $this->Swoole->on('WorkerError', $closePools); + } + + public function start() { + $this->Swoole->start(); + } +} +``` + +## サーバーの実行 + +- 開発(PHP 組み込みサーバー / PHP-FPM): + - php -S localhost:8000 (index が public/ にある場合は -t public/ を追加) +- 本番(Swoole): + - php swoole_server.php + +ヒント:本番環境では、TLS、静的ファイル、負荷分散を処理するために Swoole の前にリバースプロキシ(Nginx)を使用してください。 + +## 設定の注意点 + +Swoole ドライバーはいくつかの設定オプションを公開しています: +- worker_num: ワーカープロセスの数 +- max_request: 再起動前のワーカーあたりのリクエスト数 +- enable_coroutine: 並行性のためにコルーチンを使用 +- buffer_output_size: 出力バッファサイズ + +これらをホストのリソースとトラフィックパターンに合わせて調整してください。 + +## エラーハンドリング + +AsyncBridge は Flight のエラーを適切な HTTP レスポンスに変換します。ルートレベルのエラーハンドリングも追加できます: + +```php +$app->route('/*', function() use ($app) { + try { + // ルートロジック + } catch (Exception $e) { + $app->response()->status(500); + $app->json(['error' => $e->getMessage()]); + } +}); +``` + +## AdapterMan および他のランタイム + +[AdapterMan](https://github.com/joanhey/adapterman) は代替ランタイムアダプターとしてサポートされています。このパッケージは適応性が高く設計されており、他のアダプターを追加または使用する場合も、通常同じパターンを踏襲します:サーバーリクエスト/レスポンスを AsyncBridge とランタイム固有のアダプター経由で Flight のリクエスト/レスポンスに変換します。 \ No newline at end of file diff --git a/content/v3/ja/awesome-plugins/awesome_plugins.md b/content/v3/ja/awesome-plugins/awesome_plugins.md index 8376063f..7f5e73f4 100644 --- a/content/v3/ja/awesome-plugins/awesome_plugins.md +++ b/content/v3/ja/awesome-plugins/awesome_plugins.md @@ -1,90 +1,96 @@ # 素晴らしいプラグイン -Flight は非常に拡張性が高いです。Flight アプリケーションに機能を追加するために使用できるプラグインがいくつかあります。一部は Flight チームによって公式にサポートされており、他のものは開始するのに役立つマイクロ/ライトライブラリです。 +Flight は驚くほど拡張性が高いです。Flight アプリケーションに機能を追加するために使用できる多くのプラグインがあります。一部は Flight チームによって公式にサポートされており、他のものはスタートするためのマイクロ/ライトライブラリです。 ## API ドキュメント -API ドキュメントは、API のために不可欠です。開発者が API とどのようにやり取りするかを理解し、何を期待するかを知るのに役立ちます。Flight プロジェクトの API ドキュメントを生成するのに役立つツールがいくつかあります。 +API ドキュメントはどんな API にとっても重要です。開発者が API とどのようにやり取りするかを理解し、何を期待するかを知るのに役立ちます。Flight プロジェクトの API ドキュメントを生成するのに役立ついくつかのツールがあります。 -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber によって書かれたブログ投稿で、OpenAPI Spec を FlightPHP と使用して API ファーストアプローチで API を構築する方法を説明しています。 +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber によるブログ記事で、OpenAPI Spec を FlightPHP と使用して API ファーストアプローチで API を構築する方法について説明しています。 - [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI は、Flight プロジェクトの API ドキュメントを生成するのに役立つ優れたツールです。非常に使いやすく、ニーズに合わせてカスタマイズ可能です。これは Swagger ドキュメントを生成するための PHP ライブラリです。 -## アプリケーション パフォーマンス監視 (APM) +## アプリケーション パフォーマンス モニタリング (APM) -アプリケーション パフォーマンス監視 (APM) は、アプリケーションのために不可欠です。アプリケーションのパフォーマンスを理解し、ボトルネックがどこにあるかを知るのに役立ちます。Flight と使用できる APM ツールがいくつかあります。 -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM は、Flight アプリケーションを監視するために使用できるシンプルな APM ライブラリです。アプリケーションのパフォーマンスを監視し、ボトルネックを特定するのに役立ちます。 +アプリケーション パフォーマンス モニタリング (APM) はどんなアプリケーションにとっても重要です。アプリケーションのパフォーマンスを理解し、ボトルネックの場所を特定するのに役立ちます。Flight で使用できる APM ツールがいくつかあります。 +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM は、Flight アプリケーションを監視するためのシンプルな APM ライブラリです。アプリケーションのパフォーマンスを監視し、ボトルネックを特定するのに使用できます。 + +## 非同期 + +Flight はすでに高速なフレームワークですが、それにターボエンジンを追加するとすべてがより楽しく(そして挑戦的)になります! + +- [flightphp/async](/awesome-plugins/async) - 公式の Flight Async ライブラリです。このライブラリは、アプリケーションに非同期処理を追加するシンプルな方法です。Swoole/Openswoole を内部で使用して、タスクを非同期で実行するシンプルで効果的な方法を提供します。 ## 認可/権限 -認可と権限は、誰が何にアクセスできるかを制御するためのコントロールが必要なアプリケーションのために不可欠です。 +認可と権限は、誰が何にアクセスできるかを制御する必要があるどんなアプリケーションにとっても重要です。 -- official [flightphp/permissions](/awesome-plugins/permissions) - 公式の Flight Permissions ライブラリです。このライブラリは、アプリケーションにユーザーおよびアプリケーション レベルの権限を追加するシンプルな方法です。 +- official [flightphp/permissions](/awesome-plugins/permissions) - 公式の Flight Permissions ライブラリです。このライブラリは、アプリケーションにユーザーおよびアプリケーション レベルの権限を追加するシンプルな方法です。 ## キャッシュ -キャッシュはアプリケーションを高速化する優れた方法です。Flight と使用できるキャッシュ ライブラリがいくつかあります。 +キャッシュはアプリケーションを高速化する優れた方法です。Flight で使用できるキャッシュ ライブラリがいくつかあります。 -- official [flightphp/cache](/awesome-plugins/php-file-cache) - 軽量でシンプルなスタンドアロン PHP イン-File キャッシュ クラス +- official [flightphp/cache](/awesome-plugins/php-file-cache) - 軽量でシンプルなスタンドアローンファイル内キャッシュ PHP クラス ## CLI -CLI アプリケーションは、アプリケーションとやり取りする優れた方法です。コントローラーを生成したり、全ルートを表示したり、その他多くのことを行うために使用できます。 +CLI アプリケーションはアプリケーションとやり取りする優れた方法です。コントローラーの生成、すべてのルートの表示などを使用できます。 -- official [flightphp/runway](/awesome-plugins/runway) - Runway は、Flight アプリケーションを管理するのに役立つ CLI アプリケーションです。 +- official [flightphp/runway](/awesome-plugins/runway) - Runway は Flight アプリケーションを管理するのに役立つ CLI アプリケーションです。 ## クッキー -クッキーは、クライアント側に少量のデータを保存する優れた方法です。ユーザー設定、アプリケーション設定などを保存するために使用できます。 +クッキーはクライアント側に少量のデータを保存する優れた方法です。ユーザーの好み、アプリケーション設定などを保存するために使用できます。 -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie は、クッキーを管理するためのシンプルで効果的な PHP ライブラリを提供します。 +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie は、クッキーを管理するシンプルで効果的な PHP ライブラリです。 ## デバッグ -デバッグは、ローカル環境で開発する際に不可欠です。デバッグ体験を向上させるプラグインがいくつかあります。 +デバッグはローカル環境で開発する際に重要です。デバッグ体験を向上させるいくつかのプラグインがあります。 -- [tracy/tracy](/awesome-plugins/tracy) - これは Flight と使用できる完全な機能のエラーハンドラーです。アプリケーションをデバッグするのに役立つパネルがいくつかあります。また、拡張して独自のパネルを追加するのが非常に簡単です。 +- [tracy/tracy](/awesome-plugins/tracy) - これは Flight で使用できる完全機能のエラーハンドラーです。アプリケーションをデバッグするのに役立ついくつかのパネルがあります。また、拡張して独自のパネルを追加するのが非常に簡単です。 - official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) エラーハンドラーと使用され、このプラグインは Flight プロジェクト専用のデバッグを支援するための追加パネルをいくつか追加します。 ## データベース -データベースはほとんどのアプリケーションのコアです。これによりデータを保存および取得します。一部のデータベース ライブラリはクエリを書くための単なるラッパーで、一部は完全な ORM です。 +データベースはほとんどのアプリケーションのコアです。これでデータを保存および取得します。一部のデータベース ライブラリはクエリを書くための単なるラッパーであり、一部はフル機能の ORM です。 -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - コアの一部である公式の Flight PDO Wrapper です。これはクエリを書くおよび実行するプロセスを簡素化するためのシンプルなラッパーです。ORM ではありません。 -- official [flightphp/active-record](/awesome-plugins/active-record) - 公式の Flight ActiveRecord ORM/マッパーです。データベースからデータを簡単に取得および保存するための優れた小さなライブラリです。 +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - コアの一部である公式の Flight PDO Wrapper です。これはクエリの記述と実行を簡素化するためのシンプルなラッパーです。ORM ではありません。 +- official [flightphp/active-record](/awesome-plugins/active-record) - 公式の Flight ActiveRecord ORM/Mapper です。データベースからデータを簡単に取得および保存するための優れた小さなライブラリです。 - [byjg/php-migration](/awesome-plugins/migrations) - プロジェクトのすべてのデータベース変更を追跡するためのプラグインです。 ## 暗号化 -暗号化は、機密データを保存するアプリケーションのために不可欠です。データを暗号化および復号化するのはそれほど難しくありませんが、暗号化キーを適切に保存するのは [can](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [be](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difficult](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key) です。最も重要なのは、暗号化キーを公開ディレクトリに保存したり、コード リポジトリにコミットしたりしないことです。 +暗号化は機密データを保存するどんなアプリケーションにとっても重要です。データの暗号化と復号化はそれほど難しくありませんが、暗号化キーの適切な保存 [は](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [です](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [難しい](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)。最も重要なのは、暗号化キーをパブリックディレクトリに保存したり、コードリポジトリにコミットしたりしないことです。 -- [defuse/php-encryption](/awesome-plugins/php-encryption) - これはデータを暗号化および復号化するために使用できるライブラリです。データを暗号化および復号化するのを開始するのはかなりシンプルです。 +- [defuse/php-encryption](/awesome-plugins/php-encryption) - これはデータを暗号化および復号化するためのライブラリです。データの暗号化と復号化を開始するのがかなりシンプルです。 ## ジョブキュー -ジョブキューは、タスクを非同期に処理するのに非常に役立ちます。これはメールの送信、画像の処理、またはリアルタイムで実行する必要のないあらゆるものです。 +ジョブキューはタスクを非同期で処理するのに非常に役立ちます。これはメールの送信、画像の処理、またはリアルタイムで必要ない何でもです。 -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue は、ジョブを非同期に処理するために使用できるライブラリです。beanstalkd、MySQL/MariaDB、SQLite、PostgreSQL と使用できます。 +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue は、ジョブを非同期で処理するためのライブラリです。beanstalkd、MySQL/MariaDB、SQLite、PostgreSQL で使用できます。 ## セッション -セッションは API にはあまり有用ではありませんが、Web アプリケーションを構築する際には、状態とログイン情報を維持するために不可欠です。 +セッションは API にはあまり役立ちませんが、Web アプリケーションを構築する際には、状態とログイン情報を維持するために重要です。 -- official [flightphp/session](/awesome-plugins/session) - 公式の Flight Session ライブラリです。これはセッションデータを保存および取得するために使用できるシンプルなセッション ライブラリです。PHP の組み込みセッション ハンドリングを使用します。 +- official [flightphp/session](/awesome-plugins/session) - 公式の Flight Session ライブラリです。これはセッションデータを保存および取得するためのシンプルなセッション ライブラリです。PHP の組み込みセッション処理を使用します。 - [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (非ブロッキング、フラッシュ、セグメント、セッション暗号化)。セッションデータのオプションの暗号化/復号化に PHP open_ssl を使用します。 ## テンプレート -テンプレートは UI を備えた Web アプリケーションのコアです。Flight と使用できるテンプレート エンジンがいくつかあります。 +テンプレートは UI を持つどんな Web アプリケーションにとってもコアです。Flight で使用できるテンプレートエンジンがいくつかあります。 -- deprecated [flightphp/core View](/learn#views) - コアの一部である非常に基本的なテンプレート エンジンです。プロジェクトに数ページ以上ある場合は使用を推奨しません。 -- [latte/latte](/awesome-plugins/latte) - Latte は、Twig や Smarty よりも PHP 構文に近い、非常に使いやすい完全な機能のテンプレート エンジンです。また、拡張して独自のフィルターと関数を追加するのが非常に簡単です。 +- deprecated [flightphp/core View](/learn#views) - コアの一部である非常に基本的なテンプレートエンジンです。プロジェクトに数ページ以上ある場合は使用を推奨しません。 +- [latte/latte](/awesome-plugins/latte) - Latte は、Twig や Smarty よりも PHP 構文に近い、非常に使いやすいフル機能のテンプレートエンジンです。また、拡張して独自のフィルターと関数を追加するのが非常に簡単です。 ## WordPress 統合 -WordPress プロジェクトで Flight を使用したいですか? そのための便利なプラグインがあります! +WordPress プロジェクトで Flight を使用したいですか?そのための便利なプラグインがあります! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - この WordPress プラグインにより、WordPress と並行して Flight を実行できます。カスタム API、マイクロサービス、または Flight フレームワークを使用して WordPress サイトにフルアプリを追加するのに最適です。両方の世界の最高を望む場合に超有用です! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - この WordPress プラグインにより、WordPress と並行して Flight を実行できます。カスタム API、マイクロサービス、または WordPress サイトに Flight フレームワークを使用してフルアプリを追加するのに最適です。両方の世界の最高を望む場合に超便利です! ## 貢献 -共有したいプラグインがありますか? リストに追加するためのプルリクエストを送信してください! \ No newline at end of file +共有したいプラグインがありますか?リストに追加するためのプルリクエストを送信してください! \ No newline at end of file diff --git a/content/v3/ja/examples.md b/content/v3/ja/examples.md index 5776d6d2..ab24d88c 100644 --- a/content/v3/ja/examples.md +++ b/content/v3/ja/examples.md @@ -1,36 +1,37 @@ -# 迅速なスタートが必要ですか? +# クイックスタートが必要ですか? -新しいFlightプロジェクトを始めるためのオプションは2つあります: +新しい Flight プロジェクトを始めるために、2つのオプションがあります: -- [フルスケルトンボイラープレート](https://github.com/flightphp/skeleton): コントローラーとビューを含む、より完全な例です。 -- [シングルファイルスケルトンボイラープレート](https://github.com/flightphp/skeleton-simple): アプリをシンプルな単一ファイルで実行するために必要なすべてを含む単一ファイルです。 +- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): コントローラーとビューを含む、より完全な例。 +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): アプリを単一のシンプルなファイルで実行するために必要なすべてを含む単一のファイル。 -コミュニティが提供した例: +コミュニティ提供の例: -- [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHPとLaravelディレクトリ、PHPツール + GHアクションが含まれています。 -- [fleact](https://github.com/flightphp/fleact) - ReactJSとの統合を持つFlightPHPスターターキット。 -- [flastro](https://github.com/flightphp/flastro) - Astro統合を持つFlightPHPスターターキット。 -- [velt](https://github.com/flightphp/velt) - Veltは、FlightPHPバックエンドを持つ迅速で簡単なSvelteスターターテンプレートです。 +- [flightravel](https://github.com/fadrian06-templates/flighravel): Laravel ディレクトリ付きの FlightPHP、PHP ツール + GH Actions +- [fleact](https://github.com/flightphp/fleact) - ReactJS 統合付きの FlightPHP スターターキット。 +- [flastro](https://github.com/flightphp/flastro) - Astro 統合付きの FlightPHP スターターキット。 +- [velt](https://github.com/flightphp/velt) - Velt は、FlightPHP バックエンド付きのクイックで簡単な Svelte スターターテンプレートです。 ## インスピレーションが必要ですか? -これらはFlightチームによって公式にスポンサーされているわけではありませんが、Flightを使って構築された自分のプロジェクトを構成する方法についてのアイデアを得ることができます! +これらは Flight チームの公式スポンサーではありませんが、Flight で構築した独自のプロジェクトの構造についてのアイデアを提供する可能性があります! -- [Decay](https://github.com/boxybird/decay) - HTMXとSleekDBを使用し、ゾンビに関するFlight v3! ([デモ](https://decay.andrewrhyand.com)) -- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - ミドルウェア、コントローラー、アクティブレコード、Latteを使ったFlight v3。 -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Flightフレームワークを使用したシンプルなCRUD APIプロジェクトで、新しいユーザーがCRUD操作とデータベース接続を迅速に設定できる基本ストラクチャを提供します。このプロジェクトは、RESTful API開発のためのFlightの使用法を示しており、初心者にとって理想的な学習ツールであり、より経験豊富な開発者にとって有用なスターターキットです。 +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental は、PHP (FlightPHP)、JavaScript、MySQL で構築されたシングルページのモバイルフレンドリーなカーレンタルウェブアプリケーションです。ユーザー登録、閲覧、車の予約をサポートし、管理者は車、ユーザー、予約を管理できます。アプリには REST API、JWT 認証、モダンなレンタル体験のためのレスポンシブデザインが備わっています。 +- [Decay](https://github.com/boxybird/decay) - ゾンビについての HTMX と SleekDB 付きの Flight v3! ([Demo](https://decay.andrewrhyand.com)) +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - ミドルウェア、コントローラー、Active Record、Latte 付きの Flight v3。 +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Flight フレームワークを使用したシンプルな CRUD API プロジェクトで、新しいユーザーが CRUD 操作とデータベース接続付きの PHP アプリケーションを迅速にセットアップするための基本構造を提供します。このプロジェクトは、RESTful API 開発のための Flight の使用方法を示し、初心者向けの学習ツールおよび経験豊富な開発者向けの便利なスターターキットとして理想的です。 - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 -- [コメント付きのペーストビン](https://github.com/n0nag0n/commie2) - Flight v3 -- [基本的なスケルトンアプリ](https://github.com/markhughes/flight-skeleton) -- [例のウィキ](https://github.com/Skayo/FlightWiki) -- [ITイノベーターPHPフレームワークアプリケーション](https://github.com/itinnovator/myphp-app) -- [LittleEducationalCMS (スペイン語)](https://github.com/casgin/LittleEducationalCMS) -- [イタリアのイエローページAPI](https://github.com/chiccomagnus/PGAPI) -- [一般的なコンテンツ管理システム (非常に少ないドキュメント付き)](https://github.com/recepuncu/cms) -- [Flightとmedooに基づく小さなphpフレームワーク。](https://github.com/ycrao/tinyme) -- [例のMVCアプリケーション](https://github.com/paddypei/Flight-MVC) -- [本番環境対応のフライトボイラープレート](https://github.com/madcoda9000/SecStore) - 数週間の開発期間を短縮する、本番環境対応の認証フレームワークです。エンタープライズグレードのセキュリティ機能を備えています。2FA/TOTP、LDAP統合、Azure SSO、インテリジェントなレート制限、セッションフィンガープリンティング、ブルートフォース攻撃対策、セキュリティ分析ダッシュボード、包括的な監査ログ、きめ細かなロールベースのアクセス制御などを備えています。 +- [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 +- [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) +- [Example Wiki](https://github.com/Skayo/FlightWiki) +- [The IT-Innovator PHP Framework Application](https://github.com/itinnovator/myphp-app) +- [LittleEducationalCMS (Spanish)](https://github.com/casgin/LittleEducationalCMS) +- [Italian Yellow Pages API](https://github.com/chiccomagnus/PGAPI) +- [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) +- [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) +- [Example MVC Application](https://github.com/paddypei/Flight-MVC) +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 開発を数週間短縮する本番環境対応の認証フレームワーク。エンタープライズグレードのセキュリティ機能:2FA/TOTP、LDAP 統合、Azure SSO、インテリジェントなレート制限、セッションフィンガープリンティング、ブルートフォース保護、セキュリティ分析ダッシュボード、包括的な監査ログ、グラニュラーなロールベースアクセス制御。 ## 自分の例を共有したいですか? -共有したいプロジェクトがある場合は、このリストに追加するためのプルリクエストを送信してください! \ No newline at end of file +共有したいプロジェクトがある場合、このリストに追加するためのプルリクエストを送信してください! \ No newline at end of file diff --git a/content/v3/ja/learn/requests.md b/content/v3/ja/learn/requests.md index 2f32548d..6019e684 100644 --- a/content/v3/ja/learn/requests.md +++ b/content/v3/ja/learn/requests.md @@ -10,13 +10,13 @@ $request = Flight::request(); ## 理解 -HTTP リクエストは、HTTP ライフサイクルの理解に不可欠な核心的な要素の一つです。ユーザーがウェブブラウザや HTTP クライアントでアクションを実行すると、ヘッダー、本文、URL などをプロジェクトに送信します。これらのヘッダー(ブラウザの言語、扱える圧縮の種類、ユーザーエージェントなど)をキャプチャし、Flight アプリケーションに送信される本文と URL をキャプチャできます。これらのリクエストは、アプリが次に何をするかを理解するために不可欠です。 +HTTP リクエストは、HTTP ライフサイクルの理解に不可欠なコア要素の一つです。ユーザーがウェブブラウザや HTTP クライアントでアクションを実行すると、ヘッダー、本文、URL などをあなたのプロジェクトに送信します。これらのヘッダー(ブラウザの言語、扱える圧縮の種類、ユーザーエージェントなど)をキャプチャし、Flight アプリケーションに送信された本文と URL をキャプチャできます。これらのリクエストは、アプリが次に何をするかを理解するために不可欠です。 ## 基本的な使用方法 -PHP には `$_GET`、`$_POST`、`$_REQUEST`、`$_SERVER`、`$_FILES`、`$_COOKIE` などのスーパーグローバル変数があります。Flight はこれらを便利な [Collections](/learn/collections) に抽象化します。`query`、`data`、`cookies`、`files` プロパティを配列またはオブジェクトとしてアクセスできます。 +PHP には `$_GET`、`$_POST`、`$_REQUEST`、`$_SERVER`、`$_FILES`、`$_COOKIE` などのスーパーグローバルがあります。Flight はこれらを便利な [Collections](/learn/collections) に抽象化します。`query`、`data`、`cookies`、`files` プロパティを配列またはオブジェクトとしてアクセスできます。 -> **注意:** プロジェクトでこれらのスーパーグローバル変数を使用することは**強く**推奨されず、`request()` オブジェクト経由で参照する必要があります。 +> **注意:** プロジェクトでこれらのスーパーグローバルを使用することは**強く**推奨されません。`request()` オブジェクト経由で参照してください。 > **注意:** `$_ENV` の抽象化は利用できません。 @@ -30,8 +30,8 @@ Flight::route('/search', function(){ $keyword = Flight::request()->query['keyword']; // または $keyword = Flight::request()->query->keyword; - echo "検索中: $keyword"; - // $keyword でデータベースをクエリしたり、他の操作を行ったりします + echo "You are searching for: $keyword"; + // $keyword でデータベースをクエリしたり、その他のことを行います }); ``` @@ -46,8 +46,8 @@ Flight::route('POST /submit', function(){ // または $name = Flight::request()->data->name; $email = Flight::request()->data->email; - echo "送信された内容: $name, $email"; - // $name と $email でデータベースに保存したり、他の操作を行ったりします + echo "You submitted: $name, $email"; + // $name と $email でデータベースに保存したり、その他のことを行います }); ``` @@ -60,7 +60,7 @@ Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; // または $savedLogin = Flight::request()->cookies->myLoginCookie; - // 保存されているかどうかを確認し、保存されていれば自動的にログインします + // 本当に保存されているかチェックし、保存されている場合は自動的にログインします if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -68,13 +68,14 @@ Flight::route('GET /login', function(){ }); ``` -新しいクッキー値の設定方法については、[overclokk/cookie](/awesome-plugins/php-cookie) を参照してください。 +新しいクッキー値の設定に関するヘルプについては、[overclokk/cookie](/awesome-plugins/php-cookie) を参照してください。 ### `$_SERVER` `$_SERVER` 配列は `getVar()` メソッド経由でアクセスするためのショートカットがあります: ```php + $host = Flight::request()->getVar('HTTP_HOST'); ``` @@ -83,34 +84,34 @@ $host = Flight::request()->getVar('HTTP_HOST'); アップロードされたファイルは `files` プロパティ経由でアクセスできます: ```php -// $_FILES プロパティへの直接アクセス。推奨されるアプローチは以下を参照 +// $_FILES プロパティへの生アクセス。推奨アプローチは以下を参照 $uploadedFile = Flight::request()->files['myFile']; // または $uploadedFile = Flight::request()->files->myFile; ``` -詳細は [Uploaded File Handler](/learn/uploaded-file) を参照してください。 +詳細については [Uploaded File Handler](/learn/uploaded-file) を参照してください。 #### ファイルアップロードの処理 _v3.12.0_ -フレームワークのヘルパーメソッドを使用してファイルアップロードを処理できます。基本的に、リクエストからファイルデータを取得し、新しい場所に移動させるだけです。 +フレームワークを使用してヘルパーメソッドでファイルアップロードを処理できます。基本的に、リクエストからファイルデータを引き出し、新しい場所に移動するだけです。 ```php Flight::route('POST /upload', function(){ - // 入力フィールドが の場合 + // 入力フィールドが のような場合 $uploadedFileData = Flight::request()->getUploadedFiles(); $uploadedFile = $uploadedFileData['myFile']; $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); }); ``` -複数のファイルをアップロードした場合、それらをループで処理できます: +複数のファイルがアップロードされた場合、それらをループで処理できます: ```php Flight::route('POST /upload', function(){ - // 入力フィールドが の場合 + // 入力フィールドが のような場合 $uploadedFiles = Flight::request()->getUploadedFiles()['myFiles']; foreach ($uploadedFiles as $uploadedFile) { $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); @@ -118,22 +119,22 @@ Flight::route('POST /upload', function(){ }); ``` -> **セキュリティ注意:** ユーザー入力の検証とサニタイズを常に実行してください。特にファイルアップロード時には、許可する拡張子の種類を検証し、ファイルの「マジックバイト」を検証して、ユーザーが主張するファイルの種類が本物であることを確認してください。このために [記事](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [や](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [ライブラリ](https://github.com/RikudouSage/MimeTypeDetector) が利用可能です。 +> **セキュリティ注意:** ユーザー入力の検証とサニタイズを常に実行してください。特にファイルアップロードの場合、許可する拡張子の種類を検証し、ファイルの「マジックバイト」を検証して、ユーザーが主張するファイルの種類であることを確認してください。このヘルプには [記事](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [と](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [ライブラリ](https://github.com/RikudouSage/MimeTypeDetector) が利用可能です。 ### リクエスト本文 -POST/PUT リクエストなどで生の HTTP リクエスト本文を取得するには、以下のようにします: +POST/PUT リクエストなどの生の HTTP リクエスト本文を取得するには、以下のようにします: ```php Flight::route('POST /users/xml', function(){ $xmlBody = Flight::request()->getBody(); - // 送信された XML で何らかの操作を行います。 + // 送信された XML で何かを行います。 }); ``` ### JSON 本文 -コンテンツタイプが `application/json` のリクエストで、例として `{"id": 123}` のデータを受け取った場合、`data` プロパティから利用可能です: +コンテンツタイプ `application/json` のリクエストを受け取り、例として `{"id": 123}` のデータの場合、`data` プロパティから利用可能です: ```php $id = Flight::request()->data->id; @@ -141,10 +142,11 @@ $id = Flight::request()->data->id; ### リクエストヘッダー -リクエストヘッダーは `getHeader()` または `getHeaders()` メソッドを使用してアクセスできます: +`getHeader()` または `getHeaders()` メソッドを使用してリクエストヘッダーにアクセスできます: ```php -// Authorization ヘッダーが必要な場合など + +// Authorization ヘッダーが必要な場合 $host = Flight::request()->getHeader('Authorization'); // または $host = Flight::request()->header('Authorization'); @@ -157,14 +159,14 @@ $headers = Flight::request()->headers(); ### リクエストメソッド -リクエストメソッドは `method` プロパティまたは `getMethod()` メソッドを使用してアクセスできます: +`method` プロパティまたは `getMethod()` メソッドを使用してリクエストメソッドにアクセスできます: ```php $method = Flight::request()->method; // 実際には getMethod() で設定されます $method = Flight::request()->getMethod(); ``` -**注意:** `getMethod()` メソッドは最初に `$_SERVER['REQUEST_METHOD']` からメソッドを取得し、存在する場合に `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` または `$_REQUEST['_method']` で上書きされます。 +**注意:** `getMethod()` メソッドは最初に `$_SERVER['REQUEST_METHOD']` からメソッドを引き出し、存在する場合に `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` または `$_REQUEST['_method']` で上書きできます。 ## リクエストオブジェクトのプロパティ @@ -186,18 +188,18 @@ $method = Flight::request()->getMethod(); - **cookies** - クッキーデータ - **files** - アップロードされたファイル - **secure** - 接続がセキュアかどうか -- **accept** - HTTP アクセプトパラメータ +- **accept** - HTTP accept パラメータ - **proxy_ip** - クライアントのプロキシ IP アドレス。`$_SERVER` 配列を `HTTP_CLIENT_IP`、`HTTP_X_FORWARDED_FOR`、`HTTP_X_FORWARDED`、`HTTP_X_CLUSTER_CLIENT_IP`、`HTTP_FORWARDED_FOR`、`HTTP_FORWARDED` の順でスキャンします。 - **host** - リクエストホスト名 - **servername** - `$_SERVER` からの SERVER_NAME ## ヘルパーメソッド -URL の一部を組み合わせたり、特定のヘッダーを扱ったりするためのいくつかのヘルパーメソッドがあります。 +URL の一部を組み合わせたり、特定のヘッダーを扱うためのいくつかのヘルパーメソッドがあります。 ### フル URL -フルリクエスト URL は `getFullUrl()` メソッドを使用してアクセスできます: +`getFullUrl()` メソッドを使用してフルリクエスト URL にアクセスできます: ```php $url = Flight::request()->getFullUrl(); @@ -206,7 +208,7 @@ $url = Flight::request()->getFullUrl(); ### ベース URL -ベース URL は `getBaseUrl()` メソッドを使用してアクセスできます: +`getBaseUrl()` メソッドを使用してベース URL にアクセスできます: ```php // http://example.com/path/to/something/cool?query=yes+thanks @@ -224,13 +226,14 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` -## コンテンツアクセプトタイプのネゴシエーション +## コンテンツ Accept タイプのネゴシエーション _v3.17.2_ `negotiateContentType()` メソッドを使用して、クライアントが送信した `Accept` ヘッダーに基づいて、最適なコンテンツタイプを決定できます。 ```php + // 例: Accept ヘッダー: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 // 以下でサポートするものを定義します。 $availableTypes = ['application/json', 'application/xml']; @@ -240,17 +243,17 @@ if ($typeToServe === 'application/json') { } elseif ($typeToServe === 'application/xml') { // XML レスポンスを送信 } else { - // デフォルトで他のものを送信するか、エラーをスロー + // デフォルトで何か他のものを設定するか、エラーをスロー } ``` > **注意:** `Accept` ヘッダーに利用可能なタイプが見つからない場合、メソッドは `null` を返します。`Accept` ヘッダーが定義されていない場合、メソッドは `$availableTypes` 配列の最初のタイプを返します。 -## 関連トピック -- [Routing](/learn/routing) - ルートをコントローラーにマッピングし、ビューをレンダリングする方法。 -- [Responses](/learn/responses) - HTTP レスポンスのカスタマイズ方法。 -- [Why a Framework?](/learn/why-frameworks) - リクエストが全体像にどのように適合するか。 -- [Collections](/learn/collections) - データのコレクションの操作。 +## 関連項目 +- [Routing](/learn/routing) - ルートをコントローラーにマッピングし、ビューをレンダリングする方法を参照。 +- [Responses](/learn/responses) - HTTP レスポンスをカスタマイズする方法。 +- [Why a Framework?](/learn/why-frameworks) - リクエストが全体像にどのように適合するかを理解。 +- [Collections](/learn/collections) - データのコレクションを扱う。 - [Uploaded File Handler](/learn/uploaded-file) - ファイルアップロードの処理。 ## トラブルシューティング @@ -258,5 +261,5 @@ if ($typeToServe === 'application/json') { ## 変更履歴 - v3.17.2 - negotiateContentType() を追加 -- v3.12.0 - リクエストオブジェクト経由でファイルアップロードを処理する機能を追加 -- v1.0 - 初回リリース \ No newline at end of file +- v3.12.0 - リクエストオブジェクト経由でファイルアップロードを扱う機能を追加。 +- v1.0 - 初回リリース。 \ No newline at end of file diff --git a/content/v3/ja/learn/routing.md b/content/v3/ja/learn/routing.md index 850993a2..58447351 100644 --- a/content/v3/ja/learn/routing.md +++ b/content/v3/ja/learn/routing.md @@ -1,17 +1,17 @@ # ルーティング ## 概要 -Flight PHP のルーティングは、URL パターンをコールバック関数やクラスメソッドにマッピングし、高速でシンプルなリクエスト処理を可能にします。最小限のオーバーヘッド、初心者向けの使用しやすさ、そして外部依存なしの拡張性を設計の目標としています。 +Flight PHP のルーティングは、URL パターンをコールバック関数やクラスメソッドにマッピングし、高速でシンプルなリクエスト処理を可能にします。最小限のオーバーヘッド、初心者向けの使いやすさ、外部依存なしの拡張性を目的として設計されています。 ## 理解 -ルーティングは、Flight 内で HTTP リクエストをアプリケーションのロジックに接続するコアメカニズムです。ルートを定義することで、異なる URL が特定のコードをトリガーする方法を指定します。これは関数、クラスメソッド、またはコントローラーアクションを通じて行われます。Flight のルーティングシステムは柔軟で、基本パターン、名前付きパラメータ、正規表現、依存性注入やリソースフルルーティングなどの高度な機能をサポートします。このアプローチにより、コードを整理しやすくメンテナンスしやすく保ちつつ、初心者には高速でシンプルに、進んだユーザーには拡張可能に保てます。 +ルーティングは、Flight で HTTP リクエストをアプリケーションのロジックに接続するコアメカニズムです。ルートを定義することで、異なる URL が関数、クラスメソッド、またはコントローラーアクションを通じて特定のコードをトリガーする方法を指定します。Flight のルーティングシステムは柔軟で、基本パターン、名前付きパラメータ、正規表現、依存性注入やリソースフルルーティングなどの高度な機能をサポートしています。このアプローチにより、コードを整理しやすくメンテナンスしやすくし、初心者には高速でシンプルに、上級者には拡張可能に保ちます。 > **注意:** ルーティングについてさらに理解したいですか?より詳細な説明のために、["なぜフレームワーク?"](/learn/why-frameworks) ページを参照してください。 ## 基本的な使用方法 ### シンプルなルートの定義 -Flight での基本的なルーティングは、URL パターンをコールバック関数またはクラスとメソッドの配列にマッチさせることで行われます。 +Flight の基本的なルーティングは、URL パターンをコールバック関数またはクラスとメソッドの配列にマッチさせることで行われます。 ```php Flight::route('/', function(){ @@ -19,7 +19,7 @@ Flight::route('/', function(){ }); ``` -> ルートは定義された順序でマッチされます。リクエストに最初にマッチするルートが呼び出されます。 +> ルートは定義された順序でマッチされます。リクエストに最初にマッチしたルートが呼び出されます。 ### コールバックとしての関数の使用 コールバックは任意の呼び出し可能なオブジェクトを使用できます。したがって、通常の関数を使用できます: @@ -77,7 +77,7 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **注意:** フレームワーク内でコントローラーが呼び出される場合、デフォルトで `flight\Engine` クラスが常に注入されます。[依存性注入コンテナ](/learn/dependency-injection-container) を通じて指定しない限りです。 +> **注意:** フレームワーク内でコントローラーが呼び出される場合、デフォルトで `flight\Engine` クラスが常に注入されます。ただし、[依存性注入コンテナ](/learn/dependency-injection-container) を通じて指定しない限りです。 ### メソッド固有のルーティング @@ -92,7 +92,7 @@ Flight::route('POST /', function () { echo 'I received a POST request.'; }); -// Flight::get() をルートに使用できません。それは変数を取得するためのメソッドで、ルートを作成するものではありません。 +// Flight::get() をルートに使用できません。これは変数を取得するためのメソッドで、ルートを作成するものではありません。 Flight::post('/', function() { /* code */ }); Flight::patch('/', function() { /* code */ }); Flight::put('/', function() { /* code */ }); @@ -109,12 +109,12 @@ Flight::route('GET|POST /', function () { ### HEAD と OPTIONS リクエストの特別な処理 -Flight は `HEAD` と `OPTIONS` HTTP リクエストの組み込み処理を提供します: +Flight は `HEAD` と `OPTIONS` HTTP リクエストに対して組み込みの処理を提供します: #### HEAD リクエスト -- **HEAD リクエスト** は `GET` リクエストと同様に扱われますが、Flight はクライアントに送信する前にレスポンスボディを自動的に削除します。 -- これにより、`GET` のルートを定義でき、同じ URL への HEAD リクエストはヘッダーのみ(コンテンツなし)を返し、HTTP 標準に従います。 +- **HEAD リクエスト** は `GET` リクエストと同様に扱われますが、Flight はクライアントに送信する前に自動的にレスポンスボディを削除します。 +- これにより、`GET` のルートを定義すると、同じ URL への HEAD リクエストはヘッダーのみ(コンテンツなし)を返し、HTTP 標準に準拠します。 ```php Flight::route('GET /info', function() { @@ -127,7 +127,7 @@ Flight::route('GET /info', function() { `OPTIONS` リクエストは、定義された任意のルートに対して Flight によって自動的に処理されます。 - OPTIONS リクエストを受け取ると、Flight は `204 No Content` ステータスと、そのルートでサポートされるすべての HTTP メソッドをリストした `Allow` ヘッダーで応答します。 -- カスタム動作やレスポンスの変更を望まない限り、OPTIONS 用の別ルートを定義する必要はありません。 +- OPTIONS 用の別々のルートを定義する必要はありません。 ```php // 以下のように定義されたルートの場合: @@ -141,7 +141,7 @@ Flight::route('GET|POST /users', function() { /* ... */ }); ### ルーターオブジェクトの使用 -さらに、ヘルパーメソッドを持つルーターオブジェクトを取得できます: +さらに、ヘルパーメソッドを含むルーターオブジェクトを取得できます: ```php $router = Flight::router(); @@ -166,14 +166,14 @@ $router->patch('/users/@id', function() { /* code */}); ```php Flight::route('/user/[0-9]+', function () { - // /user/1234 にマッチします + // これにより /user/1234 がマッチします }); ``` この方法は利用可能ですが、名前付きパラメータ、または正規表現付きの名前付きパラメータを使用することを推奨します。これらはより読みやすく、メンテナンスしやすいためです。 ### 名前付きパラメータ -ルートで名前付きパラメータを指定でき、コールバック関数に渡されます。**これは主にルートの可読性のためです。重要な注意事項については以下のセクションを参照してください。** +ルートで名前付きパラメータを指定すると、コールバック関数に渡されます。**これはルートの読みやすさのためです。何よりも重要です。以下のセクションの重要な注意事項を参照してください。** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -185,16 +185,16 @@ Flight::route('/@name/@id', function (string $name, string $id) { ```php Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { - // /bob/123 にマッチします - // /bob/12345 にはマッチしません + // これにより /bob/123 がマッチします + // しかし /bob/12345 はマッチしません }); ``` -> **注意:** 位置パラメータとのマッチング regex グループ `()` はサポートされていません。例: `:'\(` +> **注意:** 位置パラメータとのマッチング用 regex グループ `()` はサポートされていません。例: `:'\(` #### 重要な注意事項 -上記の例では、`@name` が直接 `$name` 変数に結びついているように見えますが、そうではありません。コールバック関数のパラメータの順序が何が渡されるかを決定します。コールバック関数のパラメータの順序を切り替えると、変数も切り替わります。例: +上記の例では、`@name` が直接 `$name` 変数に結びついているように見えますが、そうではありません。コールバック関数のパラメータの順序が何が渡されるかを決定します。コールバック関数内のパラメータの順序を切り替えると、変数も切り替わります。例: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -203,7 +203,7 @@ Flight::route('/@name/@id', function (string $id, string $name) { ``` 以下の URL にアクセスした場合:`/bob/123`、出力は `hello, 123 (bob)!` になります。 -ルートとコールバック関数の設定時に _注意してください_! +ルートとコールバック関数の設定時には _注意してください_! ### オプションのパラメータ マッチングにオプションの名前付きパラメータを指定するには、セグメントを括弧で囲みます。 @@ -212,7 +212,7 @@ Flight::route('/@name/@id', function (string $id, string $name) { Flight::route( '/blog(/@year(/@month(/@day)))', function(?string $year, ?string $month, ?string $day) { - // 以下の URL にマッチします: + // 以下の URL がマッチします: // /blog/2012/12/10 // /blog/2012/12 // /blog/2012 @@ -221,14 +221,14 @@ Flight::route( ); ``` -マッチしないオプションのパラメータは `NULL` として渡されます。 +マッチしなかったオプションのパラメータは `NULL` として渡されます。 ### ワイルドカードルーティング -マッチングは個別の URL セグメントでのみ行われます。複数のセグメントにマッチするには、` * ` ワイルドカードを使用します。 +マッチングは個別の URL セグメントでのみ行われます。複数のセグメントをマッチさせるには、`*` ワイルドカードを使用できます。 ```php Flight::route('/blog/*', function () { - // /blog/2000/02/01 にマッチします + // これにより /blog/2000/02/01 がマッチします }); ``` @@ -242,7 +242,7 @@ Flight::route('*', function () { ### 404 Not Found ハンドラー -デフォルトでは、URL が見つからない場合、Flight は非常にシンプルでプレーンな `HTTP 404 Not Found` レスポンスを送信します。よりカスタマイズされた 404 レスポンスを望む場合、独自の `notFound` メソッドを [マップ](/learn/extending) できます: +デフォルトでは、URL が見つからない場合、Flight は非常にシンプルでプレーンな `HTTP 404 Not Found` レスポンスを送信します。よりカスタマイズされた 404 レスポンスを作成するには、独自の `notFound` メソッドを [マップ](/learn/extending) できます: ```php Flight::map('notFound', function() { @@ -264,9 +264,9 @@ Flight::map('notFound', function() { ### メソッドが見つからないハンドラー -デフォルトでは、URL は見つかるがメソッドが許可されていない場合、Flight は非常にシンプルでプレーンな `HTTP 405 Method Not Allowed` レスポンスを送信します(例: Method Not Allowed. Allowed Methods are: GET, POST)。また、その URL で許可されたメソッドの `Allow` ヘッダーも含めます。 +デフォルトでは、URL は見つかるがメソッドが許可されていない場合、Flight は非常にシンプルでプレーンな `HTTP 405 Method Not Allowed` レスポンスを送信します(例: Method Not Allowed. Allowed Methods are: GET, POST)。また、その URL で許可されたメソッドを含む `Allow` ヘッダーも含めます。 -よりカスタマイズされた 405 レスポンスを望む場合、独自の `methodNotFound` メソッドを [マップ](/learn/extending) できます: +よりカスタマイズされた 405 レスポンスを作成するには、独自の `methodNotFound` メソッドを [マップ](/learn/extending) できます: ```php use flight\net\Route; @@ -294,7 +294,7 @@ Flight::map('methodNotFound', function(Route $route) { ## 高度な使用方法 ### ルートでの依存性注入 -コンテナ(PSR-11、PHP-DI、Dice など)を介した依存性注入を使用する場合、利用可能なルートのタイプは、自身でオブジェクトを作成しコンテナでオブジェクトを作成するか、クラスとメソッドを呼び出す文字列を使用するかのいずれかです。詳細は [依存性注入](/learn/dependency-injection-container) ページを参照してください。 +コンテナ(PSR-11、PHP-DI、Dice など)経由で依存性注入を使用する場合、利用可能なルートのタイプは、自身でオブジェクトを作成してコンテナを使用してオブジェクトを作成するか、クラスとメソッドを呼び出す文字列を使用するかのいずれかです。詳細は [依存性注入](/learn/dependency-injection-container) ページを参照してください。 簡単な例: @@ -322,7 +322,7 @@ class Greeting // PSR-11 に関する詳細は依存性注入ページを参照 $dice = new \Dice\Dice(); -// 変数を '$dice = ' で再代入することを忘れずに!!!!! +// '$dice = ' で変数を再割り当てすることを忘れずに!!!!! $dice = $dice->addRule('flight\database\PdoWrapper', [ 'shared' => true, 'constructParams' => [ @@ -347,15 +347,15 @@ Flight::route('/hello/@id', 'Greeting::hello'); Flight::start(); ``` -### 実行を次のルートに渡す +### 次のルートへの実行の引き渡し 非推奨 -コールバック関数から `true` を返すことで、実行を次のマッチするルートに渡せます。 +コールバック関数から `true` を返すことで、次のマッチするルートに実行を引き渡せます。 ```php Flight::route('/user/@name', function (string $name) { // 条件をチェック if ($name !== "Bob") { - // 次のルートに継続 + // 次のルートに続行 return true; } }); @@ -365,10 +365,10 @@ Flight::route('/user/*', function () { }); ``` -このような複雑なユースケースには、[ミドルウェア](/learn/middleware) を使用することを推奨します。 +複雑なユースケースを扱うには、[ミドルウェア](/learn/middleware) を使用することを推奨します。 ### ルートエイリアス -ルートにエイリアスを割り当てることで、後でアプリ内でそのエイリアスを動的に呼び出し、コード内で後で生成できます(例: HTML テンプレート内のリンク、またはリダイレクト URL の生成)。 +ルートにエイリアスを割り当てることで、後でアプリ内で動的にそのエイリアスを呼び出してコード内で生成できます(例: HTML テンプレート内のリンク、またはリダイレクト URL の生成)。 ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); @@ -388,8 +388,7 @@ class UserController { } ``` -URL が変更された場合に特に役立ちます。上記の例で、ユーザーが `/admin/users/@id` に移動されたとします。 -ルートにエイリアスを設定していれば、コード内の古い URL をすべて見つけて変更する必要がなく、エイリアスは上記の例のように `/admin/users/5` を返します。 +URL が変更された場合に特に役立ちます。上記の例で、ユーザーが `/admin/users/@id` に移動したとします。ルートにエイリアスを設定しているため、コード内のすべての古い URL を探して変更する必要はありません。エイリアスは上記の例のように `/admin/users/5` を返します。 グループ内でもルートエイリアスは動作します: @@ -402,10 +401,10 @@ Flight::group('/users', function() { ``` ### ルート情報の検査 -マッチするルート情報を検査したい場合、2 つの方法があります: +マッチしたルート情報を検査するには、2 つの方法があります: -1. `Flight::router()` オブジェクトの `executedRoute` プロパティを使用できます。 -2. ルートメソッドの 3 番目のパラメータに `true` を渡すことで、ルートオブジェクトをコールバックに渡すようリクエストできます。ルートオブジェクトは常にコールバックに渡される最後のパラメータです。 +1. `Flight::router()` オブジェクトの `executedRoute` プロパティを使用します。 +2. ルートメソッドの 3 番目のパラメータに `true` を渡すことで、ルートオブジェクトをコールバックに渡すようリクエストします。ルートオブジェクトはコールバック関数に渡される最後のパラメータになります。 #### `executedRoute` ```php @@ -435,7 +434,7 @@ Flight::route('/', function() { }); ``` -> **注意:** `executedRoute` プロパティはルートが実行された後にのみ設定されます。ルートが実行される前にアクセスしようとすると `NULL` です。[ミドルウェア](/learn/middleware) でも executedRoute を使用できます! +> **注意:** `executedRoute` プロパティは、ルートが実行された後にのみ設定されます。ルートが実行される前にアクセスしようとすると、`NULL` になります。[ミドルウェア](/learn/middleware) でも executedRoute を使用できます! #### ルート定義に `true` を渡す ```php @@ -463,7 +462,7 @@ Flight::route('/', function(\flight\net\Route $route) { }, true);// <-- この true パラメータがそれを実現します ``` -### ルートグループ化とミドルウェア +### ルートグループとミドルウェア 関連するルートをグループ化したい場合(例: `/api/v1`)があります。`group` メソッドを使用してこれを行えます: ```php @@ -483,7 +482,7 @@ Flight::group('/api/v1', function () { ```php Flight::group('/api', function () { Flight::group('/v1', function () { - // Flight::get() は変数を取得します。ルートを設定しません!オブジェクトコンテキストを以下参照 + // Flight::get() は変数を取得します。ルートを設定しません!以下のオブジェクトコンテキストを参照 Flight::route('GET /users', function () { // GET /api/v1/users にマッチ }); @@ -498,7 +497,7 @@ Flight::group('/api', function () { }); Flight::group('/v2', function () { - // Flight::get() は変数を取得します。ルートを設定しません!オブジェクトコンテキストを以下参照 + // Flight::get() は変数を取得します。ルートを設定しません!以下のオブジェクトコンテキストを参照 Flight::route('GET /users', function () { // GET /api/v2/users にマッチ }); @@ -508,7 +507,7 @@ Flight::group('/api', function () { #### オブジェクトコンテキストでのグループ化 -`Engine` オブジェクトを使用してルートグループ化を次のように使用できます: +`Engine` オブジェクトを使用してルートグループを次のように使用できます: ```php $app = Flight::app(); @@ -530,20 +529,20 @@ $app->group('/api/v1', function (Router $router) { #### ミドルウェア付きのグループ化 -ルートグループにミドルウェアを割り当てられます: +ルートのグループにミドルウェアを割り当てられます: ```php Flight::group('/api/v1', function () { Flight::route('/users', function () { // /api/v1/users にマッチ }); -}, [ MyAuthMiddleware::class ]); // インスタンスを使用したい場合 [ new MyAuthMiddleware() ] +}, [ MyAuthMiddleware::class ]); // インスタンスを使用する場合は [ new MyAuthMiddleware() ] ``` 詳細は [グループミドルウェア](/learn/middleware#grouping-middleware) ページを参照してください。 ### リソースルーティング -`resource` メソッドを使用して、リソース用のルートセットを作成できます。これは RESTful 規約に従うリソース用のルートセットを作成します。 +`resource` メソッドを使用して、リソース用のルートセットを作成できます。これにより、RESTful 規約に従ったリソース用のルートセットが作成されます。 リソースを作成するには: @@ -600,7 +599,7 @@ class UsersController } ``` -> **注意**: 新しく追加されたルートは `php runway routes` を実行することで `runway` で表示できます。 +> **注意**: 新しく追加されたルートは、`php runway routes` を実行することで `runway` で表示できます。 #### リソースルートのカスタマイズ @@ -609,7 +608,7 @@ class UsersController ##### エイリアスベース `aliasBase` を構成できます。デフォルトでは、エイリアスは指定された URL の最後の部分です。 -例: `/users/` は `aliasBase` を `users` にします。これらのルートが作成されると、エイリアスは `users.index`、`users.create` などになります。エイリアスを変更したい場合、`aliasBase` を望む値に設定します。 +例: `/users/` は `aliasBase` を `users` にします。これらのルートが作成されると、エイリアスは `users.index`、`users.create` などになります。エイリアスを変更したい場合、`aliasBase` を希望の値に設定します。 ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); @@ -629,11 +628,11 @@ Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` -これらは基本的にホワイトリストとブラックリストオプションで、作成するルートを指定できます。 +これらは基本的にホワイトリストとブラックリストのオプションで、作成するルートを指定できます。 ##### ミドルウェア -`resource` メソッドで作成された各ルートに実行されるミドルウェアを指定できます。 +`resource` メソッドによって作成された各ルートで実行されるミドルウェアを指定できます。 ```php Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]); @@ -641,15 +640,16 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid ### ストリーミングレスポンス -`stream()` または `streamWithHeaders()` を使用してクライアントにレスポンスをストリーミングできます。 -これは大きなファイル、長時間実行プロセス、または大きなレスポンスの生成に役立ちます。 +`stream()` または `streamWithHeaders()` を使用して、クライアントにレスポンスをストリーミングできます。 +これは大規模なファイル、長時間実行プロセス、または大規模なレスポンスの生成に役立ちます。 ルートのストリーミングは通常のルートとは少し異なります。 > **注意:** ストリーミングレスポンスは、`flight.v2.output_buffering` を `false` に設定した場合にのみ利用可能です。 #### 手動ヘッダーでのストリーム -ルートで `stream()` メソッドを使用してクライアントにレスポンスをストリーミングできます。これを行う場合、クライアントに何かを出力する前にすべてのヘッダーを手動で設定する必要があります。 +ルートで `stream()` メソッドを使用してクライアントにレスポンスをストリーミングできます。 +これを行う場合、クライアントに出力する前にすべてのヘッダーを手動で設定する必要があります。 これは `header()` PHP 関数または `Flight::response()->setRealHeader()` メソッドで行います。 ```php @@ -660,8 +660,8 @@ Flight::route('/@filename', function($filename) { // 明らかにパスをサニタイズするなど。 $fileNameSafe = basename($filename); - // ルート実行後に追加のヘッダーを設定する場合 - // 何かをエコーする前に定義する必要があります。 + // ルート実行後に追加のヘッダーを設定する場合、 + // 何かがエコーされる前に定義する必要があります。 // すべて header() 関数の生の呼び出しまたは // Flight::response()->setRealHeader() の呼び出しでなければなりません header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); @@ -686,15 +686,15 @@ Flight::route('/@filename', function($filename) { })->stream(); ``` -#### ヘッダー付きストリーム +#### ヘッダー付きのストリーム -ストリーミングを開始する前にヘッダーを設定するために `streamWithHeaders()` メソッドを使用できます。 +ストリーミングを開始する前にヘッダーを設定するには、`streamWithHeaders()` メソッドを使用できます。 ```php Flight::route('/stream-users', function() { - // ここに追加のヘッダーを追加可能 - // header() または Flight::response()->setRealHeader() を使用する必要があります + // ここに任意の追加ヘッダーを追加できます + // header() または Flight::response()->setRealHeader() を使用するだけです // データの取得方法の例として... $users_stmt = Flight::db()->query("SELECT id, first_name, last_name FROM users"); @@ -716,7 +716,7 @@ Flight::route('/stream-users', function() { })->streamWithHeaders([ 'Content-Type' => 'application/json', 'Content-Disposition' => 'attachment; filename="users.json"', - // オプションのステータスコード、デフォルト 200 + // オプションのステータスコード、デフォルトは 200 'status' => 200 ]); ``` @@ -725,33 +725,33 @@ Flight::route('/stream-users', function() { - [ミドルウェア](/learn/middleware) - 認証、ロギングなどにルートでミドルウェアを使用。 - [依存性注入](/learn/dependency-injection-container) - ルートでのオブジェクト作成と管理の簡素化。 - [なぜフレームワーク?](/learn/why-frameworks) - Flight のようなフレームワークを使用する利点の理解。 -- [拡張](/learn/extending) - `notFound` メソッドを含む独自機能で Flight を拡張する方法。 +- [拡張](/learn/extending) - `notFound` メソッドを含む独自の機能で Flight を拡張する方法。 - [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - 正規表現マッチングのための PHP 関数。 ## トラブルシューティング -- ルートパラメータは名前ではなく順序でマッチされます。コールバックパラメータの順序がルート定義に一致することを確認。 -- `Flight::get()` はルートを定義しません。ルーティングには `Flight::route('GET /...')` を使用するか、グループ内のルーターオブジェクトコンテキスト(例: `$router->get(...)`)を使用。 +- ルートパラメータは名前ではなく順序でマッチされます。コールバックパラメータの順序がルート定義と一致していることを確認してください。 +- `Flight::get()` はルートを定義しません。ルーティングには `Flight::route('GET /...')` またはグループ内のルーターオブジェクトコンテキスト(例: `$router->get(...)`)を使用してください。 - executedRoute プロパティはルート実行後にのみ設定されます。実行前は NULL です。 -- ストリーミングにはレガシー Flight 出力バッファリング機能の無効化(`flight.v2.output_buffering = false`)が必要です。 -- 依存性注入の場合、特定のルート定義のみコンテナベースのインスタンス化をサポート。 +- ストリーミングには、Flight の出力バッファリング機能が無効(`flight.v2.output_buffering = false`)である必要があります。 +- 依存性注入の場合、コンテナベースのインスタンス化をサポートするのは特定のルート定義のみです。 ### 404 Not Found または予期しないルート動作 -404 Not Found エラーが表示される場合(しかし、命に誓ってそこにあるしタイポではないと確信している場合)、これはルートエンドポイントで値を返す代わりに単にエコーしなかった問題かもしれません。この理由は意図的ですが、一部の開発者を驚かせる可能性があります。 +404 Not Found エラー(しかし命にかけて本当にあると誓い、タイポではない)が見える場合、これはルートエンドポイントで値を返すのではなくエコーするだけに問題がある可能性があります。この理由は意図的ですが、一部の開発者を驚かせる可能性があります。 ```php Flight::route('/hello', function(){ - // これが 404 Not Found エラーを引き起こす可能性 + // これにより 404 Not Found エラーが発生する可能性があります return 'Hello World'; }); -// 恐らくこれが望ましい +// 恐らくこれが欲しい Flight::route('/hello', function(){ echo 'Hello World'; }); ``` -この理由は、ルーターに組み込まれた特別なメカニズムのためで、リターン出力を「次のルートに進む」シグナルとして扱います。 +この理由は、ルーターに組み込まれた特別なメカニズムのためで、戻り値を出力として「次のルートに進む」信号として扱います。 動作は [ルーティング](/learn/routing#passing) セクションで文書化されています。 ## 変更履歴 diff --git a/content/v3/ko/awesome-plugins/async.md b/content/v3/ko/awesome-plugins/async.md new file mode 100644 index 00000000..cd98308c --- /dev/null +++ b/content/v3/ko/awesome-plugins/async.md @@ -0,0 +1,212 @@ +# Async + +Async는 Flight 프레임워크를 위한 작은 패키지로, Swoole, AdapterMan, ReactPHP, Amp, RoadRunner, Workerman 등의 비동기 서버와 런타임에서 Flight 앱을 실행할 수 있게 합니다. 기본적으로 Swoole과 AdapterMan 어댑터를 포함합니다. + +목표: PHP-FPM(또는 내장 서버)으로 개발하고 디버그한 후, 프로덕션에서 Swoole(또는 다른 비동기 드라이버)로 최소한의 변경으로 전환합니다. + +## 요구 사항 + +- PHP 7.4 이상 +- Flight 프레임워크 3.16.1 이상 +- [Swoole 확장](https://www.openswoole.com) + +## 설치 + +Composer를 통해 설치하세요: + +```bash +composer require flightphp/async +``` + +Swoole로 실행할 계획이라면 확장을 설치하세요: + +```bash +# pecl 사용 +pecl install swoole +# 또는 openswoole +pecl install openswoole + +# 또는 패키지 관리자 사용 (Debian/Ubuntu 예시) +sudo apt-get install php-swoole +``` + +## 간단한 Swoole 예제 + +아래는 동일한 코드베이스를 사용하여 PHP-FPM(또는 내장 서버)와 Swoole을 모두 지원하는 최소 설정입니다. + +프로젝트에서 필요한 파일: + +- index.php +- swoole_server.php +- SwooleServerDriver.php + +### index.php + +이 파일은 개발 시 앱을 PHP 모드로 강제 실행하는 간단한 스위치입니다. + +```php +// index.php +route('/', function() use ($app) { + $app->json(['hello' => 'world']); +}); + +if (!defined('NOT_SWOOLE')) { + // Swoole 모드에서 실행될 때 SwooleServerDriver 클래스를 요구합니다. + require_once __DIR__ . '/SwooleServerDriver.php'; + + Swoole\Runtime::enableCoroutine(); + $Swoole_Server = new SwooleServerDriver('127.0.0.1', 9501, $app); + $Swoole_Server->start(); +} else { + $app->start(); +} +``` + +### SwooleServerDriver.php + +AsyncBridge와 Swoole 어댑터를 사용하여 Swoole 요청을 Flight로 연결하는 간결한 드라이버입니다. + +```php +// SwooleServerDriver.php +Swoole = new SwooleServer($host, $port); + $this->app = $app; + + $this->setDefault(); + $this->bindWorkerEvents(); + $this->bindHttpEvent(); + } + + protected function setDefault() { + $this->Swoole->set([ + 'daemonize' => false, + 'dispatch_mode' => 1, + 'max_request' => 8000, + 'open_tcp_nodelay' => true, + 'reload_async' => true, + 'max_wait_time' => 60, + 'enable_reuse_port' => true, + 'enable_coroutine' => true, + 'http_compression' => false, + 'enable_static_handler' => true, + 'document_root' => __DIR__, + 'static_handler_locations' => ['/css', '/js', '/images', '/.well-known'], + 'buffer_output_size' => 4 * 1024 * 1024, + 'worker_num' => 4, + ]); + + $app = $this->app; + $app->map('stop', function (?int $code = null) use ($app) { + if ($code !== null) { + $app->response()->status($code); + } + }); + } + + protected function bindHttpEvent() { + $app = $this->app; + $AsyncBridge = new AsyncBridge($app); + + $this->Swoole->on('Start', function(SwooleServer $server) { + echo "Swoole http server is started at http://127.0.0.1:9501\n"; + }); + + $this->Swoole->on('Request', function (SwooleRequest $request, SwooleResponse $response) use ($AsyncBridge) { + $SwooleAsyncRequest = new SwooleAsyncRequest($request); + $SwooleAsyncResponse = new SwooleAsyncResponse($response); + + $AsyncBridge->processRequest($SwooleAsyncRequest, $SwooleAsyncResponse); + + $response->end(); + gc_collect_cycles(); + }); + } + + protected function bindWorkerEvents() { + $createPools = function() { + // 여기서 워커별 연결 풀을 생성합니다. + }; + $closePools = function() { + // 여기서 풀을 닫거나 정리합니다. + }; + $this->Swoole->on('WorkerStart', $createPools); + $this->Swoole->on('WorkerStop', $closePools); + $this->Swoole->on('WorkerError', $closePools); + } + + public function start() { + $this->Swoole->start(); + } +} +``` + +## 서버 실행 + +- 개발 (PHP 내장 서버 / PHP-FPM): + - php -S localhost:8000 (index가 public/에 있는 경우 -t public/ 추가) +- 프로덕션 (Swoole): + - php swoole_server.php + +팁: 프로덕션에서는 TLS, 정적 파일, 로드 밸런싱을 처리하기 위해 Swoole 앞에 리버스 프록시(Nginx)를 사용하세요. + +## 구성 노트 + +Swoole 드라이버는 여러 구성 옵션을 노출합니다: +- worker_num: 워커 프로세스 수 +- max_request: 재시작 전 워커당 요청 수 +- enable_coroutine: 동시성을 위한 코루틴 사용 +- buffer_output_size: 출력 버퍼 크기 + +호스트 리소스와 트래픽 패턴에 맞게 조정하세요. + +## 오류 처리 + +AsyncBridge는 Flight 오류를 적절한 HTTP 응답으로 변환합니다. 라우트 수준 오류 처리도 추가할 수 있습니다: + +```php +$app->route('/*', function() use ($app) { + try { + // 라우트 로직 + } catch (Exception $e) { + $app->response()->status(500); + $app->json(['error' => $e->getMessage()]); + } +}); +``` + +## AdapterMan 및 기타 런타임 + +[AdapterMan](https://github.com/joanhey/adapterman)은 대안 런타임 어댑터로 지원됩니다. 이 패키지는 적응 가능하게 설계되었습니다 — 다른 어댑터를 추가하거나 사용하는 것은 일반적으로 동일한 패턴을 따릅니다: AsyncBridge와 런타임별 어댑터를 통해 서버 요청/응답을 Flight의 요청/응답으로 변환합니다. \ No newline at end of file diff --git a/content/v3/ko/awesome-plugins/awesome_plugins.md b/content/v3/ko/awesome-plugins/awesome_plugins.md index 53e3c8cb..0eddf635 100644 --- a/content/v3/ko/awesome-plugins/awesome_plugins.md +++ b/content/v3/ko/awesome-plugins/awesome_plugins.md @@ -1,24 +1,30 @@ # 멋진 플러그인 -Flight는 놀라울 정도로 확장 가능합니다. Flight 애플리케이션에 기능을 추가하는 데 사용할 수 있는 여러 플러그인이 있습니다. 일부는 Flight 팀에서 공식적으로 지원하며, 다른 일부는 시작하는 데 도움이 되는 마이크로/라이트 라이브러리입니다. +Flight는 놀라울 정도로 확장 가능합니다. Flight 애플리케이션에 기능을 추가하는 데 사용할 수 있는 여러 플러그인이 있습니다. 일부는 Flight 팀에서 공식적으로 지원하며, 다른 일부는 시작하는 데 도움을 주기 위한 마이크로/라이트 라이브러리입니다. ## API 문서화 -API 문서화는 모든 API에 필수적입니다. 개발자들이 API와 상호 작용하는 방법을 이해하고 반환되는 것을 기대할 수 있도록 돕습니다. Flight 프로젝트에 대한 API 문서화를 생성하는 데 도움이 되는 몇 가지 도구가 있습니다. +API 문서화는 모든 API에 필수적입니다. 개발자들이 API와 상호 작용하는 방법을 이해하고 반환되는 것을 예상할 수 있도록 도와줍니다. Flight 프로젝트를 위한 API 문서화를 생성하는 데 도움을 주는 몇 가지 도구가 있습니다. - [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber가 작성한 블로그 포스트로, OpenAPI 사양을 FlightPHP와 함께 사용하여 API 우선 접근 방식을 통해 API를 구축하는 방법에 대해 설명합니다. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI는 Flight 프로젝트에 대한 API 문서화를 생성하는 데 도움이 되는 훌륭한 도구입니다. 사용하기 매우 쉽고 필요에 맞게 사용자 지정할 수 있습니다. 이는 Swagger 문서화를 생성하는 데 도움이 되는 PHP 라이브러리입니다. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI는 Flight 프로젝트를 위한 API 문서화를 생성하는 데 도움이 되는 훌륭한 도구입니다. 사용하기 매우 쉽고 필요에 맞게 사용자 지정할 수 있습니다. 이는 Swagger 문서화를 생성하는 데 도움을 주는 PHP 라이브러리입니다. ## 애플리케이션 성능 모니터링 (APM) -애플리케이션 성능 모니터링 (APM)은 모든 애플리케이션에 필수적입니다. 애플리케이션이 어떻게 작동하는지 이해하고 병목 현상이 어디에 있는지 파악하는 데 도움이 됩니다. Flight와 함께 사용할 수 있는 여러 APM 도구가 있습니다. -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM은 Flight 애플리케이션을 모니터링하는 데 사용할 수 있는 간단한 APM 라이브러리입니다. 애플리케이션의 성능을 모니터링하고 병목 현상을 식별하는 데 도움이 됩니다. +애플리케이션 성능 모니터링 (APM)은 모든 애플리케이션에 필수적입니다. 애플리케이션이 어떻게 작동하는지 이해하고 병목 현상이 어디에 있는지 파악하는 데 도움을 줍니다. Flight와 함께 사용할 수 있는 여러 APM 도구가 있습니다. +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM은 Flight 애플리케이션을 모니터링하는 데 사용할 수 있는 간단한 APM 라이브러리입니다. 애플리케이션의 성능을 모니터링하고 병목 현상을 식별하는 데 도움을 줄 수 있습니다. + +## Async + +Flight는 이미 빠른 프레임워크이지만, 터보 엔진을 장착하면 모든 것이 더 재미있고 (도전적) 됩니다! + +- [flightphp/async](/awesome-plugins/async) - 공식 Flight Async 라이브러리입니다. 이 라이브러리는 애플리케이션에 비동기 처리를 추가하는 간단한 방법입니다. Swoole/Openswoole을 내부적으로 사용하여 작업을 비동기적으로 실행하는 간단하고 효과적인 방법을 제공합니다. ## 권한 부여/권한 권한 부여와 권한은 누가 무엇에 접근할 수 있는지에 대한 제어가 필요한 모든 애플리케이션에 필수적입니다. -- official [flightphp/permissions](/awesome-plugins/permissions) - 공식 Flight 권한 라이브러리입니다. 이 라이브러리는 애플리케이션에 사용자 및 애플리케이션 수준의 권한을 추가하는 간단한 방법입니다. +- official [flightphp/permissions](/awesome-plugins/permissions) - 공식 Flight Permissions 라이브러리입니다. 이 라이브러리는 애플리케이션에 사용자 및 애플리케이션 수준의 권한을 추가하는 간단한 방법입니다. ## 캐싱 @@ -30,7 +36,7 @@ API 문서화는 모든 API에 필수적입니다. 개발자들이 API와 상호 CLI 애플리케이션은 애플리케이션과 상호 작용하는 훌륭한 방법입니다. 컨트롤러 생성, 모든 경로 표시 등에 사용할 수 있습니다. -- official [flightphp/runway](/awesome-plugins/runway) - Runway는 Flight 애플리케이션을 관리하는 데 도움이 되는 CLI 애플리케이션입니다. +- official [flightphp/runway](/awesome-plugins/runway) - Runway는 Flight 애플리케이션을 관리하는 데 도움을 주는 CLI 애플리케이션입니다. ## 쿠키 @@ -40,44 +46,44 @@ CLI 애플리케이션은 애플리케이션과 상호 작용하는 훌륭한 ## 디버깅 -디버깅은 로컬 환경에서 개발할 때 필수적입니다. 디버깅 경험을 향상시킬 수 있는 몇 가지 플러그인이 있습니다. +로컬 환경에서 개발할 때 디버깅은 필수적입니다. 디버깅 경험을 향상시킬 수 있는 몇 가지 플러그인이 있습니다. -- [tracy/tracy](/awesome-plugins/tracy) - Flight와 함께 사용할 수 있는 완전한 기능을 갖춘 오류 핸들러입니다. 애플리케이션을 디버깅하는 데 도움이 되는 여러 패널을 가지고 있습니다. 확장하기도 매우 쉽고 자체 패널을 추가할 수도 있습니다. -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) 오류 핸들러와 함께 사용되며, Flight 프로젝트에 특화된 디버깅을 돕기 위해 몇 가지 추가 패널을 제공하는 플러그인입니다. +- [tracy/tracy](/awesome-plugins/tracy) - Flight와 함께 사용할 수 있는 완전한 기능을 갖춘 오류 처리기입니다. 애플리케이션을 디버깅하는 데 도움을 주는 여러 패널을 가지고 있습니다. 확장하기도 매우 쉽고 자체 패널을 추가할 수도 있습니다. +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) 오류 처리기와 함께 사용되며, Flight 프로젝트를 위한 디버깅을 도와주는 몇 가지 추가 패널을 추가하는 플러그인입니다. ## 데이터베이스 -데이터베이스는 대부분의 애플리케이션의 핵심입니다. 데이터를 저장하고 검색하는 방법입니다. 일부 데이터베이스 라이브러리는 쿼리를 작성하는 간단한 래퍼일 뿐이며, 일부는 완전한 ORMs입니다. +데이터베이스는 대부분의 애플리케이션의 핵심입니다. 데이터를 저장하고 검색하는 방법입니다. 일부 데이터베이스 라이브러리는 쿼리를 작성하는 단순한 래퍼이고, 일부는 완전한 ORM입니다. -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 코어의 일부인 공식 Flight PDO 래퍼입니다. 쿼리를 작성하고 실행하는 과정을 단순화하는 데 도움이 되는 간단한 래퍼입니다. ORM이 아닙니다. -- official [flightphp/active-record](/awesome-plugins/active-record) - 공식 Flight ActiveRecord ORM/매퍼입니다. 데이터베이스에서 데이터를 쉽게 검색하고 저장하는 데 훌륭한 작은 라이브러리입니다. +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 코어의 일부인 공식 Flight PDO Wrapper입니다. 쿼리를 작성하고 실행하는 과정을 단순화하는 데 도움을 주는 간단한 래퍼입니다. ORM이 아닙니다. +- official [flightphp/active-record](/awesome-plugins/active-record) - 공식 Flight ActiveRecord ORM/Mapper입니다. 데이터베이스에서 데이터를 쉽게 검색하고 저장하는 훌륭한 작은 라이브러리입니다. - [byjg/php-migration](/awesome-plugins/migrations) - 프로젝트의 모든 데이터베이스 변경 사항을 추적하는 플러그인입니다. ## 암호화 -암호화는 민감한 데이터를 저장하는 모든 애플리케이션에 필수적입니다. 데이터를 암호화하고 복호화하는 것은 그리 어렵지 않지만, 암호화 키를 적절히 저장하는 것은 [어렵습니다](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [그렇습니다](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [습니다](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). 가장 중요한 것은 암호화 키를 공용 디렉토리에 저장하지 않거나 코드 저장소에 커밋하지 않는 것입니다. +암호화는 민감한 데이터를 저장하는 모든 애플리케이션에 필수적입니다. 데이터를 암호화하고 복호화하는 것은 그리 어렵지 않지만, 암호화 키를 적절히 저장하는 것은 [어렵습니다](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [수](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [있습니다](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). 가장 중요한 것은 암호화 키를 공개 디렉토리에 저장하지 않거나 코드 저장소에 커밋하지 않는 것입니다. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - 데이터를 암호화하고 복호화하는 데 사용할 수 있는 라이브러리입니다. 데이터를 암호화하고 복호화하는 데 시작하기가 상당히 간단합니다. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - 데이터를 암호화하고 복호화하는 데 사용할 수 있는 라이브러리입니다. 데이터를 암호화하고 복호화하기 시작하는 것은 상당히 간단합니다. ## 작업 큐 -작업 큐는 작업을 비동기적으로 처리하는 데 매우 유용합니다. 이메일 보내기, 이미지 처리 또는 실시간으로 수행할 필요가 없는 모든 작업에 사용할 수 있습니다. +작업 큐는 작업을 비동기적으로 처리하는 데 매우 도움이 됩니다. 이메일 보내기, 이미지 처리 또는 실시간으로 수행할 필요가 없는 모든 작업에 사용할 수 있습니다. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue는 작업을 비동기적으로 처리하는 데 사용할 수 있는 라이브러리입니다. beanstalkd, MySQL/MariaDB, SQLite, PostgreSQL과 함께 사용할 수 있습니다. ## 세션 -세션은 API에는 별로 유용하지 않지만 웹 애플리케이션을 구축할 때 상태와 로그인 정보를 유지하는 데 필수적일 수 있습니다. +세션은 API에는 정말 유용하지 않지만, 웹 애플리케이션을 구축할 때 상태와 로그인 정보를 유지하는 데 필수적일 수 있습니다. -- official [flightphp/session](/awesome-plugins/session) - 공식 Flight 세션 라이브러리입니다. 세션 데이터를 저장하고 검색하는 데 사용할 수 있는 간단한 세션 라이브러리입니다. PHP의 내장 세션 처리를 사용합니다. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 세션 관리자 (비동기 블로킹, 플래시, 세그먼트, 세션 암호화). 세션 데이터의 선택적 암호화/복호화를 위해 PHP open_ssl을 사용합니다. +- official [flightphp/session](/awesome-plugins/session) - 공식 Flight Session 라이브러리입니다. 세션 데이터를 저장하고 검색하는 데 사용할 수 있는 간단한 세션 라이브러리입니다. PHP의 내장 세션 처리를 사용합니다. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (비동기식, 플래시, 세그먼트, 세션 암호화). 세션 데이터의 선택적 암호화/복호화를 위해 PHP open_ssl을 사용합니다. ## 템플릿 템플릿은 UI가 있는 모든 웹 애플리케이션의 핵심입니다. Flight와 함께 사용할 수 있는 여러 템플릿 엔진이 있습니다. - deprecated [flightphp/core View](/learn#views) - 코어의 일부인 매우 기본적인 템플릿 엔진입니다. 프로젝트에 몇 페이지 이상이 있다면 사용하지 않는 것이 좋습니다. -- [latte/latte](/awesome-plugins/latte) - Latte는 사용하기 매우 쉽고 Twig나 Smarty보다 PHP 구문에 더 가까운 느낌을 주는 완전한 기능을 갖춘 템플릿 엔진입니다. 확장하기도 매우 쉽고 자체 필터와 함수를 추가할 수도 있습니다. +- [latte/latte](/awesome-plugins/latte) - Latte는 사용하기 매우 쉽고 Twig나 Smarty보다 PHP 구문에 더 가까운 느낌의 완전한 기능을 갖춘 템플릿 엔진입니다. 확장하기도 매우 쉽고 자체 필터와 함수를 추가할 수도 있습니다. ## WordPress 통합 diff --git a/content/v3/ko/examples.md b/content/v3/ko/examples.md index 9f7f6dfc..ae078101 100644 --- a/content/v3/ko/examples.md +++ b/content/v3/ko/examples.md @@ -1,36 +1,37 @@ # 빠른 시작이 필요하신가요? -새로운 Flight 프로젝트를 시작하는 데는 두 가지 옵션이 있습니다: - -- [전체 스켈레톤 보일러플레이트](https://github.com/flightphp/skeleton): 컨트롤러와 뷰가 포함된 더 완전한 예제입니다. -- [단일 파일 스켈레톤 보일러플레이트](https://github.com/flightphp/skeleton-simple): 앱을 단일 간단 파일로 실행하는 데 필요한 모든 것을 포함하는 단일 파일입니다. - -커뮤니티가 기여한 예제: - -- [flightravel](https://github.com/fadrian06-templates/flighravel): PHP 도구와 GH Actions가 포함된 Laravel 디렉터리의 FlightPHP -- [fleact](https://github.com/flightphp/fleact) - ReactJS 통합이 포함된 FlightPHP 스타터 키트입니다. -- [flastro](https://github.com/flightphp/flastro) - Astro 통합이 포함된 FlightPHP 스타터 키트입니다. -- [velt](https://github.com/flightphp/velt) - Velt는 FlightPHP 백엔드와 함께 빠르고 쉬운 Svelte 스타터 템플릿입니다. - -## 영감이 필요하신가요? - -이것들은 Flight 팀에서 공식적으로 후원하는 것은 아니지만, Flight로 구축된 자신의 프로젝트 구조에 대한 아이디어를 줄 수 있습니다! - -- [Decay](https://github.com/boxybird/decay) - 좀비에 관한 HTMX 및 SleekDB가 포함된 Flight v3! ([데모](https://decay.andrewrhyand.com)) -- [Flight 예제 블로그](https://github.com/n0nag0n/flightphp-blog) - 미들웨어, 컨트롤러, 액티브 레코드 및 Latte가 포함된 Flight v3입니다. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Flight 프레임워크를 사용한 간단한 CRUD API 프로젝트로, CRUD 작업 및 데이터베이스 연결을 통해 PHP 응용 프로그램을 빠르게 설정할 수 있는 기본 구조를 제공합니다. 이 프로젝트는 RESTful API 개발을 위해 Flight를 사용하는 방법을 보여 주며, 초보자에게는 이상적인 학습 도구이자 경험이 더 많은 개발자에게 유용한 스타터 키트입니다. -- [Flight 학교 관리 시스템](https://github.com/krmu/FlightPHP_School) - Flight v3 -- [댓글이 포함된 Paste Bin](https://github.com/n0nag0n/commie2) - Flight v3 -- [기본 스켈레톤 앱](https://github.com/markhughes/flight-skeleton) -- [예제 위키](https://github.com/Skayo/FlightWiki) -- [IT-혁신자 PHP 프레임워크 응용 프로그램](https://github.com/itinnovator/myphp-app) -- [LittleEducationalCMS (스페인어)](https://github.com/casgin/LittleEducationalCMS) -- [이탈리아 황색 페이지 API](https://github.com/chiccomagnus/PGAPI) -- [일반 콘텐츠 관리 시스템 (문서가 거의 없음)](https://github.com/recepuncu/cms) -- [Flight와 medoo를 기반으로 한 작은 php 프레임워크.](https://github.com/ycrao/tinyme) -- [예제 MVC 응용 프로그램](https://github.com/paddypei/Flight-MVC) -- [프로덕션 준비 완료 Flight 보일러플레이트](https://github.com/madcoda9000/SecStore) - 몇 주에 달하는 개발 시간을 절약해 주는 프로덕션 준비 인증 프레임워크입니다. 엔터프라이즈급 보안 기능을 제공합니다: 2FA/TOTP, LDAP 통합, Azure SSO, 지능형 속도 제한, 세션 지문 인식, 무차별 대입 공격 방어, 보안 분석 대시보드, 포괄적인 감사 로깅, 세분화된 역할 기반 접근 제어. +새로운 Flight 프로젝트를 시작하는 데 두 가지 옵션이 있습니다: + +- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): 컨트롤러와 뷰가 포함된 더 완전한 예제입니다. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): 앱을 단일 간단한 파일에서 실행하는 데 필요한 모든 것을 포함한 단일 파일입니다. + +커뮤니티 기여 예제: + +- [flightravel](https://github.com/fadrian06-templates/flighravel): Laravel 디렉토리와 PHP 도구 + GH Actions를 사용한 FlightPHP +- [fleact](https://github.com/flightphp/fleact) - ReactJS 통합을 포함한 FlightPHP 스타터 키트. +- [flastro](https://github.com/flightphp/flastro) - Astro 통합을 포함한 FlightPHP 스타터 키트. +- [velt](https://github.com/flightphp/velt) - FlightPHP 백엔드를 사용한 빠르고 쉬운 Svelte 스타터 템플릿인 Velt입니다. + +## 영감을 얻고 싶으신가요? + +이것들은 Flight 팀의 공식 후원이 아니지만, Flight로 구축된 자신의 프로젝트를 구조화하는 데 아이디어를 줄 수 있습니다! + +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental은 PHP (FlightPHP), JavaScript, MySQL로 구축된 단일 페이지, 모바일 친화적인 자동차 대여 웹 애플리케이션입니다. 사용자 등록, 차량 검색 및 예약을 지원하며, 관리자는 차량, 사용자 및 예약을 관리할 수 있습니다. 앱에는 REST API, JWT 인증 및 현대적인 대여 경험을 위한 반응형 디자인이 포함되어 있습니다. +- [Decay](https://github.com/boxybird/decay) - 좀비에 관한 HTMX와 SleekDB를 사용한 Flight v3! ([Demo](https://decay.andrewrhyand.com)) +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - 미들웨어, 컨트롤러, Active Record 및 Latte를 사용한 Flight v3. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Flight 프레임워크를 사용한 간단한 CRUD API 프로젝트로, CRUD 작업과 데이터베이스 연결이 포함된 PHP 애플리케이션을 신속하게 설정할 수 있는 기본 구조를 제공합니다. 이 프로젝트는 RESTful API 개발을 위한 Flight 사용 방법을 보여주며, 초보자에게 이상적인 학습 도구이자 경험이 풍부한 개발자에게 유용한 스타터 키트입니다. +- [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 +- [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 +- [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) +- [Example Wiki](https://github.com/Skayo/FlightWiki) +- [The IT-Innovator PHP Framework Application](https://github.com/itinnovator/myphp-app) +- [LittleEducationalCMS (Spanish)](https://github.com/casgin/LittleEducationalCMS) +- [Italian Yellow Pages API](https://github.com/chiccomagnus/PGAPI) +- [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) +- [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) +- [Example MVC Application](https://github.com/paddypei/Flight-MVC) +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 개발 주를 절약해주는 프로덕션 준비 인증 프레임워크. 기업급 보안 기능: 2FA/TOTP, LDAP 통합, Azure SSO, 지능형 속도 제한, 세션 지문 인식, 무차별 대입 공격 보호, 보안 분석 대시보드, 포괄적인 감사 로깅 및 세밀한 역할 기반 액세스 제어. ## 자신의 예제를 공유하고 싶으신가요? -공유하고 싶은 프로젝트가 있다면, 이 목록에 추가할 수 있도록 끌어오기 요청을 제출해 주세요! \ No newline at end of file +공유하고 싶은 프로젝트가 있다면, 이 목록에 추가하기 위해 풀 리퀘스트를 제출해주세요! \ No newline at end of file diff --git a/content/v3/ko/learn/requests.md b/content/v3/ko/learn/requests.md index 0f6eda19..86701b57 100644 --- a/content/v3/ko/learn/requests.md +++ b/content/v3/ko/learn/requests.md @@ -1,6 +1,6 @@ -# Requests +# 요청 -## Overview +## 개요 Flight는 HTTP 요청을 단일 객체로 캡슐화하며, 이를 다음과 같이 접근할 수 있습니다: @@ -8,59 +8,59 @@ Flight는 HTTP 요청을 단일 객체로 캡슐화하며, 이를 다음과 같 $request = Flight::request(); ``` -## Understanding +## 이해 -HTTP 요청은 HTTP 라이프사이클에 대한 이해의 핵심 요소 중 하나입니다. 사용자가 웹 브라우저나 HTTP 클라이언트에서 작업을 수행하면, 헤더, 본문, URL 등을 프로젝트로 보냅니다. 이러한 헤더(브라우저 언어, 처리 가능한 압축 유형, 사용자 에이전트 등)를 캡처하고, Flight 애플리케이션으로 전송된 본문과 URL을 캡처할 수 있습니다. 이러한 요청은 앱이 다음에 무엇을 할지 이해하는 데 필수적입니다. +HTTP 요청은 HTTP 수명 주기를 이해하는 데 핵심적인 측면 중 하나입니다. 사용자가 웹 브라우저나 HTTP 클라이언트에서 작업을 수행하면, 헤더, 본문, URL 등을 프로젝트로 보냅니다. 이러한 헤더(브라우저 언어, 처리할 수 있는 압축 유형, 사용자 에이전트 등)를 캡처하고, Flight 애플리케이션으로 전송된 본문과 URL을 캡처할 수 있습니다. 이러한 요청은 앱이 다음에 무엇을 할지 이해하는 데 필수적입니다. -## Basic Usage +## 기본 사용법 PHP에는 `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES`, `$_COOKIE`와 같은 여러 슈퍼 글로벌이 있습니다. Flight는 이를 편리한 [Collections](/learn/collections)로 추상화합니다. `query`, `data`, `cookies`, `files` 속성을 배열 또는 객체로 접근할 수 있습니다. -> **Note:** 프로젝트에서 이러한 슈퍼 글로벌을 사용하는 것은 **강력히** 권장되지 않으며, `request()` 객체를 통해 참조해야 합니다. +> **참고:** 프로젝트에서 이러한 슈퍼 글로벌을 사용하는 것은 **강력히** 권장되지 않으며, `request()` 객체를 통해 참조해야 합니다. -> **Note:** `$_ENV`에 대한 추상화는 제공되지 않습니다. +> **참고:** `$_ENV`에 대한 추상화는 제공되지 않습니다. ### `$_GET` -`$_GET` 배열은 `query` 속성을 통해 접근할 수 있습니다: +`query` 속성을 통해 `$_GET` 배열에 접근할 수 있습니다: ```php // GET /search?keyword=something Flight::route('/search', function(){ $keyword = Flight::request()->query['keyword']; - // or + // 또는 $keyword = Flight::request()->query->keyword; echo "You are searching for: $keyword"; - // query a database or something else with the $keyword + // $keyword로 데이터베이스 쿼리 또는 다른 작업 수행 }); ``` ### `$_POST` -`$_POST` 배열은 `data` 속성을 통해 접근할 수 있습니다: +`data` 속성을 통해 `$_POST` 배열에 접근할 수 있습니다: ```php Flight::route('POST /submit', function(){ $name = Flight::request()->data['name']; $email = Flight::request()->data['email']; - // or + // 또는 $name = Flight::request()->data->name; $email = Flight::request()->data->email; echo "You submitted: $name, $email"; - // save to a database or something else with the $name and $email + // $name과 $email로 데이터베이스 저장 또는 다른 작업 수행 }); ``` ### `$_COOKIE` -`$_COOKIE` 배열은 `cookies` 속성을 통해 접근할 수 있습니다: +`cookies` 속성을 통해 `$_COOKIE` 배열에 접근할 수 있습니다: ```php Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; - // or + // 또는 $savedLogin = Flight::request()->cookies->myLoginCookie; - // check if it's really saved or not and if it is auto log them in + // 실제로 저장되었는지 확인하고, 저장되었다면 자동 로그인 if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -68,31 +68,30 @@ Flight::route('GET /login', function(){ }); ``` -새 쿠키 값 설정에 대한 도움말은 [overclokk/cookie](/awesome-plugins/php-cookie)를 참조하세요. +새 쿠키 값 설정에 대한 도움은 [overclokk/cookie](/awesome-plugins/php-cookie)를 참조하세요. ### `$_SERVER` -`$_SERVER` 배열에 접근하기 위해 `getVar()` 메서드를 사용할 수 있는 단축키가 있습니다: +`getVar()` 메서드를 통해 `$_SERVER` 배열에 접근하는 단축 방법이 있습니다: ```php - $host = Flight::request()->getVar('HTTP_HOST'); ``` ### `$_FILES` -업로드된 파일은 `files` 속성을 통해 접근할 수 있습니다: +`files` 속성을 통해 업로드된 파일에 접근할 수 있습니다: ```php -// raw access to $_FILES property. See below for recommended approach +// $_FILES 속성에 대한 직접 접근. 권장 접근법은 아래 참조 $uploadedFile = Flight::request()->files['myFile']; -// or +// 또는 $uploadedFile = Flight::request()->files->myFile; ``` -더 자세한 정보는 [Uploaded File Handler](/learn/uploaded-file)를 참조하세요. +더 많은 정보는 [Uploaded File Handler](/learn/uploaded-file)를 참조하세요. -#### Processing File Uploads +#### 파일 업로드 처리 _v3.12.0_ @@ -100,7 +99,7 @@ _v3.12.0_ ```php Flight::route('POST /upload', function(){ - // If you had an input field like + // 와 같은 입력 필드가 있는 경우 $uploadedFileData = Flight::request()->getUploadedFiles(); $uploadedFile = $uploadedFileData['myFile']; $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); @@ -111,7 +110,7 @@ Flight::route('POST /upload', function(){ ```php Flight::route('POST /upload', function(){ - // If you had an input field like + // 와 같은 입력 필드가 있는 경우 $uploadedFiles = Flight::request()->getUploadedFiles()['myFiles']; foreach ($uploadedFiles as $uploadedFile) { $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); @@ -119,56 +118,55 @@ Flight::route('POST /upload', function(){ }); ``` -> **Security Note:** 사용자 입력을 항상 검증하고 정제하세요, 특히 파일 업로드 시에는 더욱 그렇습니다. 업로드할 허용 확장자 유형을 검증해야 하며, 파일의 "매직 바이트"를 검증하여 사용자가 주장하는 파일 유형이 실제로 맞는지 확인해야 합니다. 이에 대한 [articles](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [and](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [libraries](https://github.com/RikudouSage/MimeTypeDetector)가 있습니다. +> **보안 참고:** 파일 업로드를 다룰 때는 항상 사용자 입력을 검증하고 정제하세요. 업로드할 허용 확장 유형을 검증하는 것뿐만 아니라, 파일의 "매직 바이트"를 검증하여 사용자가 주장하는 파일 유형인지 확인해야 합니다. 이에 대한 [기사](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [및](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [라이브러리](https://github.com/RikudouSage/MimeTypeDetector)가 도움이 됩니다. -### Request Body +### 요청 본문 -POST/PUT 요청을 처리할 때 예를 들어, 원시 HTTP 요청 본문을 가져오려면 다음과 같이 할 수 있습니다: +POST/PUT 요청을 다룰 때와 같은 원시 HTTP 요청 본문을 가져오려면 다음을 할 수 있습니다: ```php Flight::route('POST /users/xml', function(){ $xmlBody = Flight::request()->getBody(); - // do something with the XML that was sent. + // 전송된 XML로 작업 수행. }); ``` -### JSON Body +### JSON 본문 -콘텐츠 유형이 `application/json`인 요청을 받고 예시 데이터가 `{"id": 123}`인 경우, `data` 속성에서 사용할 수 있습니다: +콘텐츠 유형이 `application/json`이고 예시 데이터가 `{"id": 123}`인 요청을 받으면, `data` 속성에서 사용할 수 있습니다: ```php $id = Flight::request()->data->id; ``` -### Request Headers +### 요청 헤더 -요청 헤더는 `getHeader()` 또는 `getHeaders()` 메서드를 사용하여 접근할 수 있습니다: +`getHeader()` 또는 `getHeaders()` 메서드를 사용하여 요청 헤더에 접근할 수 있습니다: ```php - -// Maybe you need Authorization header +// Authorization 헤더가 필요한 경우 $host = Flight::request()->getHeader('Authorization'); -// or +// 또는 $host = Flight::request()->header('Authorization'); -// If you need to grab all headers +// 모든 헤더를 가져와야 하는 경우 $headers = Flight::request()->getHeaders(); -// or +// 또는 $headers = Flight::request()->headers(); ``` -### Request Method +### 요청 메서드 -요청 메서드는 `method` 속성 또는 `getMethod()` 메서드를 사용하여 접근할 수 있습니다: +`method` 속성 또는 `getMethod()` 메서드를 사용하여 요청 메서드에 접근할 수 있습니다: ```php -$method = Flight::request()->method; // actually populated by getMethod() +$method = Flight::request()->method; // 실제로는 getMethod()로 채워짐 $method = Flight::request()->getMethod(); ``` -**Note:** `getMethod()` 메서드는 먼저 `$_SERVER['REQUEST_METHOD']`에서 메서드를 가져오며, 존재할 경우 `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` 또는 `$_REQUEST['_method']`로 덮어쓸 수 있습니다. +**참고:** `getMethod()` 메서드는 먼저 `$_SERVER['REQUEST_METHOD']`에서 메서드를 가져온 다음, `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']`가 존재하면 이를 덮어쓰거나 `$_REQUEST['_method']`가 존재하면 이를 사용합니다. -## Request Object Properties +## 요청 객체 속성 요청 객체는 다음 속성을 제공합니다: @@ -193,30 +191,31 @@ $method = Flight::request()->getMethod(); - **host** - 요청 호스트 이름 - **servername** - `$_SERVER`의 SERVER_NAME -## Helper Methods +## 도우미 메서드 -URL의 일부를 조합하거나 특정 헤더를 처리하기 위한 몇 가지 도우미 메서드가 있습니다. +URL의 일부를 조합하거나 특정 헤더를 다루기 위한 몇 가지 도우미 메서드가 있습니다. -### Full URL +### 전체 URL -전체 요청 URL은 `getFullUrl()` 메서드를 사용하여 접근할 수 있습니다: +`getFullUrl()` 메서드를 사용하여 전체 요청 URL에 접근할 수 있습니다: ```php $url = Flight::request()->getFullUrl(); // https://example.com/some/path?foo=bar ``` -### Base URL -기본 URL은 `getBaseUrl()` 메서드를 사용하여 접근할 수 있습니다: +### 기본 URL + +`getBaseUrl()` 메서드를 사용하여 기본 URL에 접근할 수 있습니다: ```php // http://example.com/path/to/something/cool?query=yes+thanks $url = Flight::request()->getBaseUrl(); // https://example.com -// Notice, no trailing slash. +// 주의: 후행 슬래시 없음. ``` -## Query Parsing +## 쿼리 파싱 `parseQuery()` 메서드에 URL을 전달하여 쿼리 문자열을 연관 배열로 파싱할 수 있습니다: @@ -225,40 +224,39 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` -## Negotiate Content Accept Types +## 콘텐츠 Accept 유형 협상 _v3.17.2_ 클라이언트가 보낸 `Accept` 헤더를 기반으로 응답할 최적의 콘텐츠 유형을 결정하기 위해 `negotiateContentType()` 메서드를 사용할 수 있습니다. ```php - -// Example Accept header: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 -// The below defines what you support. +// 예시 Accept 헤더: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// 아래는 지원하는 유형을 정의합니다. $availableTypes = ['application/json', 'application/xml']; $typeToServe = Flight::request()->negotiateContentType($availableTypes); if ($typeToServe === 'application/json') { - // Serve JSON response + // JSON 응답 제공 } elseif ($typeToServe === 'application/xml') { - // Serve XML response + // XML 응답 제공 } else { - // Default to something else or throw an error + // 다른 기본값 사용 또는 오류 발생 } ``` -> **Note:** `Accept` 헤더에 사용 가능한 유형 중 하나가 발견되지 않으면 메서드는 `null`을 반환합니다. `Accept` 헤더가 정의되지 않은 경우, 메서드는 `$availableTypes` 배열의 첫 번째 유형을 반환합니다. +> **참고:** `Accept` 헤더에 사용 가능한 유형 중 하나가 없으면 메서드는 `null`을 반환합니다. `Accept` 헤더가 정의되지 않은 경우, 메서드는 `$availableTypes` 배열의 첫 번째 유형을 반환합니다. -## See Also +## 관련 자료 - [Routing](/learn/routing) - 라우트를 컨트롤러에 매핑하고 뷰를 렌더링하는 방법. - [Responses](/learn/responses) - HTTP 응답을 사용자 지정하는 방법. -- [Why a Framework?](/learn/why-frameworks) - 요청이 큰 그림에 어떻게 맞는지. +- [Why a Framework?](/learn/why-frameworks) - 요청이 전체 그림에 어떻게 맞는지. - [Collections](/learn/collections) - 데이터 컬렉션 작업. - [Uploaded File Handler](/learn/uploaded-file) - 파일 업로드 처리. -## Troubleshooting +## 문제 해결 - `request()->ip`와 `request()->proxy_ip`는 웹 서버가 프록시, 로드 밸런서 등 뒤에 있는 경우 다를 수 있습니다. -## Changelog +## 변경 로그 - v3.17.2 - negotiateContentType() 추가 - v3.12.0 - 요청 객체를 통해 파일 업로드 처리 기능 추가. - v1.0 - 초기 릴리스. \ No newline at end of file diff --git a/content/v3/ko/learn/routing.md b/content/v3/ko/learn/routing.md index 1d5ef114..d217b3de 100644 --- a/content/v3/ko/learn/routing.md +++ b/content/v3/ko/learn/routing.md @@ -1,17 +1,17 @@ # 라우팅 ## 개요 -Flight PHP의 라우팅은 URL 패턴을 콜백 함수나 클래스 메서드에 매핑하여 빠르고 간단한 요청 처리를 가능하게 합니다. 이는 최소한의 오버헤드, 초보자 친화적인 사용, 그리고 외부 종속성 없이 확장성을 위해 설계되었습니다. +Flight PHP의 라우팅은 URL 패턴을 콜백 함수나 클래스 메서드에 매핑하여 빠르고 간단한 요청 처리를 가능하게 합니다. 이는 최소한의 오버헤드, 초보자 친화적인 사용, 그리고 외부 의존성 없이 확장성을 위해 설계되었습니다. ## 이해 -라우팅은 Flight에서 HTTP 요청을 애플리케이션 로직에 연결하는 핵심 메커니즘입니다. 라우트를 정의함으로써 다양한 URL이 함수, 클래스 메서드, 또는 컨트롤러 액션을 통해 특정 코드를 트리거하는 방식을 지정할 수 있습니다. Flight의 라우팅 시스템은 유연하며, 기본 패턴, 명명된 매개변수, 정규 표현식, 그리고 의존성 주입 및 리소스 라우팅과 같은 고급 기능을 지원합니다. 이 접근 방식은 코드를 체계적으로 유지하고 유지보수를 쉽게 하며, 초보자에게는 빠르고 간단하며 고급 사용자에게는 확장 가능합니다. +라우팅은 Flight에서 HTTP 요청을 애플리케이션 로직에 연결하는 핵심 메커니즘입니다. 라우트를 정의함으로써 서로 다른 URL이 함수, 클래스 메서드 또는 컨트롤러 액션을 통해 특정 코드를 트리거하는 방식을 지정할 수 있습니다. Flight의 라우팅 시스템은 유연하며, 기본 패턴, 명명된 매개변수, 정규 표현식, 그리고 의존성 주입 및 리소스 라우팅과 같은 고급 기능을 지원합니다. 이 접근 방식은 코드를 체계적으로 유지하고 유지보수를 용이하게 하며, 초보자에게는 빠르고 간단하며 고급 사용자에게는 확장 가능합니다. -> **참고:** 라우팅에 대해 더 이해하고 싶으신가요? ["프레임워크를 사용하는 이유?](/learn/why-frameworks)" 페이지를 확인하여 더 자세한 설명을 보세요. +> **참고:** 라우팅에 대해 더 알고 싶으신가요? 더 자세한 설명을 위해 ["왜 프레임워크인가?](/learn/why-frameworks)" 페이지를 확인하세요. ## 기본 사용법 ### 간단한 라우트 정의 -Flight의 기본 라우팅은 URL 패턴을 콜백 함수나 클래스와 메서드의 배열로 매칭합니다. +Flight의 기본 라우팅은 URL 패턴을 콜백 함수나 클래스와 메서드의 배열로 매칭하여 수행됩니다. ```php Flight::route('/', function(){ @@ -22,7 +22,7 @@ Flight::route('/', function(){ > 라우트는 정의된 순서대로 매칭됩니다. 요청과 일치하는 첫 번째 라우트가 호출됩니다. ### 콜백으로 함수 사용 -콜백은 호출 가능한 모든 객체가 될 수 있습니다. 따라서 일반 함수를 사용할 수 있습니다: +콜백은 호출 가능한 모든 객체일 수 있습니다. 따라서 일반 함수를 사용할 수 있습니다: ```php function hello() { @@ -44,7 +44,7 @@ class GreetingController { Flight::route('/', [ 'GreetingController','hello' ]); // 또는 -Flight::route('/', [ GreetingController::class, 'hello' ]); // 선호되는 방법 +Flight::route('/', [ GreetingController::class, 'hello' ]); // 선호하는 방법 // 또는 Flight::route('/', [ 'GreetingController::hello' ]); // 또는 @@ -77,7 +77,7 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **참고:** 기본적으로 프레임워크 내에서 컨트롤러가 호출될 때 `flight\Engine` 클래스가 항상 주입됩니다. [의존성 주입 컨테이너](/learn/dependency-injection-container)를 통해 지정하지 않는 한 예외입니다. +> **참고:** 프레임워크 내에서 컨트롤러가 호출될 때 기본적으로 `flight\Engine` 클래스가 항상 주입됩니다. [의존성 주입 컨테이너](/learn/dependency-injection-container)를 통해 지정하지 않는 한 예외입니다. ### 메서드별 라우팅 @@ -92,7 +92,8 @@ Flight::route('POST /', function () { echo 'I received a POST request.'; }); -// Flight::get()을 라우트에 사용할 수 없습니다. 이는 변수를 가져오는 메서드이지 라우트를 생성하는 것이 아닙니다. +// Flight::get()은 라우트를 생성하는 메서드가 아니므로 라우트에 사용할 수 없습니다. +// 변수 가져오기 메서드입니다. Flight::post('/', function() { /* code */ }); Flight::patch('/', function() { /* code */ }); Flight::put('/', function() { /* code */ }); @@ -113,8 +114,8 @@ Flight는 `HEAD` 및 `OPTIONS` HTTP 요청에 대한 내장 처리를 제공합 #### HEAD 요청 -- **HEAD 요청**은 `GET` 요청과 동일하게 처리되지만, Flight는 클라이언트로 전송하기 전에 응답 본문을 자동으로 제거합니다. -- 이는 `GET`에 대한 라우트를 정의하면 동일한 URL에 대한 HEAD 요청이 헤더만 반환(콘텐츠 없음)하도록 하여 HTTP 표준을 준수합니다. +- **HEAD 요청**은 `GET` 요청과 동일하게 처리되지만, Flight가 클라이언트로 보내기 전에 응답 본문을 자동으로 제거합니다. +- 이는 `GET`에 대한 라우트를 정의하면 동일한 URL에 대한 HEAD 요청이 헤더만 반환(콘텐츠 없음)하도록 하여 HTTP 표준에 부합합니다. ```php Flight::route('GET /info', function() { @@ -126,8 +127,8 @@ Flight::route('GET /info', function() { #### OPTIONS 요청 `OPTIONS` 요청은 정의된 모든 라우트에 대해 Flight가 자동으로 처리합니다. -- OPTIONS 요청이 수신되면 Flight는 `204 No Content` 상태와 해당 라우트에 지원되는 모든 HTTP 메서드를 나열하는 `Allow` 헤더로 응답합니다. -- 커스텀 동작이나 응답 수정을 원하지 않는 한 별도의 OPTIONS 라우트를 정의할 필요가 없습니다. +- OPTIONS 요청이 수신되면 Flight는 `204 No Content` 상태와 해당 라우트에 대한 지원 HTTP 메서드 목록이 포함된 `Allow` 헤더로 응답합니다. +- OPTIONS에 대한 별도의 라우트를 정의할 필요가 없습니다. ```php // 다음과 같이 정의된 라우트의 경우: @@ -141,12 +142,12 @@ Flight::route('GET|POST /users', function() { /* ... */ }); ### 라우터 객체 사용 -추가로 라우터 객체를 가져와서 도우미 메서드를 사용할 수 있습니다: +또한 라우터 객체를 가져와서 사용할 수 있으며, 이는 몇 가지 도우미 메서드를 제공합니다: ```php $router = Flight::router(); -// Flight::route()처럼 모든 메서드를 매핑합니다. +// Flight::route()와 동일하게 모든 메서드를 매핑 $router->map('/', function() { echo 'hello world!'; }); @@ -162,7 +163,7 @@ $router->patch('/users/@id', function() { /* code */}); ``` ### 정규 표현식 (Regex) -라우트에 정규 표현식을 사용할 수 있습니다: +라우트에서 정규 표현식을 사용할 수 있습니다: ```php Flight::route('/user/[0-9]+', function () { @@ -170,10 +171,10 @@ Flight::route('/user/[0-9]+', function () { }); ``` -이 방법은 사용 가능하지만, 명명된 매개변수 또는 정규 표현식이 포함된 명명된 매개변수를 사용하는 것이 더 읽기 쉽고 유지보수가 용이하므로 권장됩니다. +이 방법은 사용 가능하지만, 더 읽기 쉽고 유지보수가 용이하므로 명명된 매개변수 또는 정규 표현식을 사용한 명명된 매개변수를 사용하는 것이 권장됩니다. ### 명명된 매개변수 -라우트에 명명된 매개변수를 지정하면 콜백 함수로 전달됩니다. **이는 라우트의 가독성을 위한 것이며, 아래의 중요한 주의 사항 섹션을 참조하세요.** +라우트에 명명된 매개변수를 지정하면 콜백 함수로 전달됩니다. **이는 라우트의 가독성을 위한 것이며, 아래 중요한 주의사항 섹션을 참조하세요.** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -190,11 +191,11 @@ Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { }); ``` -> **참고:** 위치 매개변수와 함께 매칭되는 regex 그룹 `()`은 지원되지 않습니다. 예: `:'\(` +> **참고:** 위치 매개변수와 함께 regex 그룹 `()` 매칭은 지원되지 않습니다. 예: `:'\(` -#### 중요한 주의 사항 +#### 중요한 주의사항 -위 예에서 `@name`이 `$name` 변수에 직접 연결된 것처럼 보이지만, 실제로는 아닙니다. 콜백 함수의 매개변수 순서가 전달되는 것을 결정합니다. 콜백 함수의 매개변수 순서를 변경하면 변수도 변경됩니다. 예시: +위 예시에서 `@name`이 변수 `$name`에 직접 연결된 것처럼 보이지만, 그렇지 않습니다. 콜백 함수의 매개변수 순서가 전달되는 것을 결정합니다. 콜백 함수의 매개변수 순서를 변경하면 변수도 변경됩니다. 다음은 예시입니다: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -202,11 +203,11 @@ Flight::route('/@name/@id', function (string $id, string $name) { }); ``` -다음 URL로 이동하면: `/bob/123`, 출력은 `hello, 123 (bob)!`이 됩니다. +다음 URL로 이동하면 `/bob/123`의 출력은 `hello, 123 (bob)!`가 됩니다. 라우트와 콜백 함수를 설정할 때 _주의하세요_! ### 선택적 매개변수 -URL 세그먼트를 괄호로 감싸서 매칭에 선택적인 명명된 매개변수를 지정할 수 있습니다. +세그먼트를 괄호로 감싸서 매칭에 선택적인 명명된 매개변수를 지정할 수 있습니다. ```php Flight::route( @@ -232,24 +233,24 @@ Flight::route('/blog/*', function () { }); ``` -모든 요청을 단일 콜백으로 라우팅하려면: +모든 요청을 단일 콜백으로 라우팅하려면 다음을 수행하세요: ```php Flight::route('*', function () { - // 무언가 수행 + // 무언가를 수행 }); ``` ### 404 Not Found 핸들러 기본적으로 URL을 찾을 수 없으면 Flight는 매우 간단하고 평범한 `HTTP 404 Not Found` 응답을 보냅니다. -더 맞춤형 404 응답을 원하면 [map](/learn/extending)으로 자신의 `notFound` 메서드를 매핑할 수 있습니다: +더 사용자 지정된 404 응답을 원한다면 [map](/learn/extending)으로 자신의 `notFound` 메서드를 매핑할 수 있습니다: ```php Flight::map('notFound', function() { $url = Flight::request()->url; - // 커스텀 템플릿으로 Flight::render()를 사용할 수도 있습니다. + // 사용자 지정 템플릿과 함께 Flight::render()를 사용할 수도 있습니다. $output = <<My Custom 404 Not Found

The page you have requested {$url} could not be found.

@@ -265,9 +266,9 @@ Flight::map('notFound', function() { ### Method Not Found 핸들러 -기본적으로 URL은 발견되지만 메서드가 허용되지 않으면 Flight는 매우 간단하고 평범한 `HTTP 405 Method Not Allowed` 응답을 보냅니다 (예: Method Not Allowed. Allowed Methods are: GET, POST). 또한 해당 URL에 허용된 메서드와 함께 `Allow` 헤더를 포함합니다. +기본적으로 URL은 발견되지만 메서드가 허용되지 않으면 Flight는 매우 간단하고 평범한 `HTTP 405 Method Not Allowed` 응답을 보냅니다 (예: Method Not Allowed. Allowed Methods are: GET, POST). 또한 해당 URL에 대한 허용된 메서드가 포함된 `Allow` 헤더를 포함합니다. -더 맞춤형 405 응답을 원하면 [map](/learn/extending)으로 자신의 `methodNotFound` 메서드를 매핑할 수 있습니다: +더 사용자 지정된 405 응답을 원한다면 [map](/learn/extending)으로 자신의 `methodNotFound` 메서드를 매핑할 수 있습니다: ```php use flight\net\Route; @@ -276,7 +277,7 @@ Flight::map('methodNotFound', function(Route $route) { $url = Flight::request()->url; $methods = implode(', ', $route->methods); - // 커스텀 템플릿으로 Flight::render()를 사용할 수도 있습니다. + // 사용자 지정 템플릿과 함께 Flight::render()를 사용할 수도 있습니다. $output = <<My Custom 405 Method Not Allowed

The method you have requested for {$url} is not allowed.

@@ -294,10 +295,10 @@ Flight::map('methodNotFound', function(Route $route) { ## 고급 사용법 -### 라우트의 의존성 주입 -컨테이너(PSR-11, PHP-DI, Dice 등)를 통한 의존성 주입을 사용하려면, 직접 객체를 생성하고 컨테이너를 사용하여 객체를 생성하거나 문자열로 클래스와 메서드를 정의하는 라우트 유형만 사용할 수 있습니다. 자세한 내용은 [의존성 주입](/learn/dependency-injection-container) 페이지를 참조하세요. +### 라우트에서의 의존성 주입 +컨테이너(PSR-11, PHP-DI, Dice 등)를 통해 의존성 주입을 사용하려면, 직접 객체를 생성하고 컨테이너를 사용하여 객체를 생성하거나 문자열을 사용하여 클래스와 메서드를 정의하는 라우트 유형만 사용 가능합니다. 더 자세한 정보는 [의존성 주입](/learn/dependency-injection-container) 페이지를 참조하세요. -간단한 예시: +간단한 예시입니다: ```php use flight\database\PdoWrapper; @@ -311,7 +312,7 @@ class Greeting } public function hello(int $id) { - // $this->pdoWrapper로 무언가 수행 + // $this->pdoWrapper로 무언가를 수행 $name = $this->pdoWrapper->fetchField("SELECT name FROM users WHERE id = ?", [ $id ]); echo "Hello, world! My name is {$name}!"; } @@ -320,7 +321,7 @@ class Greeting // index.php // 필요한 매개변수로 컨테이너 설정 -// PSR-11에 대한 자세한 내용은 의존성 주입 페이지를 참조하세요. +// PSR-11에 대한 더 많은 정보는 의존성 주입 페이지를 참조하세요. $dice = new \Dice\Dice(); // '$dice = '로 변수를 재할당하는 것을 잊지 마세요!!!!! @@ -362,21 +363,21 @@ Flight::route('/user/@name', function (string $name) { }); Flight::route('/user/*', function () { - // 이는 호출됩니다. + // 이 라우트가 호출됩니다. }); ``` -이제 [미들웨어](/learn/middleware)를 사용하여 이러한 복잡한 사용 사례를 처리하는 것을 권장합니다. +이제 이런 복잡한 사용 사례를 처리하기 위해 [미들웨어](/learn/middleware)를 사용하는 것이 권장됩니다. ### 라우트 별칭 -라우트에 별칭을 지정하면 나중에 코드에서 동적으로 호출하여 HTML 템플릿의 링크나 리다이렉트 URL 생성 등에 사용할 수 있습니다. +라우트에 별칭을 할당하면 나중에 코드에서 동적으로 해당 별칭을 호출하여 링크(HTML 템플릿의 링크나 리다이렉트 URL 생성 등)를 생성할 수 있습니다. ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); // 또는 Flight::route('/users/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view'); -// 코드 어딘가에서 나중에 +// 코드의 나중 부분에서 class UserController { public function update() { @@ -389,8 +390,8 @@ class UserController { } ``` -URL이 변경될 때 특히 유용합니다. 위 예에서 사용자가 `/admin/users/@id`로 이동했다고 가정하면. -라우트에 별칭이 있으면 코드의 모든 이전 URL을 찾고 변경할 필요가 없으며, 별칭이 이제 `/admin/users/5`를 반환합니다. +URL이 변경되는 경우에 특히 유용합니다. 위 예시에서 users가 `/admin/users/@id`로 이동했다고 가정해 보세요. +라우트에 별칭이 있으면 코드에서 모든 이전 URL을 찾고 변경할 필요가 없으며, 별칭은 이제 위 예시처럼 `/admin/users/5`를 반환합니다. 그룹 내에서도 라우트 별칭이 작동합니다: @@ -406,13 +407,13 @@ Flight::group('/users', function() { 매칭된 라우트 정보를 검사하려면 2가지 방법이 있습니다: 1. `Flight::router()` 객체의 `executedRoute` 속성을 사용할 수 있습니다. -2. 라우트 메서드의 세 번째 매개변수로 `true`를 전달하여 콜백으로 라우트 객체를 요청할 수 있습니다. 라우트 객체는 항상 콜백 함수의 마지막 매개변수로 전달됩니다. +2. 라우트 메서드의 세 번째 매개변수로 `true`를 전달하여 라우트 객체를 콜백으로 전달받을 수 있습니다. 라우트 객체는 항상 콜백 함수의 마지막 매개변수로 전달됩니다. #### `executedRoute` ```php Flight::route('/', function() { $route = Flight::router()->executedRoute; - // $route로 무언가 수행 + // $route로 무언가를 수행 // 매칭된 HTTP 메서드 배열 $route->methods; @@ -422,7 +423,7 @@ Flight::route('/', function() { // 매칭 정규 표현식 $route->regex; - // URL 패턴의 '*' 내용 포함 + // URL 패턴에서 사용된 '*'의 내용 포함 $route->splat; // URL 경로 표시... 정말 필요하다면 @@ -450,7 +451,7 @@ Flight::route('/', function(\flight\net\Route $route) { // 매칭 정규 표현식 $route->regex; - // URL 패턴의 '*' 내용 포함 + // URL 패턴에서 사용된 '*'의 내용 포함 $route->splat; // URL 경로 표시... 정말 필요하다면 @@ -465,8 +466,7 @@ Flight::route('/', function(\flight\net\Route $route) { ``` ### 라우트 그룹화 및 미들웨어 -관련 라우트를 함께 그룹화해야 할 때가 있습니다 (예: `/api/v1`). -`group` 메서드를 사용하여 이를 수행할 수 있습니다: +관련 라우트를 함께 그룹화해야 할 때가 있습니다(예: `/api/v1`). `group` 메서드를 사용하여 이를 수행할 수 있습니다: ```php Flight::group('/api/v1', function () { @@ -508,7 +508,7 @@ Flight::group('/api', function () { }); ``` -#### 객체 컨텍스트와 그룹화 +#### 객체 컨텍스트와 함께 그룹화 다음 방식으로 `Engine` 객체와 함께 라우트 그룹화를 사용할 수 있습니다: @@ -528,11 +528,11 @@ $app->group('/api/v1', function (Router $router) { }); ``` -> **참고:** `$router` 객체를 사용한 라우트와 그룹 정의의 선호되는 방법입니다. +> **참고:** `$router` 객체를 사용한 라우트 및 그룹 정의의 선호 방법입니다. -#### 미들웨어와 그룹화 +#### 미들웨어와 함께 그룹화 -라우트 그룹에 미들웨어를 지정할 수도 있습니다: +라우트 그룹에 미들웨어를 할당할 수도 있습니다: ```php Flight::group('/api/v1', function () { @@ -545,7 +545,7 @@ Flight::group('/api/v1', function () { [그룹 미들웨어](/learn/middleware#grouping-middleware) 페이지에서 더 자세한 내용을 확인하세요. ### 리소스 라우팅 -`resource` 메서드를 사용하여 리소스에 대한 라우트 세트를 생성할 수 있습니다. 이는 RESTful 규칙을 따르는 리소스에 대한 라우트 세트를 생성합니다. +`resource` 메서드를 사용하여 리소스에 대한 일련의 라우트를 생성할 수 있습니다. 이는 RESTful 규칙을 따르는 리소스에 대한 라우트 세트를 생성합니다. 리소스를 생성하려면 다음을 수행하세요: @@ -553,7 +553,7 @@ Flight::group('/api/v1', function () { Flight::resource('/users', UsersController::class); ``` -배경에서 다음 라우트가 생성됩니다: +배경에서 발생하는 일은 다음 라우트를 생성하는 것입니다: ```php [ @@ -602,7 +602,7 @@ class UsersController } ``` -> **참고**: 새로 추가된 라우트를 보려면 `php runway routes`를 실행하세요. +> **참고**: 새로 추가된 라우트를 보려면 `php runway routes`를 실행하여 `runway`를 사용하세요. #### 리소스 라우트 사용자 지정 @@ -611,7 +611,7 @@ class UsersController ##### 별칭 베이스 `aliasBase`를 구성할 수 있습니다. 기본적으로 별칭은 지정된 URL의 마지막 부분입니다. -예를 들어 `/users/`는 `aliasBase`가 `users`가 됩니다. 이러한 라우트가 생성되면 별칭은 `users.index`, `users.create` 등이 됩니다. 별칭을 변경하려면 `aliasBase`를 원하는 값으로 설정하세요. +예를 들어 `/users/`는 `aliasBase`가 `users`가 됩니다. 이러한 라우트가 생성될 때 별칭은 `users.index`, `users.create` 등이 됩니다. 별칭을 변경하려면 `aliasBase`를 원하는 값으로 설정하세요. ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); @@ -619,7 +619,7 @@ Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); ##### Only 및 Except -`only`와 `except` 옵션을 사용하여 생성할 라우트를 지정할 수 있습니다. +`only` 및 `except` 옵션을 사용하여 생성할 라우트를 지정할 수도 있습니다. ```php // 이 메서드만 화이트리스트하고 나머지는 블랙리스트 @@ -631,11 +631,11 @@ Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` -이는 생성할 라우트를 지정할 수 있는 화이트리스트 및 블랙리스트 옵션입니다. +이것들은 라우트를 생성할 라우트를 지정할 수 있는 화이트리스트 및 블랙리스트 옵션입니다. ##### 미들웨어 -`resource` 메서드로 생성된 각 라우트에 실행될 미들웨어를 지정할 수도 있습니다. +`resource` 메서드가 생성한 각 라우트에 실행될 미들웨어를 지정할 수도 있습니다. ```php Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]); @@ -643,28 +643,29 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid ### 스트리밍 응답 -이제 `stream()` 또는 `streamWithHeaders()`를 사용하여 클라이언트에 응답을 스트리밍할 수 있습니다. -이는 대용량 파일 전송, 장기 실행 프로세스, 또는 대용량 응답 생성에 유용합니다. +이제 `stream()` 또는 `streamWithHeaders()`를 사용하여 클라이언트로 응답을 스트리밍할 수 있습니다. +이는 대용량 파일, 장기 실행 프로세스 또는 대용량 응답 생성에 유용합니다. 라우트 스트리밍은 일반 라우트와 약간 다르게 처리됩니다. -> **참고:** 스트리밍 응답은 [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering)이 `false`로 설정된 경우에만 사용할 수 있습니다. +> **참고:** 스트리밍 응답은 [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering)이 `false`로 설정된 경우에만 사용 가능합니다. -#### 수동 헤더와 스트림 +#### 수동 헤더와 함께 스트림 -라우트의 `stream()` 메서드를 사용하여 클라이언트에 응답을 스트리밍할 수 있습니다. 이렇게 하면 클라이언트에 아무것도 출력하기 전에 모든 헤더를 수동으로 설정해야 합니다. -이는 `header()` PHP 함수나 `Flight::response()->setRealHeader()` 메서드로 수행됩니다. +라우트의 `stream()` 메서드를 사용하여 클라이언트로 응답을 스트리밍할 수 있습니다. +이렇게 하면 클라이언트로 아무것도 출력하기 전에 모든 헤더를 수동으로 설정해야 합니다. +이는 `header()` PHP 함수 또는 `Flight::response()->setRealHeader()` 메서드로 수행됩니다. ```php Flight::route('/@filename', function($filename) { $response = Flight::response(); - // 명백히 경로를 정화하는 등의 작업을 수행합니다. + // 명백히 경로를 정제하고 그 밖의 것을 수행합니다. $fileNameSafe = basename($filename); - // 라우트 실행 후 추가 헤더를 설정해야 하는 경우 + // 라우트 실행 후 여기서 추가 헤더를 설정해야 한다면 // 아무것도 에코되기 전에 정의해야 합니다. - // 모두 header() 함수의 raw 호출이거나 + // 모두 header() 함수의 원시 호출이거나 // Flight::response()->setRealHeader() 호출이어야 합니다. header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); // 또는 @@ -676,21 +677,21 @@ Flight::route('/@filename', function($filename) { Flight::halt(404, 'File not found'); } - // 원하면 콘텐츠 길이를 수동으로 설정 + // 원한다면 콘텐츠 길이를 수동으로 설정 header('Content-Length: '.filesize($filePath)); // 또는 $response->setRealHeader('Content-Length: '.filesize($filePath)); - // 파일을 읽으면서 클라이언트에 스트리밍 + // 파일을 읽으면서 클라이언트로 스트리밍 readfile($filePath); // 여기가 마법의 줄입니다. })->stream(); ``` -#### 헤더와 스트림 +#### 헤더와 함께 스트림 -스트리밍을 시작하기 전에 헤더를 설정하려면 `streamWithHeaders()` 메서드를 사용할 수도 있습니다. +스트리밍을 시작하기 전에 헤더를 설정하기 위해 `streamWithHeaders()` 메서드를 사용할 수도 있습니다. ```php Flight::route('/stream-users', function() { @@ -698,7 +699,7 @@ Flight::route('/stream-users', function() { // 여기에 원하는 추가 헤더를 추가할 수 있습니다. // header() 또는 Flight::response()->setRealHeader()를 사용해야 합니다. - // 데이터 가져오는 방식 예시... + // 데이터를 어떻게 가져오든, 예시로... $users_stmt = Flight::db()->query("SELECT id, first_name, last_name FROM users"); echo '{'; @@ -709,7 +710,7 @@ Flight::route('/stream-users', function() { echo ','; } - // 클라이언트에 데이터를 보내기 위해 필요 + // 데이터를 클라이언트로 보내기 위해 필요 ob_flush(); } echo '}'; @@ -723,15 +724,15 @@ Flight::route('/stream-users', function() { ]); ``` -## 관련 자료 +## 관련 항목 - [미들웨어](/learn/middleware) - 인증, 로깅 등에 라우트와 함께 미들웨어 사용. - [의존성 주입](/learn/dependency-injection-container) - 라우트에서 객체 생성 및 관리를 단순화. -- [프레임워크를 사용하는 이유?](/learn/why-frameworks) - Flight와 같은 프레임워크의 이점 이해. -- [확장](/learn/extending) - `notFound` 메서드를 포함한 Flight의 사용자 지정 기능 확장 방법. +- [왜 프레임워크인가?](/learn/why-frameworks) - Flight와 같은 프레임워크 사용의 이점 이해. +- [확장](/learn/extending) - `notFound` 메서드를 포함한 자체 기능으로 Flight 확장 방법. - [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - 정규 표현식 매칭을 위한 PHP 함수. ## 문제 해결 -- 라우트 매개변수는 이름이 아닌 순서에 따라 매칭됩니다. 콜백 매개변수 순서가 라우트 정의와 일치하는지 확인하세요. +- 라우트 매개변수는 이름이 아닌 순서대로 매칭됩니다. 콜백 매개변수 순서가 라우트 정의와 일치하는지 확인하세요. - `Flight::get()`은 라우트를 정의하지 않습니다; 라우팅에는 `Flight::route('GET /...')` 또는 그룹의 Router 객체 컨텍스트(예: `$router->get(...)`)를 사용하세요. - executedRoute 속성은 라우트 실행 후에만 설정됩니다; 실행 전에 NULL입니다. - 스트리밍은 레거시 Flight 출력 버퍼링 기능이 비활성화되어야 합니다(`flight.v2.output_buffering = false`). @@ -739,7 +740,7 @@ Flight::route('/stream-users', function() { ### 404 Not Found 또는 예상치 못한 라우트 동작 -404 Not Found 오류를 보고 있지만 (생명이 걸려도 타이포가 아니라고 맹세함) 실제로 라우트 엔드포인트에서 값을 반환하는 대신 에코만 하는 문제일 수 있습니다. 이는 의도적이며 일부 개발자에게 은밀하게 다가올 수 있습니다. +404 Not Found 오류를 보고 계시지만(인생을 걸고 타이포가 아니라고 맹세하더라도) 이는 라우트 엔드포인트에서 값을 반환하는 대신 에코하는 문제일 수 있습니다. 이는 의도적 이유로 일부 개발자에게 숨어들 수 있습니다. ```php Flight::route('/hello', function(){ @@ -747,15 +748,15 @@ Flight::route('/hello', function(){ return 'Hello World'; }); -// 원하는 것 +// 아마 원하는 것은 Flight::route('/hello', function(){ echo 'Hello World'; }); ``` -이유는 라우터에 내장된 특수 메커니즘 때문으로, 반환 출력을 "다음 라우트로 이동" 신호로 처리합니다. +이유는 라우터에 내장된 특별 메커니즘 때문으로, 반환 출력을 "다음 라우트로 이동" 신호로 처리합니다. 동작은 [라우팅](/learn/routing#passing) 섹션에 문서화되어 있습니다. ## 변경 로그 -- v3: 리소스 라우팅, 라우트 별칭, 스트리밍 지원, 라우트 그룹, 미들웨어 지원 추가. +- v3: 리소스 라우팅, 라우트 별칭, 스트리밍 지원, 라우트 그룹 및 미들웨어 지원 추가. - v1: 기본 기능의 대부분 사용 가능. \ No newline at end of file diff --git a/content/v3/lv/awesome-plugins/async.md b/content/v3/lv/awesome-plugins/async.md new file mode 100644 index 00000000..3d473b49 --- /dev/null +++ b/content/v3/lv/awesome-plugins/async.md @@ -0,0 +1,212 @@ +# Async + +Async ir mazs pakotnes Flight ietvaram, kas ļauj palaist jūsu Flight lietotnes asinhronos serveros un vidēs, piemēram, Swoole, AdapterMan, ReactPHP, Amp, RoadRunner, Workerman utt. No kastes tas ietver adapterus Swoole un AdapterMan. + +Mērķis: izstrādāt un atkļūdot ar PHP-FPM (vai iebūvēto serveri) un pārslēgties uz Swoole (vai citu asinhrono draiveri) ražošanā ar minimālām izmaiņām. + +## Prasības + +- PHP 7.4 vai augstāka +- Flight ietvars 3.16.1 vai augstāka +- [Swoole paplašinājums](https://www.openswoole.com) + +## Instalēšana + +Instalējiet caur composer: + +```bash +composer require flightphp/async +``` + +Ja plānojat palaist ar Swoole, instalējiet paplašinājumu: + +```bash +# izmantojot pecl +pecl install swoole +# vai openswoole +pecl install openswoole + +# vai ar pakotņu pārvaldnieku (Debian/Ubuntu piemērs) +sudo apt-get install php-swoole +``` + +## Ātrs Swoole piemērs + +Zemāk ir minimāla iestatīšana, kas parāda, kā atbalstīt gan PHP-FPM (vai iebūvēto serveri), gan Swoole, izmantojot to pašu koda bāzi. + +Faili, kas būs nepieciešami jūsu projektā: + +- index.php +- swoole_server.php +- SwooleServerDriver.php + +### index.php + +Šis fails ir vienkāršs slēdzis, kas piespiež lietotni palaist PHP režīmā izstrādei. + +```php +// index.php +route('/', function() use ($app) { + $app->json(['hello' => 'world']); +}); + +if (!defined('NOT_SWOOLE')) { + // Nepieciešams SwooleServerDriver klase, kad darbojas Swoole režīmā. + require_once __DIR__ . '/SwooleServerDriver.php'; + + Swoole\Runtime::enableCoroutine(); + $Swoole_Server = new SwooleServerDriver('127.0.0.1', 9501, $app); + $Swoole_Server->start(); +} else { + $app->start(); +} +``` + +### SwooleServerDriver.php + +Īss draiveris, kas parāda, kā savienot Swoole pieprasījumus ar Flight, izmantojot AsyncBridge un Swoole adapterus. + +```php +// SwooleServerDriver.php +Swoole = new SwooleServer($host, $port); + $this->app = $app; + + $this->setDefault(); + $this->bindWorkerEvents(); + $this->bindHttpEvent(); + } + + protected function setDefault() { + $this->Swoole->set([ + 'daemonize' => false, + 'dispatch_mode' => 1, + 'max_request' => 8000, + 'open_tcp_nodelay' => true, + 'reload_async' => true, + 'max_wait_time' => 60, + 'enable_reuse_port' => true, + 'enable_coroutine' => true, + 'http_compression' => false, + 'enable_static_handler' => true, + 'document_root' => __DIR__, + 'static_handler_locations' => ['/css', '/js', '/images', '/.well-known'], + 'buffer_output_size' => 4 * 1024 * 1024, + 'worker_num' => 4, + ]); + + $app = $this->app; + $app->map('stop', function (?int $code = null) use ($app) { + if ($code !== null) { + $app->response()->status($code); + } + }); + } + + protected function bindHttpEvent() { + $app = $this->app; + $AsyncBridge = new AsyncBridge($app); + + $this->Swoole->on('Start', function(SwooleServer $server) { + echo "Swoole http server is started at http://127.0.0.1:9501\n"; + }); + + $this->Swoole->on('Request', function (SwooleRequest $request, SwooleResponse $response) use ($AsyncBridge) { + $SwooleAsyncRequest = new SwooleAsyncRequest($request); + $SwooleAsyncResponse = new SwooleAsyncResponse($response); + + $AsyncBridge->processRequest($SwooleAsyncRequest, $SwooleAsyncResponse); + + $response->end(); + gc_collect_cycles(); + }); + } + + protected function bindWorkerEvents() { + $createPools = function() { + // izveidojiet darbinieka specifiskas savienojumu kopas šeit + }; + $closePools = function() { + // aizveriet kopas / tīriet šeit + }; + $this->Swoole->on('WorkerStart', $createPools); + $this->Swoole->on('WorkerStop', $closePools); + $this->Swoole->on('WorkerError', $closePools); + } + + public function start() { + $this->Swoole->start(); + } +} +``` + +## Servera palaišana + +- Izstrāde (PHP iebūvētais serveris / PHP-FPM): + - php -S localhost:8000 (vai pievienojiet -t public/ ja jūsu index ir public/) +- Ražošana (Swoole): + - php swoole_server.php + +Padoms: Ražošanā izmantojiet reverso proxy (Nginx) Swoole priekšā, lai apstrādātu TLS, statiskos failus un slodzes līdzsvarošanu. + +## Konfigurācijas piezīmes + +Swoole draiveris piedāvā vairākas konfigurācijas opcijas: +- worker_num: darbinieku procesu skaits +- max_request: pieprasījumi uz darbinieku pirms restartēšanas +- enable_coroutine: izmantojiet korutīnas vienlaicībai +- buffer_output_size: izvades bufera izmērs + +Pielāgojiet šos, lai atbilstu jūsu resursiem un trafika modeļiem. + +## Kļūdu apstrāde + +AsyncBridge pārvērš Flight kļūdas pareizās HTTP atbildēs. Jūs varat arī pievienot maršruta līmeņa kļūdu apstrādi: + +```php +$app->route('/*', function() use ($app) { + try { + // maršruta loģika + } catch (Exception $e) { + $app->response()->status(500); + $app->json(['error' => $e->getMessage()]); + } +}); +``` + +## AdapterMan un citas vidēs + +[AdapterMan](https://github.com/joanhey/adapterman) tiek atbalstīts kā alternatīvs vidēs adapteris. Pakotne ir paredzēta pielāgošanai — pievienošana vai izmantošana citu adapteru parasti seko tam pašam modelim: pārveido servera pieprasījumu/atbildi par Flight pieprasījumu/atbildi caur AsyncBridge un vidēs specifiskajiem adapteriem. \ No newline at end of file diff --git a/content/v3/lv/awesome-plugins/awesome_plugins.md b/content/v3/lv/awesome-plugins/awesome_plugins.md index ae306e93..2ad5d078 100644 --- a/content/v3/lv/awesome-plugins/awesome_plugins.md +++ b/content/v3/lv/awesome-plugins/awesome_plugins.md @@ -1,53 +1,59 @@ # Lieliski spraudņi -Flight ir neticami paplašināms. Ir vairāki spraudņi, ko var izmantot, lai pievienotu funkcionalitāti jūsu Flight lietojumprogrammai. Daži no tiem oficiāli atbalsta Flight komanda, bet citi ir mikro/lite bibliotēkas, lai palīdzētu jums sākt. +Flight ir neticami paplašināms. Ir vairāki spraudņi, ko var izmantot, lai pievienotu funkcionalitāti jūsu Flight aplikācijai. Daži no tiem oficiāli atbalsta Flight komanda, bet citi ir mikro/lite bibliotēkas, lai palīdzētu jums sākt. ## API dokumentācija -API dokumentācija ir izšķiroša jebkuram API. Tā palīdz izstrādātājiem saprast, kā mijiedarboties ar jūsu API un ko sagaidīt pretī. Ir pieejami vairāki rīki, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. +API dokumentācija ir izšķiroša jebkurai API. Tā palīdz izstrādātājiem saprast, kā mijiedarboties ar jūsu API un ko sagaidīt pretī. Ir pieejami vairāki rīki, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Bloga ieraksts, ko uzrakstījis Daniels Šreibers par to, kā izmantot OpenAPI specifikāciju ar FlightPHP, lai izveidotu jūsu API, izmantojot API pirmo pieeju. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ir lielisks rīks, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. To ir ļoti viegli izmantot un var pielāgot savām vajadzībām. Šī ir PHP bibliotēka, lai palīdzētu ģenerēt Swagger dokumentāciju. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Bloga ieraksts, ko uzrakstījis Daniels Šreibers, par to, kā izmantot OpenAPI specifikāciju ar FlightPHP, lai izveidotu jūsu API, izmantojot API pirmo pieeju. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ir lielisks rīks, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. To ir ļoti viegli izmantot un to var pielāgot jūsu vajadzībām. Šī ir PHP bibliotēka, lai palīdzētu ģenerēt Swagger dokumentāciju. -## Lietojumprogrammas veiktspējas uzraudzība (APM) +## Aplikācijas veiktspējas uzraudzība (APM) -Lietojumprogrammas veiktspējas uzraudzība (APM) ir izšķiroša jebkurai lietojumprogrammai. Tā palīdz saprast, kā darbojas jūsu lietojumprogramma un kur ir pudeles kakla vietas. Ir vairāki APM rīki, ko var izmantot ar Flight. -- oficiāls [flightphp/apm](/awesome-plugins/apm) - Flight APM ir vienkārša APM bibliotēka, ko var izmantot, lai uzraudzītu jūsu Flight lietojumprogrammas. To var izmantot, lai uzraudzītu jūsu lietojumprogrammas veiktspēju un palīdzētu identificēt pudeles kakla vietas. +Aplikācijas veiktspējas uzraudzība (APM) ir izšķiroša jebkurai aplikācijai. Tā palīdz saprast, kā jūsu aplikācija darbojas un kur ir pudeles kakli. Ir vairāki APM rīki, ko var izmantot ar Flight. +- oficiāls [flightphp/apm](/awesome-plugins/apm) - Flight APM ir vienkārša APM bibliotēka, ko var izmantot, lai uzraudzītu jūsu Flight aplikācijas. To var izmantot, lai uzraudzītu jūsu aplikācijas veiktspēju un palīdzētu identificēt pudeles kaklus. -## Autorizācija/Atslēgas +## Async -Autorizācija un atļaujas ir izšķirošas jebkurai lietojumprogrammai, kas prasa kontroli par to, kam ir piekļuve kam. +Flight jau ir ātrs ietvars, bet pievienojot tam turbo dzinēju, viss kļūst jautrāks (un izaicinošāks)! -- oficiāls [flightphp/permissions](/awesome-plugins/permissions) - Oficiālā Flight atļauju bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot lietotāja un lietojumprogrammas līmeņa atļaujas jūsu lietojumprogrammai. +- [flightphp/async](/awesome-plugins/async) - Oficiālā Flight Async bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot asinhrono apstrādi jūsu aplikācijai. Tā izmanto Swoole/Openswoole zem kapota, lai nodrošinātu vienkāršu un efektīvu veidu, kā palaist uzdevumus asinhroni. + +## Autorizācija/Atļaujas + +Autorizācija un atļaujas ir izšķirošas jebkurai aplikācijai, kas prasa kontroli par to, kam ir piekļuve kam. + +- oficiāls [flightphp/permissions](/awesome-plugins/permissions) - Oficiālā Flight Permissions bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot lietotāja un aplikācijas līmeņa atļaujas jūsu aplikācijai. ## Kešošana -Kešošana ir lielisks veids, kā paātrināt jūsu lietojumprogrammu. Ir vairāki kešošanas bibliotēkas, ko var izmantot ar Flight. +Kešošana ir lielisks veids, kā paātrināt jūsu aplikāciju. Ir vairāki kešošanas bibliotēkas, ko var izmantot ar Flight. -- oficiāls [flightphp/cache](/awesome-plugins/php-file-cache) - Viegls, vienkāršs un neatkarīgs PHP failu kešošanas klase +- oficiāls [flightphp/cache](/awesome-plugins/php-file-cache) - Gaisīga, vienkārša un neatkarīga PHP failā kešošanas klase ## CLI -CLI lietojumprogrammas ir lielisks veids, kā mijiedarboties ar jūsu lietojumprogrammu. Jūs varat izmantot tās, lai ģenerētu kontrolierus, parādītu visas maršrutus un vairāk. +CLI aplikācijas ir lielisks veids, kā mijiedarboties ar jūsu aplikāciju. Jūs varat izmantot tās, lai ģenerētu kontrolierus, parādītu visas maršrutus un vairāk. -- oficiāls [flightphp/runway](/awesome-plugins/runway) - Runway ir CLI lietojumprogramma, kas palīdz pārvaldīt jūsu Flight lietojumprogrammas. +- oficiāls [flightphp/runway](/awesome-plugins/runway) - Runway ir CLI aplikācija, kas palīdz jums pārvaldīt jūsu Flight aplikācijas. ## Sīkfaili -Sīkfaili ir lielisks veids, kā uzglabāt mazus datu gabaliņus klientu pusē. Tos var izmantot, lai uzglabātu lietotāja preferences, lietojumprogrammas iestatījumus un vairāk. +Sīkfaili ir lielisks veids, kā uzglabāt mazus datu gabalus klientu pusē. Tos var izmantot, lai uzglabātu lietotāja preferences, aplikācijas iestatījumus un vairāk. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie ir PHP bibliotēka, kas nodrošina vienkāršu un efektīvu veidu, kā pārvaldīt sīkfailus. ## Kļūdu labošana -Kļūdu labošana ir izšķiroša, kad jūs izstrādājat savā lokālajā vidē. Ir daži spraudņi, kas var uzlabot jūsu kļūdu labošanas pieredzi. +Kļūdu labošana ir izšķiroša, kad jūs attīstāt savā lokālajā vidē. Ir daži spraudņi, kas var uzlabot jūsu kļūdu labošanas pieredzi. -- [tracy/tracy](/awesome-plugins/tracy) - Šī ir pilnībā aprīkota kļūdu apstrādes bibliotēka, ko var izmantot ar Flight. Tā satur vairākas paneļus, kas var palīdzēt labot kļūdas jūsu lietojumprogrammā. To ir arī ļoti viegli paplašināt un pievienot savus paneļus. -- oficiāls [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Izmantojot ar [Tracy](/awesome-plugins/tracy) kļūdu apstrādi, šis spraudnis pievieno dažus papildu paneļus, lai palīdzētu ar kļūdu labošanu tieši Flight projektiem. +- [tracy/tracy](/awesome-plugins/tracy) - Šis ir pilnībā aprīkots kļūdu apstrādātājs, ko var izmantot ar Flight. Tam ir vairāki paneļi, kas var palīdzēt jums labot kļūdas jūsu aplikācijā. To ir arī ļoti viegli paplašināt un pievienot savus paneļus. +- oficiāls [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Izmantojot ar [Tracy](/awesome-plugins/tracy) kļūdu apstrādātāju, šis spraudnis pievieno dažus papildu paneļus, lai palīdzētu ar kļūdu labošanu specifiski Flight projektiem. ## Datubāzes -Datubāzes ir kodols lielākajai daļai lietojumprogrammu. Tā ir veids, kā uzglabāt un izgūt datus. Dažas datubāzu bibliotēkas ir vienkārši apvalki vaicājumu rakstīšanai, bet dažas ir pilnvērtīgas ORM. +Datubāzes ir kodols lielākajai daļai aplikāciju. Tā ir veids, kā uzglabāt un izgūt datus. Dažas datubāzu bibliotēkas ir vienkārši apvalki vaicājumu rakstīšanai, bet dažas ir pilnvērtīgas ORM. - oficiāls [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Oficiālais Flight PDO apvalks, kas ir daļa no kodola. Šis ir vienkāršs apvalks, lai palīdzētu vienkāršot vaicājumu rakstīšanas un izpildes procesu. Tas nav ORM. - oficiāls [flightphp/active-record](/awesome-plugins/active-record) - Oficiālā Flight ActiveRecord ORM/Mapper. Lieliska maza bibliotēka, lai viegli izgūtu un uzglabātu datus jūsu datubāzē. @@ -55,35 +61,35 @@ Datubāzes ir kodols lielākajai daļai lietojumprogrammu. Tā ir veids, kā uzg ## Šifrēšana -Šifrēšana ir izšķiroša jebkurai lietojumprogrammai, kas uzglabā sensitīvus datus. Datu šifrēšana un dešifrēšana nav pārāk grūta, bet pareiza šifrēšanas atslēgas uzglabāšana [var](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [būt](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [grūta](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Visnozīmīgākais ir nekad neuzglabāt jūsu šifrēšanas atslēgu publiskā direktorijā vai apņemt to jūsu koda repozitorijā. +Šifrēšana ir izšķiroša jebkurai aplikācijai, kas uzglabā sensitīvus datus. Datu šifrēšana un dešifrēšana nav pārāk grūti, bet pareiza šifrēšanas atslēgas uzglabāšana [var](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [būt](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [grūti](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Visnozīmīgākais ir nekad neuzglabāt jūsu šifrēšanas atslēgu publiskā direktorijā vai neiekļaut to jūsu koda repozitorijā. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Šī ir bibliotēka, ko var izmantot, lai šifrētu un dešifrētu datus. Sākšana un palaišana ir diezgan vienkārša, lai sāktu šifrēt un dešifrēt datus. ## Darbu rinda -Darbu rindas ir patiešām noderīgas, lai asinhroni apstrādātu uzdevumus. Tas var būt e-pastu sūtīšana, attēlu apstrāde vai jebkas, kam nav jāveic reāllaikā. +Darbu rindas ir patiešām noderīgas, lai asinhroni apstrādātu uzdevumus. Tas var būt e-pastu sūtīšana, attēlu apstrāde vai jebkas, kam nav jābūt reāllaika. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue ir bibliotēka, ko var izmantot, lai asinhroni apstrādātu darbus. To var izmantot ar beanstalkd, MySQL/MariaDB, SQLite un PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue ir bibliotēka, ko var izmantot, lai apstrādātu darbus asinhroni. To var izmantot ar beanstalkd, MySQL/MariaDB, SQLite un PostgreSQL. -## Sesija +## Sesijas -Sesijas nav īsti noderīgas API, bet veidojot tīmekļa lietojumprogrammu, sesijas var būt izšķirošas stāvokļa un pieteikšanās informācijas uzturēšanai. +Sesijas nav īsti noderīgas API, bet veidojot tīmekļa aplikāciju, sesijas var būt izšķirošas, lai uzturētu stāvokli un pieteikšanās informāciju. -- oficiāls [flightphp/session](/awesome-plugins/session) - Oficiālā Flight sesijas bibliotēka. Šī ir vienkārša sesijas bibliotēka, ko var izmantot, lai uzglabātu un izgūtu sesijas datus. Tā izmanto PHP iebūvēto sesijas apstrādi. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Sesijas pārvaldnieks (nebloķējošs, zibspuldze, segments, sesijas šifrēšana). Izmanto PHP open_ssl izvēles šifrēšanai/dešifrēšanai sesijas datiem. +- oficiāls [flightphp/session](/awesome-plugins/session) - Oficiālā Flight Session bibliotēka. Šī ir vienkārša sesijas bibliotēka, ko var izmantot, lai uzglabātu un izgūtu sesijas datus. Tā izmanto PHP iebūvēto sesijas apstrādi. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session pārvaldnieks (nebloķējošs, zibspuldze, segments, sesijas šifrēšana). Izmanto PHP open_ssl opcionālai sesijas datu šifrēšanai/dešifrēšanai. ## Veidnes -Veidnes ir kodols jebkurai tīmekļa lietojumprogrammai ar lietotāja saskarni. Ir vairāki veidņu dzinēji, ko var izmantot ar Flight. +Veidnes ir kodols jebkurai tīmekļa aplikācijai ar UI. Ir vairāki veidņu dzinēji, ko var izmantot ar Flight. - novecojis [flightphp/core View](/learn#views) - Šis ir ļoti pamata veidņu dzinējs, kas ir daļa no kodola. Nav ieteicams izmantot, ja jūsu projektā ir vairāk nekā pāris lapas. -- [latte/latte](/awesome-plugins/latte) - Latte ir pilnībā aprīkots veidņu dzinējs, ko ir ļoti viegli izmantot un tas jūtas tuvāk PHP sintaksei nekā Twig vai Smarty. To ir arī ļoti viegli paplašināt un pievienot savus filtrus un funkcijas. +- [latte/latte](/awesome-plugins/latte) - Latte ir pilnībā aprīkots veidņu dzinējs, kas ir ļoti viegli lietojams un jūtas tuvāk PHP sintaksei nekā Twig vai Smarty. To ir arī ļoti viegli paplašināt un pievienot savus filtrus un funkcijas. ## WordPress integrācija -Vai vēlaties izmantot Flight savā WordPress projektā? Ir ērts spraudnis tam! +Vai vēlaties izmantot Flight jūsu WordPress projektā? Ir ērts spraudnis tam! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Šis WordPress spraudnis ļauj palaist Flight tieši blakus WordPress. Tas ir ideāls, lai pievienotu pielāgotus API, mikroservusus vai pat pilnvērtīgas lietojumprogrammas jūsu WordPress vietnē, izmantojot Flight framework. Ļoti noderīgi, ja vēlaties labāko no abām pasaulēm! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Šis WordPress spraudnis ļauj palaist Flight tieši blakus WordPress. Tas ir ideāls, lai pievienotu pielāgotas API, mikroservisus vai pat pilnas aplikācijas jūsu WordPress vietnē, izmantojot Flight ietvaru. Ļoti noderīgi, ja vēlaties labāko no abām pasaulēm! ## Iesaiste diff --git a/content/v3/lv/examples.md b/content/v3/lv/examples.md index 5cb30234..d7b1605e 100644 --- a/content/v3/lv/examples.md +++ b/content/v3/lv/examples.md @@ -1,36 +1,37 @@ -# Nepieciešams ātrs sākums? +# Vai ātri sākt? -Jums ir divas iespējas, kā uzsākt jaunu Flight projektu: +Jums ir divas opcijas, lai sāktu jaunu Flight projektu: -- [Pilnais skeleta veidne](https://github.com/flightphp/skeleton): Vairāk pilnīgs piemērs ar kontrolieriem un skatlogiem. -- [Vienas faila skeleta veidne](https://github.com/flightphp/skeleton-simple): Viens fails, kas iekļauj visu, kas jums nepieciešams, lai palaistu savu lietojumprogrammu vienā vienkāršā failā. +- [Pilna skeletu sagatave](https://github.com/flightphp/skeleton): Pilnīgāks piemērs ar kontrolieriem un skatiem. +- [Vienkārša faila skeletu sagatave](https://github.com/flightphp/skeleton-simple): Viens fails, kas ietver visu nepieciešamo, lai palaistu jūsu lietotni vienā vienkāršā failā. -Kopienas sniegtie piemēri: +Kopienas sniegti piemēri: -- [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP ar Laravel katalogiem, ar PHP rīkiem + GH darbībām -- [fleact](https://github.com/flightphp/fleact) - FlightPHP sākuma komplekts ar ReactJS integrāciju. -- [flastro](https://github.com/flightphp/flastro) - FlightPHP sākuma komplekts ar Astro integrāciju. -- [velt](https://github.com/flightphp/velt) - Velt ir ātra un vienkārša Svelte sākuma veidne ar FlightPHP aizmugurē. +- [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP ar Laravel direktorijām, ar PHP rīkiem + GH Actions +- [fleact](https://github.com/flightphp/fleact) - FlightPHP starter komplekts ar ReactJS integrāciju. +- [flastro](https://github.com/flightphp/flastro) - FlightPHP starter komplekts ar Astro integrāciju. +- [velt](https://github.com/flightphp/velt) - Velt ir ātrs un viegls Svelte starter veidne ar FlightPHP aizmuguri. -## Nepieciešama iedvesma? +## Vai vajag iedvesmu? -Lai gan šie nav oficiāli atbalstīti no Flight komandas, tie var dot jums idejas, kā strukturēt savus projektus, kas izveidoti ar Flight! +Lai gan šie nav oficiāli atbalstīti no Flight komandas puses, tie var sniegt idejas, kā strukturēt savus paša projektus, kas izveidoti ar Flight! -- [Decay](https://github.com/boxybird/decay) - Flight v3 ar HTMX un SleekDB, pilnībā par zombijiem! ([Demo](https://decay.andrewrhyand.com)) -- [Flight Piemēru emuārs](https://github.com/n0nag0n/flightphp-blog) - Flight v3 ar Middleware, kontrolieriem, Aktīvo ierakstu un Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Vienkāršs CRUD API projekts, kas izmanto Flight framework, kas nodrošina pamata struktūru jaunajiem lietotājiem, lai ātri izveidotu PHP lietojumprogrammu ar CRUD operācijām un datu bāzes savienojamību. Projekts demonstrē, kā izmantot Flight RESTful API izstrādei, padarot to par ideālu mācību rīku iesācējiem un noderīgu sākuma komplektu pieredzējušākiem izstrādātājiem. -- [Flight Skolas vadības sistēma](https://github.com/krmu/FlightPHP_School) - Flight v3 -- [Paste Bin ar komentāriem](https://github.com/n0nag0n/commie2) - Flight v3 -- [Pamata skeleta lietojumprogramma](https://github.com/markhughes/flight-skeleton) -- [Piemēru Viki](https://github.com/Skayo/FlightWiki) -- [IT-Innovator PHP Framework lietojumprogramma](https://github.com/itinnovator/myphp-app) -- [LittleEducationalCMS (spāņu)](https://github.com/casgin/LittleEducationalCMS) -- [Itāļu dzelteno lapu API](https://github.com/chiccomagnus/PGAPI) -- [Vispārējs satura pārvaldības sistēma (ar....ļoti maz dokumentācijas)](https://github.com/recepuncu/cms) -- [Mazs php framework, kas balstīts uz Flight un medoo.](https://github.com/ycrao/tinyme) -- [Piemēru MVC lietojumprogramma](https://github.com/paddypei/Flight-MVC) -— [Ražošanai gatava izmēģinājuma versija](https://github.com/madcoda9000/SecStore) — Ražošanai gatava autentifikācijas sistēma, kas ietaupa jūsu izstrādes laiku nedēļām. Piedāvā uzņēmuma līmeņa drošību: 2FA/TOTP, LDAP integrāciju, Azure SSO, viedu ātruma ierobežošanu, sesijas pirkstu nospiedumu noņemšanu, brutālas piespēles aizsardzību, drošības analītikas informācijas paneli, visaptverošu audita reģistrēšanu un detalizētu uz lomām balstītu piekļuves kontroli. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental ir vienlapa, mobilajām ierīcēm draudzīga auto nomas tīmekļa lietotne, kas izveidota ar PHP (FlightPHP), JavaScript un MySQL. Tā atbalsta lietotāju reģistrāciju, pārlūkošanu un auto rezervēšanu, savukārt administratori var pārvaldīt auto, lietotājus un rezervācijas. Lietotnē ir REST API, JWT autentifikācija un responsīvs dizains modernai nomas pieredzei. +- [Decay](https://github.com/boxybird/decay) - Flight v3 ar HTMX un SleekDB, viss par zombijiem! ([Demo](https://decay.andrewrhyand.com)) +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 ar starprogrammatūru, kontrolieriem, Active Record un Latte. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Vienkāršs CRUD API projekts, izmantojot Flight ietvaru, kas nodrošina pamata struktūru jauniem lietotājiem, lai ātri izveidotu PHP lietotni ar CRUD operācijām un datubāzes savienojumu. Projekts demonstrē, kā izmantot Flight RESTful API izstrādei, padarot to par ideālu mācību rīku iesācējiem un noderīgu starter komplektu pieredzējušākiem izstrādātājiem. +- [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 +- [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 +- [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) +- [Example Wiki](https://github.com/Skayo/FlightWiki) +- [The IT-Innovator PHP Framework Application](https://github.com/itinnovator/myphp-app) +- [LittleEducationalCMS (Spanish)](https://github.com/casgin/LittleEducationalCMS) +- [Italian Yellow Pages API](https://github.com/chiccomagnus/PGAPI) +- [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) +- [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) +- [Example MVC Application](https://github.com/paddypei/Flight-MVC) +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Ražošanai gatavs autentifikācijas ietvars, kas ietaupa nedēļām ilgu izstrādi. Funkcijas ietver uzņēmuma līmeņa drošību: 2FA/TOTP, LDAP integrācija, Azure SSO, inteliģenta ātruma ierobežošana, sesijas pirkstu nospieduma atpazīšana, aizsardzība pret brutālu spēku, drošības analītikas panelis, visaptveroša audita žurnālošana un granulāra lomām balstīta piekļuves kontrole. -## Vēlaties dalīties ar savu piemēru? +## Vai vēlaties dalīties ar savu paša piemēru? -Ja jums ir projekts, ko vēlaties dalīties, lūdzu, iesniedziet pull pieprasījumu, lai pievienotu to šim sarakstam! \ No newline at end of file +Ja jums ir projekts, kuru vēlaties dalīt, lūdzu, iesniedziet pull request, lai to pievienotu šim sarakstam! \ No newline at end of file diff --git a/content/v3/lv/learn/requests.md b/content/v3/lv/learn/requests.md index a0aaf871..8e34ec9f 100644 --- a/content/v3/lv/learn/requests.md +++ b/content/v3/lv/learn/requests.md @@ -2,7 +2,7 @@ ## Pārskats -Flight ietver HTTP pieprasījumu vienā objektā, ko var piekļūt, darot: +Flight ieslēdz HTTP pieprasījumu vienā objektā, ko var piekļūt, veicot: ```php $request = Flight::request(); @@ -10,13 +10,13 @@ $request = Flight::request(); ## Saprašana -HTTP pieprasījumi ir viens no galvenajiem HTTP cikla aspektiem, ko saprast. Lietotājs veic darbību tīmekļa pārlūkprogrammā vai HTTP klientā, un viņi nosūta virkni galvenes, ķermeņa, URL utt. uz jūsu projektu. Jūs varat uztvert šīs galvenes (pārlūkprogrammas valoda, kādu veida kompresiju viņi var apstrādāt, lietotāja aģents utt.) un uztvert ķermeni un URL, kas nosūtīts uz jūsu Flight lietojumprogrammu. Šie pieprasījumi ir būtiski jūsu lietojumprogrammai, lai saprastu, ko darīt tālāk. +HTTP pieprasījumi ir viens no galvenajiem HTTP dzīves cikla aspektiem, ko jāizprot. Lietotājs veic darbību tīmekļa pārlūkprogrammā vai HTTP klientā, un tie nosūta virkni galvenes, ķermeņa, URL utt. uz jūsu projektu. Jūs varat uztvert šīs galvenes (pārlūkprogrammas valoda, kādu kompresijas veidu tās var apstrādāt, lietotāja aģents utt.) un uztvert ķermeni un URL, kas nosūtīts uz jūsu Flight lietojumprogrammu. Šie pieprasījumi ir būtiski, lai jūsu lietojumprogramma saprastu, ko darīt tālāk. ## Pamata Izmantošana -PHP ir vairākas superglobālas, tostarp `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` un `$_COOKIE`. Flight abstraktē šīs prom praktiskos [Collections](/learn/collections). Jūs varat piekļūt `query`, `data`, `cookies` un `files` īpašībām kā masīviem vai objektiem. +PHP ir vairākas superglobālās mainīgās, tostarp `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` un `$_COOKIE`. Flight abstraktē šīs prom praktiskajās [Kolekcijās](/learn/collections). Jūs varat piekļūt `query`, `data`, `cookies` un `files` īpašībām kā masīviem vai objektiem. -> **Piezīme:** Ir ** ĻOTI** atdissludināts izmantot šīs superglobālas savā projektā, un tās jāatsaucas caur `request()` objektu. +> **Piezīme:** Ir ** ĻOTI** atgrūstami izmantot šīs superglobālās mainīgās savā projektā, un tām jāatsaucas caur `request()` objektu. > **Piezīme:** Nav pieejama abstrakcija `$_ENV`. @@ -30,8 +30,8 @@ Flight::route('/search', function(){ $keyword = Flight::request()->query['keyword']; // or $keyword = Flight::request()->query->keyword; - echo "Jūs meklējat: $keyword"; - // vaicāt datubāzi vai kaut ko citu ar $keyword + echo "You are searching for: $keyword"; + // query a database or something else with the $keyword }); ``` @@ -46,8 +46,8 @@ Flight::route('POST /submit', function(){ // or $name = Flight::request()->data->name; $email = Flight::request()->data->email; - echo "Jūs iesniedzāt: $name, $email"; - // saglabāt datubāzē vai kaut ko citu ar $name un $email + echo "You submitted: $name, $email"; + // save to a database or something else with the $name and $email }); ``` @@ -60,7 +60,7 @@ Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; // or $savedLogin = Flight::request()->cookies->myLoginCookie; - // pārbaudīt, vai tas tiešām ir saglabāts vai nē, un ja ir, automātiski pieteikties + // check if it's really saved or not and if it is auto log them in if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -68,7 +68,7 @@ Flight::route('GET /login', function(){ }); ``` -Palīdzībai iestatīt jaunas cepumu vērtības skatiet [overclokk/cookie](/awesome-plugins/php-cookie) +Lai iegūtu palīdzību par jaunu sīkfailu vērtību iestatīšanu, skatiet [overclokk/cookie](/awesome-plugins/php-cookie) ### `$_SERVER` @@ -81,7 +81,7 @@ $host = Flight::request()->getVar('HTTP_HOST'); ### `$_FILES` -Jūs varat piekļūt augšupielādētiem failiem caur `files` īpašību: +Jūs varat piekļūt augšupielādētajām failiem caur `files` īpašību: ```php // raw access to $_FILES property. See below for recommended approach @@ -92,26 +92,26 @@ $uploadedFile = Flight::request()->files->myFile; Skatiet [Uploaded File Handler](/learn/uploaded-file) vairāk informācijas. -#### Apstrāde Failu Augšupielādes +#### Failu Augšupielādes Apstrāde _v3.12.0_ -Jūs varat apstrādāt failu augšupielādi, izmantojot ietvaru ar dažām palīglokalizācijām. Tas būtībā samazinās līdz failu datu izvilkšanai no pieprasījuma un pārvietošanai uz jaunu atrašanās vietu. +Jūs varat apstrādāt failu augšupielādi, izmantojot ietvaru ar dažām palīgapstrādes metodēm. Tas būtībā samazinās līdz faila datu iegūšanai no pieprasījuma un to pārvietošanai uz jaunu atrašanās vietu. ```php Flight::route('POST /upload', function(){ - // Ja jums ir ievades lauks kā + // If you had an input field like $uploadedFileData = Flight::request()->getUploadedFiles(); $uploadedFile = $uploadedFileData['myFile']; $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); }); ``` -Ja jums ir vairāki augšupielādēti faili, jūs varat iterēt caur tiem: +Ja jums ir vairāki augšupielādēti faili, jūs varat tos iziet cauri cilpai: ```php Flight::route('POST /upload', function(){ - // Ja jums ir ievades lauks kā + // If you had an input field like $uploadedFiles = Flight::request()->getUploadedFiles()['myFiles']; foreach ($uploadedFiles as $uploadedFile) { $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); @@ -119,23 +119,23 @@ Flight::route('POST /upload', function(){ }); ``` -> **Drošības Piezīme:** Vienmēr validējiet un sanitējiet lietotāja ievadi, īpaši, kad darbojaties ar failu augšupielādi. Vienmēr validējiet paplašinājumu tipus, kurus atļausiet augšupielādēt, bet jums arī jāvalidē faila "magic bytes", lai nodrošinātu, ka tas tiešām ir tāda tipa fails, kādu lietotājs apgalvo. Ir pieejami [raksti](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [un](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [bibliotēkas](https://github.com/RikudouSage/MimeTypeDetector), lai palīdzētu ar to. +> **Drošības Piezīme:** Vienmēr validējiet un sanitizējiet lietotāja ievadi, īpaši, kad strādājat ar failu augšupielādi. Vienmēr validējiet paplašinājumu veidus, kurus atļausiet augšupielādēt, bet jums arī vajadzētu validēt faila "magic bytes", lai nodrošinātu, ka tas patiešām ir tāds faila veids, kādu lietotājs apgalvo. Ir pieejami [raksti](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [un](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [bibliotēkas](https://github.com/RikudouSage/MimeTypeDetector), lai palīdzētu ar to. ### Pieprasījuma Ķermenis -Lai iegūtu neapstrādātu HTTP pieprasījuma ķermeni, piemēram, kad darbojaties ar POST/PUT pieprasījumiem, -jūs varat darīt: +Lai iegūtu neapstrādātu HTTP pieprasījuma ķermeni, piemēram, strādājot ar POST/PUT pieprasījumiem, +jūs varat veikt: ```php Flight::route('POST /users/xml', function(){ $xmlBody = Flight::request()->getBody(); - // darīt kaut ko ar XML, kas tika nosūtīts. + // do something with the XML that was sent. }); ``` ### JSON Ķermenis -Ja jūs saņemat pieprasījumu ar satura tipu `application/json` un piemēra datiem `{"id": 123}` +Ja jūs saņemat pieprasījumu ar satura veidu `application/json` un piemēra datiem `{"id": 123}` tas būs pieejams no `data` īpašības: ```php @@ -148,12 +148,12 @@ Jūs varat piekļūt pieprasījuma galvenēm, izmantojot `getHeader()` vai `getH ```php -// Varbūt jums vajag Autorizācijas galveni +// Maybe you need Authorization header $host = Flight::request()->getHeader('Authorization'); // or $host = Flight::request()->header('Authorization'); -// Ja jums vajag paņemt visas galvenes +// If you need to grab all headers $headers = Flight::request()->getHeaders(); // or $headers = Flight::request()->headers(); @@ -168,7 +168,7 @@ $method = Flight::request()->method; // actually populated by getMethod() $method = Flight::request()->getMethod(); ``` -**Piezīme:** `getMethod()` metode vispirms izvelk metodi no `$_SERVER['REQUEST_METHOD']`, tad to var pārrakstīt +**Piezīme:** `getMethod()` metode vispirms iegūst metodi no `$_SERVER['REQUEST_METHOD']`, tad to var pārspēt `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']`, ja tā pastāv, vai `$_REQUEST['_method']`, ja tā pastāv. ## Pieprasījuma Objekta Īpašības @@ -184,21 +184,21 @@ Pieprasījuma objekts nodrošina šādas īpašības: - **ajax** - Vai pieprasījums ir AJAX pieprasījums - **scheme** - Servera protokols (http, https) - **user_agent** - Pārlūkprogrammas informācija -- **type** - Satura tips +- **type** - Satura veids - **length** - Satura garums - **query** - Vaicājuma virknes parametri - **data** - POST dati vai JSON dati -- **cookies** - Cepumu dati -- **files** - Augšupielādēti faili +- **cookies** - Sīkfailu dati +- **files** - Augšupielādētie faili - **secure** - Vai savienojums ir drošs - **accept** - HTTP pieņemšanas parametri -- **proxy_ip** - Proxy IP adrese klienta. Skenē `$_SERVER` masīvu pēc `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` tajā secībā. -- **host** - Pieprasījuma resursdatora nosaukums +- **proxy_ip** - Klienta proxy IP adrese. Skenē `$_SERVER` masīvu pēc `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` šādā secībā. +- **host** - Pieprasījuma saimnieka nosaukums - **servername** - SERVER_NAME no `$_SERVER` -## Palīglokas +## Palīgapstrādes Metodes -Ir dažas palīglokas, lai saliktu URL daļas vai darbotos ar noteiktām galvenēm. +Ir dažas palīgapstrādes metodes, lai saliktu URL daļas vai strādātu ar noteiktām galvenēm. ### Pilns URL @@ -216,7 +216,7 @@ Jūs varat piekļūt bāzes URL, izmantojot `getBaseUrl()` metodi: // http://example.com/path/to/something/cool?query=yes+thanks $url = Flight::request()->getBaseUrl(); // https://example.com -// Pievērsiet uzmanību, nav beigu slīpsvītras. +// Notice, no trailing slash. ``` ## Vaicājuma Parsēšana @@ -228,28 +228,28 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` -## Sarunu Satura Pieņemšanas Tipi +## Saturu Pieņemšanas Veidu Sarunas _v3.17.2_ -Jūs varat izmantot `negotiateContentType()` metodi, lai noteiktu labāko satura tipu, ar kuru atbildēt, balstoties uz `Accept` galveni, ko nosūtīja klients. +Jūs varat izmantot `negotiateContentType()` metodi, lai noteiktu labāko satura veidu, ar kuru atbildēt, balstoties uz `Accept` galveni, ko nosūtījis klients. ```php -// Piemēra Accept galvene: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 -// Zemāk definē, ko jūs atbalstāt. +// Example Accept header: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// The below defines what you support. $availableTypes = ['application/json', 'application/xml']; $typeToServe = Flight::request()->negotiateContentType($availableTypes); if ($typeToServe === 'application/json') { - // Pasniegt JSON atbildi + // Serve JSON response } elseif ($typeToServe === 'application/xml') { - // Pasniegt XML atbildi + // Serve XML response } else { - // Noklusējuma kaut ko citu vai mest kļūdu + // Default to something else or throw an error } ``` -> **Piezīme:** Ja neviens no pieejamajiem tipiem nav atrasts `Accept` galvenē, metode atgriezīs `null`. Ja nav definēta `Accept` galvene, metode atgriezīs pirmo tipu `$availableTypes` masīvā. +> **Piezīme:** Ja neviena no pieejamajām veidiem nav atrasta `Accept` galvenē, metode atgriezīs `null`. Ja nav definēta `Accept` galvene, metode atgriezīs pirmo veidu `$availableTypes` masīvā. ## Skatīt Arī - [Routing](/learn/routing) - Skatiet, kā kartēt maršrutus uz kontrolieriem un renderēt skatus. @@ -259,9 +259,9 @@ if ($typeToServe === 'application/json') { - [Uploaded File Handler](/learn/uploaded-file) - Failu augšupielādes apstrāde. ## Traucējummeklēšana -- `request()->ip` un `request()->proxy_ip` var atšķirties, ja jūsu tīmekļa serveris ir aiz proxy, slodzes līdzsvara utt. +- `request()->ip` un `request()->proxy_ip` var atšķirties, ja jūsu tīmekļa serveris ir aiz proxy, slodzes balansētāja utt. ## Izmaiņu Žurnāls - v3.17.2 - Pievienota negotiateContentType() - v3.12.0 - Pievienota spēja apstrādāt failu augšupielādi caur pieprasījuma objektu. -- v1.0 - Sākotnējā izlaišana. \ No newline at end of file +- v1.0 - Sākotnējais izdevums. \ No newline at end of file diff --git a/content/v3/lv/learn/routing.md b/content/v3/lv/learn/routing.md index 3f52953e..4997c0b9 100644 --- a/content/v3/lv/learn/routing.md +++ b/content/v3/lv/learn/routing.md @@ -1,44 +1,44 @@ -# Maršrutizēšana +# Maršrutizācija ## Pārskats -Maršrutizēšana Flight PHP kartē URL modeļus uz atgriezeniskās saites funkcijām vai klases metodēm, ļaujot ātri un vienkārši apstrādāt pieprasījumus. Tā ir paredzēta minimālam overhead, iesācējam draudzīgai lietošanai un paplašināmībai bez ārējām atkarībām. +Maršrutizācija Flight PHP kartē URL raksturlietas ar atgriezeniskajām funkcijām vai klases metodēm, ļaujot ātri un vienkārši apstrādāt pieprasījumus. Tā ir paredzēta minimālam overhead, iesācējam draudzīgai lietošanai un paplašināmībai bez ārējām atkarībām. ## Saprašana -Maršrutizēšana ir kodola mehānisms, kas savieno HTTP pieprasījumus ar jūsu lietojumprogrammas loģiku Flight. Definējot maršrutus, jūs norādāt, kā dažādi URL aktivizē specifisku kodu, vai nu caur funkcijām, klases metodēm vai kontroliera darbībām. Flight maršrutizēšanas sistēma ir elastīga, atbalstot pamata modeļus, nosauktos parametrus, regulārās izteiksmes un papildu funkcijas, piemēram, atkarību injekciju un resursu maršrutizēšanu. Šī pieeja uztur jūsu kodu organizētu un viegli uzturamu, vienlaikus paliekot ātrai un vienkāršai iesācējiem un paplašināmai pieredzējušiem lietotājiem. +Maršrutizācija ir kodola mehānisms, kas savieno HTTP pieprasījumus ar jūsu lietojumprogrammas loģiku Flight. Definējot maršrutus, jūs norādāt, kā dažādas URL izraisa specifisku kodu, vai nu caur funkcijām, klases metodēm vai kontroliera darbībām. Flight maršrutizācijas sistēma ir elastīga, atbalsta pamatraksturlietas, nosauktos parametrus, regulārās izteiksmes un papildu funkcijas, piemēram, atkarību injekciju un resursu maršrutizāciju. Šī pieeja uztur jūsu kodu organizētu un viegli uzturamu, vienlaikus paliekot ātra un vienkārša iesācējiem un paplašināma pieredzējušiem lietotājiem. -> **Piezīme:** Vēlaties saprast vairāk par maršrutizēšanu? Apskatiet ["kāpēc ietvars?"](/learn/why-frameworks) lapu plašākam skaidrojumam. +> **Piezīme:** Vēlaties saprast vairāk par maršrutizāciju? Apskatiet ["kāpēc ietvars?"](/learn/why-frameworks) lapu plašākam skaidrojumam. -## Pamata lietošana +## Pamata Lietošana -### Vienkārša maršruta definēšana -Pamata maršrutizēšana Flight tiek veikta, saskaņojot URL modeli ar atgriezeniskās saites funkciju vai klases un metodes masīvu. +### Vienkārša Maršruta Definēšana +Pamata maršrutizācija Flight tiek veikta, saskaņojot URL raksturlietu ar atgriezenisko funkciju vai klases un metodes masīvu. ```php Flight::route('/', function(){ - echo 'hello world!'; + echo 'sveiks pasaule!'; }); ``` -> Maršruti tiek saskaņoti tajā secībā, kādā tie ir definēti. Pirmais maršruts, kas atbilst pieprasījumam, tiks izsaukts. +> Maršruti tiek saskaņoti tajā secībā, kādā tie ir definēti. Pirmais maršruts, kas saskan ar pieprasījumu, tiks izsaukts. -### Funkciju lietošana kā atgriezeniskās saites -Atgriezeniskā saite var būt jebkurš aizmirsts objekts. Tātad jūs varat izmantot parastu funkciju: +### Funkciju Lietošana kā Atgriezeniskajām Funkcijām +Atgriezeniskā funkcija var būt jebkurš callable objekts. Tātad jūs varat izmantot parasto funkciju: ```php function hello() { - echo 'hello world!'; + echo 'sveiks pasaule!'; } Flight::route('/', 'hello'); ``` -### Klases un metodes lietošana kā kontrolieris -Jūs varat izmantot klases metodi (statisku vai nē) kā kontrolieris: +### Klases un Metodes Lietošana kā Kontrolieris +Jūs varat izmantot klases metodi (statisku vai nē) kā: ```php class GreetingController { public function hello() { - echo 'hello world!'; + echo 'sveiks pasaule!'; } } @@ -51,7 +51,7 @@ Flight::route('/', [ 'GreetingController::hello' ]); Flight::route('/', [ 'GreetingController->hello' ]); ``` -Vai arī izveidojot objektu vispirms un pēc tam izsaucot metodi: +Vai arī izveidojot objektu pirms tam un pēc tam izsaucot metodi: ```php use flight\Engine; @@ -66,7 +66,7 @@ class GreetingController } public function hello() { - echo "Hello, {$this->name}!"; + echo "Sveiks, {$this->name}!"; } } @@ -77,19 +77,19 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **Piezīme:** Pēc noklusējuma, kad kontrolieris tiek izsaukts ietvarā, `flight\Engine` klase vienmēr tiek injicēta, ja vien jūs nenorādāt caur [atkarību injekcijas konteineru](/learn/dependency-injection-container) +> **Piezīme:** Pēc noklusējuma, kad kontrolieris tiek izsaukts ietvarā, flight\Engine klase vienmēr tiek injicēta, ja vien jūs neprecizējat caur [atkarību injekcijas konteineru](/learn/dependency-injection-container) -### Metodes specifiska maršrutizēšana +### Metodes Specifiska Maršrutizācija -Pēc noklusējuma maršrutu modeļi tiek saskaņoti pret visām pieprasījuma metodēm. Jūs varat atbildēt uz specifiskām metodēm, novietojot identifikatoru pirms URL. +Pēc noklusējuma maršruta raksturlietas tiek saskaņotas pret visām pieprasījuma metodēm. Jūs varat atbildēt uz specifiskām metodēm, novietojot identifikatoru pirms URL. ```php Flight::route('GET /', function () { - echo 'I received a GET request.'; + echo 'Es saņēmu GET pieprasījumu.'; }); Flight::route('POST /', function () { - echo 'I received a POST request.'; + echo 'Es saņēmu POST pieprasījumu.'; }); // You cannot use Flight::get() for routes as that is a method @@ -100,35 +100,35 @@ Flight::put('/', function() { /* code */ }); Flight::delete('/', function() { /* code */ }); ``` -Jūs varat arī kartēt vairākas metodes uz vienu atgriezenisko saiti, izmantojot `|` atdalītāju: +Jūs varat arī kartēt vairākas metodes uz vienu atgriezenisko funkciju, izmantojot `|` atdalītāju: ```php Flight::route('GET|POST /', function () { - echo 'I received either a GET or a POST request.'; + echo 'Es saņēmu vai nu GET, vai POST pieprasījumu.'; }); ``` -### Īpaša apstrāde HEAD un OPTIONS pieprasījumiem +### Īpaša Apstrāde HEAD un OPTIONS Pieprasījumiem -Flight nodrošina iebūvētu apstrādi `HEAD` un `OPTIONS` HTTP pieprasījumiem: +Flight nodrošina iebūvētu apstrādi HEAD un OPTIONS HTTP pieprasījumiem: -#### HEAD pieprasījumi +#### HEAD Pieprasījumi -- **HEAD pieprasījumi** tiek apstrādāti tāpat kā `GET` pieprasījumi, bet Flight automātiski noņem atbildes ķermeni pirms nosūtīšanas klientam. -- Tas nozīmē, ka jūs varat definēt maršrutu `GET`, un HEAD pieprasījumi uz to pašu URL atgriezīs tikai galvenes (bez satura), kā paredzēts HTTP standartos. +- **HEAD pieprasījumi** tiek apstrādāti tieši kā GET pieprasījumi, bet Flight automātiski noņem atbildes ķermeni pirms tā nosūtīšanas klientam. +- Tas nozīmē, ka jūs varat definēt maršrutu GET, un HEAD pieprasījumi uz to pašu URL atgriezīs tikai galvenes (bez satura), kā paredzēts HTTP standartos. ```php Flight::route('GET /info', function() { - echo 'This is some info!'; + echo 'Šī ir kāda informācija!'; }); // A HEAD request to /info will return the same headers, but no body. ``` -#### OPTIONS pieprasījumi +#### OPTIONS Pieprasījumi -`OPTIONS` pieprasījumi tiek automātiski apstrādāti Flight jebkuram definētam maršrutam. -- Kad OPTIONS pieprasījums tiek saņemts, Flight atbild ar `204 No Content` statusu un `Allow` galveni, kas uzskaita visas atbalstītās HTTP metodes tam maršrutam. -- Jums nav jādefinē atsevišķs maršruts OPTIONS, ja vien jūs nevēlaties pielāgotu uzvedību vai modificēt atbildi. +OPTIONS pieprasījumi tiek automātiski apstrādāti Flight jebkuram definētam maršrutam. +- Kad saņemts OPTIONS pieprasījums, Flight atbild ar `204 No Content` statusu un `Allow` galveni, kas uzskaita visas atbalstītās HTTP metodes tam maršrutam. +- Jums nav jādefinē atsevišķs maršruts OPTIONS. ```php // For a route defined as: @@ -140,9 +140,9 @@ Flight::route('GET|POST /users', function() { /* ... */ }); // Allow: GET, POST, HEAD, OPTIONS ``` -### Maršrutētāja objekta lietošana +### Maršrutētāja Objekta Lietošana -Papildus jūs varat iegūt Maršrutētāja objektu, kuram ir dažas palīgfunkcijas jums: +Papildus jūs varat iegūt Maršrutētāja objektu, kuram ir daži palīgapstrādes metodes jūsu lietošanai: ```php @@ -150,12 +150,12 @@ $router = Flight::router(); // maps all methods just like Flight::route() $router->map('/', function() { - echo 'hello world!'; + echo 'sveiks pasaule!'; }); // GET request $router->get('/users', function() { - echo 'users'; + echo 'lietotāji'; }); $router->post('/users', function() { /* code */}); $router->put('/users/update/@id', function() { /* code */}); @@ -163,7 +163,7 @@ $router->delete('/users/@id', function() { /* code */}); $router->patch('/users/@id', function() { /* code */}); ``` -### Regulārās izteiksmes (Regex) +### Regulārās Izteiksmes (Regex) Jūs varat izmantot regulārās izteiksmes savos maršrutos: ```php @@ -174,12 +174,12 @@ Flight::route('/user/[0-9]+', function () { Lai gan šī metode ir pieejama, ieteicams izmantot nosauktos parametrus vai nosauktos parametrus ar regulārajām izteiksmēm, jo tie ir lasāmāki un vieglāk uzturami. -### Nosauktie parametri -Jūs varat norādīt nosauktos parametrus savos maršrutos, kuri tiks nodoti jūsu atgriezeniskajai funkcijai. **Tas ir vairāk maršruta lasāmībai nekā jebkas cits. Lūdzu, skatiet sadaļu zemāk par svarīgu brīdinājumu.** +### Nosauktie Parametri +Jūs varat norādīt nosauktos parametrus savos maršrutos, kas tiks nodoti jūsu atgriezeniskajai funkcijai. **Tas ir vairāk maršruta lasāmībai nekā jebkas cits. Lūdzu, skatiet sadaļu zemāk par svarīgu brīdinājumu.** ```php Flight::route('/@name/@id', function (string $name, string $id) { - echo "hello, $name ($id)!"; + echo "sveiks, $name ($id)!"; }); ``` @@ -192,23 +192,23 @@ Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { }); ``` -> **Piezīme:** Saskaņošana regex grupām `()` ar pozīciju parametriem nav atbalstīta. Piem.: `:'\(` +> **Piezīme:** Saskaņošanas regex grupas `()` ar pozicionālajiem parametriem nav atbalstītas. Piem: `:'\(` -#### Svarīgs brīdinājums +#### Svarīgs Brīdinājums Lai gan iepriekšējā piemērā šķiet, ka `@name` ir tieši saistīts ar mainīgo `$name`, tas nav. Parametru secība atgriezeniskajā funkcijā nosaka, kas tam tiek nodots. Ja jūs mainītu parametru secību atgriezeniskajā funkcijā, mainīgie tiktu mainīti arī. Šeit ir piemērs: ```php Flight::route('/@name/@id', function (string $id, string $name) { - echo "hello, $name ($id)!"; + echo "sveiks, $name ($id)!"; }); ``` -Un ja jūs apmeklētu šādu URL: `/bob/123`, izvade būtu `hello, 123 (bob)!`. -_Lūdzu, esiet uzmanīgi_, kad iestatāt savus maršrutus un atgriezeniskās saites funkcijas! +Un ja jūs apmeklētu šādu URL: `/bob/123`, izvade būtu `sveiks, 123 (bob)!`. +_Lūdzu, esiet uzmanīgi_, kad iestatāt savus maršrutus un atgriezeniskās funkcijas! -### Neobligātie parametri -Jūs varat norādīt nosauktos parametrus, kas ir neobligāti saskaņošanai, iekļaujot segmentus iekavās. +### Neobligātie Parametri +Jūs varat norādīt nosauktos parametrus, kas ir neobligāti saskaņošanai, ietverot segmentus iekavās. ```php Flight::route( @@ -223,10 +223,10 @@ Flight::route( ); ``` -Jei neobligātie parametri, kas nav saskaņoti, tiks nodoti kā `NULL`. +Jei kuri neobligātie parametri netiek saskaņoti, tie tiks nodoti kā `NULL`. -### Mežģa maršrutizēšana -Saskaņošana tiek veikta tikai uz atsevišķiem URL segmentiem. Ja vēlaties saskaņot vairākus segmentus, varat izmantot `*` mežģi. +### Wildcard Maršrutizācija +Saskaņošana tiek veikta tikai uz atsevišķiem URL segmentiem. Ja vēlaties saskaņot vairākus segmentus, varat izmantot `*` wildcard. ```php Flight::route('/blog/*', function () { @@ -234,7 +234,7 @@ Flight::route('/blog/*', function () { }); ``` -Lai maršrutētu visus pieprasījumus uz vienu atgriezenisko saiti, varat izdarīt: +Lai maršrutētu visus pieprasījumus uz vienu atgriezenisko funkciju, varat darīt: ```php Flight::route('*', function () { @@ -242,7 +242,7 @@ Flight::route('*', function () { }); ``` -### 404 Nav atrasts apstrādātājs +### 404 Nav Atrasts Apstrādātājs Pēc noklusējuma, ja URL nevar atrast, Flight nosūtīs `HTTP 404 Not Found` atbildi, kas ir ļoti vienkārša un vienkārša. Ja vēlaties pielāgotu 404 atbildi, varat [kartēt](/learn/extending) savu `notFound` metodi: @@ -253,8 +253,8 @@ Flight::map('notFound', function() { // You could also use Flight::render() with a custom template. $output = <<My Custom 404 Not Found -

The page you have requested {$url} could not be found.

+

Mans Pielāgots 404 Nav Atrasts

+

Lapa, kuru jūs pieprasījāt {$url}, netika atrasta.

HTML; $this->response() @@ -265,9 +265,9 @@ Flight::map('notFound', function() { }); ``` -### Metodes nav atrasts apstrādātājs +### Metodes Nav Atrasts Apstrādātājs -Pēc noklusējuma, ja URL ir atrasts, bet metode nav atļauta, Flight nosūtīs `HTTP 405 Method Not Allowed` atbildi, kas ir ļoti vienkārša un vienkārša (Pi.: Method Not Allowed. Allowed Methods are: GET, POST). Tā arī iekļaus `Allow` galveni ar atļautajām metodēm tam URL. +Pēc noklusējuma, ja URL ir atrasts, bet metode nav atļauta, Flight nosūtīs `HTTP 405 Method Not Allowed` atbildi, kas ir ļoti vienkārša un vienkārša (Piem: Method Not Allowed. Allowed Methods are: GET, POST). Tā arī iekļaus `Allow` galveni ar atļautajām metodēm tam URL. Ja vēlaties pielāgotu 405 atbildi, varat [kartēt](/learn/extending) savu `methodNotFound` metodi: @@ -280,9 +280,9 @@ Flight::map('methodNotFound', function(Route $route) { // You could also use Flight::render() with a custom template. $output = <<My Custom 405 Method Not Allowed -

The method you have requested for {$url} is not allowed.

-

Allowed Methods are: {$methods}

+

Mans Pielāgots 405 Metode Nav Atļauta

+

Metode, kuru jūs pieprasījāt {$url}, nav atļauta.

+

Atļautās Metodes ir: {$methods}

HTML; $this->response() @@ -294,10 +294,10 @@ Flight::map('methodNotFound', function(Route $route) { }); ``` -## Papildu lietošana +## Papildu Lietošana -### Atkarību injekcija maršrutos -Ja vēlaties izmantot atkarību injekciju caur konteineru (PSR-11, PHP-DI, Dice utt.), vienīgais maršrutu veids, kur tas ir pieejams, ir vai nu tieši izveidojot objektu pats un izmantojot konteineru, lai izveidotu savu objektu, vai arī varat izmantot virknes, lai definētu klasi un metodi, ko izsaukt. Jūs varat doties uz [Atkarību injekcijas](/learn/dependency-injection-container) lapu, lai iegūtu vairāk informācijas. +### Atkarību Injekcija Maršrutos +Ja vēlaties izmantot atkarību injekciju caur konteineru (PSR-11, PHP-DI, Dice utt.), vienīgais maršrutu veids, kur tas ir pieejams, ir vai nu tieši izveidojot objektu pats un izmantojot konteineru, lai izveidotu jūsu objektu, vai arī varat izmantot virknes, lai definētu klasi un metodi, ko izsaukt. Jūs varat apmeklēt [Atkarību Injekcijas](/learn/dependency-injection-container) lapu vairāk informācijas. Šeit ir ātrs piemērs: @@ -316,7 +316,7 @@ class Greeting public function hello(int $id) { // do something with $this->pdoWrapper $name = $this->pdoWrapper->fetchField("SELECT name FROM users WHERE id = ?", [ $id ]); - echo "Hello, world! My name is {$name}!"; + echo "Sveiks, pasaule! Mans vārds ir {$name}!"; } } @@ -351,9 +351,9 @@ Flight::route('/hello/@id', 'Greeting::hello'); Flight::start(); ``` -### Izpildes nodošana nākamajam maršrutam -Novecojis -Jūs varat nodot izpildi nākamajam saskaņotajam maršrutam, atgriežot `true` no jūsu atgriezeniskās saites funkcijas. +### Izpildes Nodošana Nākamajam Maršrutam +Deprecated +Jūs varat nodot izpildi nākamajam saskanīgajam maršrutam, atgriežot `true` no jūsu atgriezeniskās funkcijas. ```php Flight::route('/user/@name', function (string $name) { @@ -369,10 +369,10 @@ Flight::route('/user/*', function () { }); ``` -Tagad ieteicams izmantot [vidutīni](/learn/middleware), lai apstrādātu sarežģītus gadījumus kā šis. +Tagad ieteicams izmantot [middleware](/learn/middleware), lai apstrādātu sarežģītus gadījumus kā šis. -### Maršruta aliasēšana -Piešķirot aliasu maršrutam, jūs varat vēlāk dinamiski izsaukt šo aliasu savā lietojumprogrammā, lai tas tiktu ģenerēts vēlāk jūsu kodā (piem.: saite HTML veidnē vai ģenerējot pāradresācijas URL). +### Maršruta Aliasēšana +Piešķirot aliasu maršrutam, jūs varat vēlāk dinamiski izsaukt šo aliasu savā lietojumprogrammā, lai tas tiktu ģenerēts vēlāk jūsu kodā (piem: saite HTML veidnē vai ģenerējot pāradresācijas URL). ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); @@ -393,7 +393,7 @@ class UserController { ``` -Tas ir īpaši noderīgi, ja jūsu URL gadās mainīties. Iepriekšējā piemērā, pieņemsim, ka lietotāji tika pārvietoti uz `/admin/users/@id` vietā. +Tas ir īpaši noderīgi, ja jūsu URL mainās. Iepriekšējā piemērā, pieņemsim, ka lietotāji tika pārvietoti uz `/admin/users/@id` vietā. Ar aliasēšanu vietā maršrutam, jums vairs nav jāmeklē visi vecie URL jūsu kodā un jāmaina tie, jo alias tagad atgriezīs `/admin/users/5`, kā piemērā iepriekš. Maršruta aliasēšana joprojām darbojas grupās: @@ -406,11 +406,11 @@ Flight::group('/users', function() { }); ``` -### Maršruta informācijas pārbaude -Ja vēlaties pārbaudīt saskaņoto maršruta informāciju, ir 2 veidi, kā to izdarīt: +### Maršruta Informācijas Pārbaude +Ja vēlaties pārbaudīt saskanīgo maršruta informāciju, ir 2 veidi, kā to izdarīt: 1. Jūs varat izmantot `executedRoute` īpašību uz `Flight::router()` objekta. -2. Jūs varat pieprasīt, lai maršruta objekts tiktu nodots jūsu atgriezeniskajai saitei, nododot `true` kā trešo parametru maršruta metodē. Maršruta objekts vienmēr būs pēdējais parametrs, kas nodots jūsu atgriezeniskajai funkcijai. +2. Jūs varat pieprasīt, lai maršruta objekts tiktu nodots jūsu atgriezeniskajai funkcijai, nododot `true` kā trešo parametru maršruta metodē. Maršruta objekts vienmēr būs pēdējais parametrs, kas nodots jūsu atgriezeniskajai funkcijai. #### `executedRoute` ```php @@ -440,9 +440,9 @@ Flight::route('/', function() { }); ``` -> **Piezīme:** `executedRoute` īpašība tiks iestatīta tikai pēc tam, kad maršruts ir izpildīts. Ja mēģināsiet piekļūt tai pirms maršruta izpildes, tā būs `NULL`. Jūs varat izmantot executedRoute arī [vidutīnos](/learn/middleware)! +> **Piezīme:** `executedRoute` īpašība tiks iestatīta tikai pēc tam, kad maršruts ir izpildīts. Ja mēģināsiet piekļūt tai pirms maršruta izpildes, tā būs `NULL`. Jūs varat izmantot executedRoute arī [middleware](/learn/middleware)! -#### Padojiet `true` maršruta definīcijā +#### Nodošana `true` maršruta definīcijā ```php Flight::route('/', function(\flight\net\Route $route) { // Array of HTTP methods matched against @@ -468,8 +468,8 @@ Flight::route('/', function(\flight\net\Route $route) { }, true);// <-- This true parameter is what makes that happen ``` -### Maršruta grupēšana un vidutīni -Var būt gadījumi, kad vēlaties grupēt saistītos maršrutus kopā (piemēram, `/api/v1`). +### Maršruta Grupēšana un Middleware +Var būt gadījumi, kad vēlaties grupēt saistītus maršrutus kopā (piemēram, `/api/v1`). Jūs varat to izdarīt, izmantojot `group` metodi: ```php @@ -484,7 +484,7 @@ Flight::group('/api/v1', function () { }); ``` -Jūs varat pat ligzdot grupu grupas: +Jūs pat varat ligzdot grupu grupas: ```php Flight::group('/api', function () { @@ -512,7 +512,7 @@ Flight::group('/api', function () { }); ``` -#### Grupēšana ar objekta kontekstu +#### Grupēšana ar Objekta Kontekstu Jūs joprojām varat izmantot maršruta grupēšanu ar `Engine` objektu šādā veidā: @@ -534,9 +534,9 @@ $app->group('/api/v1', function (Router $router) { > **Piezīme:** Šī ir ieteiktā metode maršrutu un grupu definēšanai ar `$router` objektu. -#### Grupēšana ar vidutīniem +#### Grupēšana ar Middleware -Jūs varat arī piešķirt vidutīnus grupai maršrutu: +Jūs varat arī piešķirt middleware grupai maršrutu: ```php Flight::group('/api/v1', function () { @@ -546,9 +546,9 @@ Flight::group('/api/v1', function () { }, [ MyAuthMiddleware::class ]); // or [ new MyAuthMiddleware() ] if you want to use an instance ``` -Skatiet vairāk detaļu [grupas vidutīnos](/learn/middleware#grouping-middleware) lapā. +Skatiet vairāk detaļu [grupas middleware](/learn/middleware#grouping-middleware) lapā. -### Resursu maršrutizēšana +### Resursu Maršrutizācija Jūs varat izveidot maršrutu kopu resursam, izmantojot `resource` metodi. Tas izveidos maršrutu kopu resursam, kas seko RESTful konvencijām. Lai izveidotu resursu, dariet šādu: @@ -608,16 +608,14 @@ class UsersController > **Piezīme**: Jūs varat skatīt jaunos pievienotos maršrutus ar `runway`, palaižot `php runway routes`. -#### Resursu maršrutu pielāgošana +#### Pielāgošana Resursu Maršrutiem Ir dažas opcijas resursu maršrutu konfigurēšanai. -##### Alias bāze +##### Alias Bāze -Jūs varat konfigurēt `aliasBase`. Pēc noklusējuma alias ir pēdējā URL norādītās daļa. -Piemēram `/users/` rezultētos ar `aliasBase` no `users`. Kad šie maršruti tiek izveidoti, -aliasi ir `users.index`, `users.create` utt. Ja vēlaties mainīt alias, iestatiet `aliasBase` -uz vērtību, ko vēlaties. +Jūs varat konfigurēt `aliasBase`. Pēc noklusējuma alias ir pēdējā URL daļa, kas norādīta. +Piemēram, `/users/` rezultēs `aliasBase` kā `users`. Kad šie maršruti ir izveidoti, alias ir `users.index`, `users.create` utt. Ja vēlaties mainīt alias, iestatiet `aliasBase` uz vēlamo vērtību. ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); @@ -625,7 +623,7 @@ Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); ##### Tikai un Izņemot -Jūs varat norādīt, kurus maršrutus vēlaties izveidot, izmantojot `only` un `except` opcijas. +Jūs varat arī norādīt, kurus maršrutus vēlaties izveidot, izmantojot `only` un `except` opcijas. ```php // Whitelist only these methods and blacklist the rest @@ -637,27 +635,27 @@ Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` -Šie ir pamatā baltā saraksta un melnā saraksta opcijas, lai jūs varētu norādīt, kurus maršrutus vēlaties izveidot. +Šie ir pamatā balstīti uz balto sarakstu un melno sarakstu opcijām, lai jūs varētu norādīt, kurus maršrutus vēlaties izveidot. -##### Vidutīni +##### Middleware -Jūs varat norādīt vidutīnus, kas jāizpilda katram no maršrutiem, ko izveido `resource` metode. +Jūs varat arī norādīt middleware, kas jāizpilda katram no maršrutiem, ko izveido `resource` metode. ```php Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]); ``` -### Strumēšanas atbildes +### Plūsmas Atbildes -Jūs tagad varat straumēt atbildes klientam, izmantojot `stream()` vai `streamWithHeaders()`. -Tas ir noderīgi lielu failu nosūtīšanai, ilgstošiem procesiem vai lielu atbilžu ģenerēšanai. -Strumēšanas maršruta apstrāde ir nedaudz atšķirīga no parasta maršruta. +Jūs tagad varat plūst atbildes klientam, izmantojot `stream()` vai `streamWithHeaders()`. +Tas ir noderīgi lielu failu nosūtīšanai, garām procesiem vai lielu atbilžu ģenerēšanai. +Maršruta plūsmošana tiek apstrādāta nedaudz savādāk nekā parasts maršruts. -> **Piezīme:** Strumēšanas atbildes ir pieejamas tikai tad, ja jums ir [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) iestatīts uz `false`. +> **Piezīme:** Plūsmas atbildes ir pieejamas tikai tad, ja jums ir iestatīts [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) kā `false`. -#### Strumēšana ar manuālām galvenēm +#### Plūsma ar Manuālām Galvenēm -Jūs varat straumēt atbildi klientam, izmantojot `stream()` metodi maršrutā. Ja dariet to, jums jāiestata visas galvenes ar roku, pirms izvadat kaut ko klientam. +Jūs varat plūst atbildi klientam, izmantojot `stream()` metodi uz maršruta. Ja dariet to, jums jāiestata visas galvenes manuāli pirms izvades kaut ko klientam. Tas tiek darīts ar `header()` php funkciju vai `Flight::response()->setRealHeader()` metodi. ```php @@ -694,9 +692,9 @@ Flight::route('/@filename', function($filename) { })->stream(); ``` -#### Strumēšana ar galvenēm +#### Plūsma ar Galvenēm -Jūs varat izmantot `streamWithHeaders()` metodi, lai iestatītu galvenes pirms sākat straumēt. +Jūs varat izmantot `streamWithHeaders()` metodi, lai iestatītu galvenes pirms plūsmošanas sākšanas. ```php Flight::route('/stream-users', function() { @@ -729,39 +727,39 @@ Flight::route('/stream-users', function() { ]); ``` -## Skatīt arī -- [Vidutīni](/learn/middleware) - Vidutīņu lietošana ar maršrutiem autentifikācijai, žurnālošanai utt. -- [Atkarību injekcija](/learn/dependency-injection-container) - Objektu izveides un vadības vienkāršošana maršrutos. -- [Kāpēc ietvars?](/learn/why-frameworks) - Ietvara izmantošanas priekšrocību saprašana, piemēram, Flight. -- [Paplašināšana](/learn/extending) - Kā paplašināt Flight ar savu funkcionalitāti, tostarp `notFound` metodi. +## Skatīt Arī +- [Middleware](/learn/middleware) - Middleware lietošana ar maršrutiem autentifikācijai, žurnālošanai utt. +- [Atkarību Injekcija](/learn/dependency-injection-container) - Objektu izveides un pārvaldības vienkāršošana maršrutos. +- [Kāpēc Ietvars?](/learn/why-frameworks) - Ietvara kā Flight izmantošanas priekšrocību saprašana. +- [Paplašināšana](/learn/extending) - Kā paplašināt Flight ar savu funkcionalitāti, ieskaitot `notFound` metodi. - [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - PHP funkcija regulāro izteiksmju saskaņošanai. ## Traucējummeklēšana -- Maršruta parametri tiek saskaņoti pēc secības, nevis pēc nosaukuma. Pārliecinieties, ka atgriezeniskās saites parametru secība atbilst maršruta definīcijai. -- `Flight::get()` lietošana nedefinē maršrutu; izmantojiet `Flight::route('GET /...')` maršrutizēšanai vai Maršrutētāja objekta kontekstu grupās (piem. `$router->get(...)`). +- Maršruta parametri tiek saskaņoti pēc secības, nevis pēc nosaukuma. Pārliecinieties, ka atgriezeniskās funkcijas parametru secība atbilst maršruta definīcijai. +- `Flight::get()` lietošana nedefinē maršrutu; izmantojiet `Flight::route('GET /...')` maršrutizācijai vai Router objekta kontekstu grupās (piem. `$router->get(...)`). - executedRoute īpašība tiek iestatīta tikai pēc maršruta izpildes; tā ir NULL pirms izpildes. -- Strumēšanai ir jāatspējo legacy Flight izvades buferizēšanas funkcionalitāte (`flight.v2.output_buffering = false`). -- Atkarību injekcijai atbalsta tikai noteiktas maršruta definīcijas konteineru balstītai instantiācijai. +- Plūsmošanai nepieciešama legacy Flight izvades buferizācijas funkcionalitāte, kas ir atspējota (`flight.v2.output_buffering = false`). +- Atkarību injekcijai tikai noteiktas maršruta definīcijas atbalsta konteineru balstītu instancēšanu. -### 404 Nav atrasts vai negaidīta maršruta uzvedība +### 404 Nav Atrasts vai Negaidīta Maršruta Uzvedība -Ja redzat 404 Nav atrasts kļūdu (bet esat pārliecināts uz savu dzīvību, ka tas tiešām ir tur un tas nav drukas kļūda), tas patiesībā varētu būt problēma ar jūsu atgriežamo vērtību maršruta galapunktā, nevis tikai to izvadi. Iemesls tam ir tīšs, bet var uzbrukt dažiem izstrādātājiem. +Ja redzat 404 Nav Atrasts kļūdu (bet jūs zvērāt uz savu dzīvi, ka tas tiešām ir tur un tas nav drukas kļūda), tas patiesībā varētu būt problēma ar vērtības atgriešanu jūsu maršruta galapunktā, nevis tikai to izsaukšanu. Iemesls tam ir tīms, bet var uzmest dažus izstrādātājus. ```php Flight::route('/hello', function(){ // This might cause a 404 Not Found error - return 'Hello World'; + return 'Sveiks Pasaule'; }); // What you probably want Flight::route('/hello', function(){ - echo 'Hello World'; + echo 'Sveiks Pasaule'; }); ``` -Iemesls tam ir īpašs mehānisms, kas iebūvēts maršrutētājā, kas apstrādā atgriezenisko izvadi kā signālu "doties uz nākamo maršrutu". -Jūs varat redzēt uzvedību, kas dokumentēta [Maršrutizēšanas](/learn/routing#passing) sadaļā. +Iemesls tam ir īpašs mehānisms, kas iebūvēts maršrutētājā, kas apstrādā atgriezenisko izvadi kā signālu "iet uz nākamo maršrutu". +Jūs varat redzēt uzvedību, kas dokumentēta [Maršrutizācijas](/learn/routing#passing) sadaļā. -## Izmaiņu žurnāls -- v3: Pievienota resursu maršrutizēšana, maršruta aliasēšana un straumēšanas atbalsts, maršruta grupas un vidutīnu atbalsts. -- v1: Liela daļa pamata funkciju ir pieejamas. \ No newline at end of file +## Izmaiņu Žurnāls +- v3: Pievienota resursu maršrutizācija, maršruta aliasēšana un plūsmas atbalsts, maršruta grupas un middleware atbalsts. +- v1: Liela daļa pamata funkciju pieejamas. \ No newline at end of file diff --git a/content/v3/pt/awesome-plugins/async.md b/content/v3/pt/awesome-plugins/async.md new file mode 100644 index 00000000..40b0b536 --- /dev/null +++ b/content/v3/pt/awesome-plugins/async.md @@ -0,0 +1,212 @@ +# Async + +Async é um pequeno pacote para o framework Flight que permite executar seus aplicativos Flight dentro de servidores e runtimes assíncronos como Swoole, AdapterMan, ReactPHP, Amp, RoadRunner, Workerman, etc. De fábrica, ele inclui adaptadores para Swoole e AdapterMan. + +O objetivo: desenvolver e depurar com PHP-FPM (ou o servidor integrado) e alternar para Swoole (ou outro driver assíncrono) para produção com mudanças mínimas. + +## Requisitos + +- PHP 7.4 ou superior +- Framework Flight 3.16.1 ou superior +- [Extensão Swoole](https://www.openswoole.com) + +## Instalação + +Instale via composer: + +```bash +composer require flightphp/async +``` + +Se você planeja executar com Swoole, instale a extensão: + +```bash +# usando pecl +pecl install swoole +# ou openswoole +pecl install openswoole + +# ou com um gerenciador de pacotes (exemplo Debian/Ubuntu) +sudo apt-get install php-swoole +``` + +## Exemplo rápido com Swoole + +Abaixo está uma configuração mínima que mostra como suportar tanto PHP-FPM (ou servidor integrado) quanto Swoole usando o mesmo código base. + +Arquivos que você precisará no seu projeto: + +- index.php +- swoole_server.php +- SwooleServerDriver.php + +### index.php + +Este arquivo é um simples interruptor que força o aplicativo a executar no modo PHP para desenvolvimento. + +```php +// index.php +route('/', function() use ($app) { + $app->json(['hello' => 'world']); +}); + +if (!defined('NOT_SWOOLE')) { + // Require a classe SwooleServerDriver quando executando no modo Swoole. + require_once __DIR__ . '/SwooleServerDriver.php'; + + Swoole\Runtime::enableCoroutine(); + $Swoole_Server = new SwooleServerDriver('127.0.0.1', 9501, $app); + $Swoole_Server->start(); +} else { + $app->start(); +} +``` + +### SwooleServerDriver.php + +Um driver conciso que mostra como conectar requisições Swoole ao Flight usando o AsyncBridge e os adaptadores Swoole. + +```php +// SwooleServerDriver.php +Swoole = new SwooleServer($host, $port); + $this->app = $app; + + $this->setDefault(); + $this->bindWorkerEvents(); + $this->bindHttpEvent(); + } + + protected function setDefault() { + $this->Swoole->set([ + 'daemonize' => false, + 'dispatch_mode' => 1, + 'max_request' => 8000, + 'open_tcp_nodelay' => true, + 'reload_async' => true, + 'max_wait_time' => 60, + 'enable_reuse_port' => true, + 'enable_coroutine' => true, + 'http_compression' => false, + 'enable_static_handler' => true, + 'document_root' => __DIR__, + 'static_handler_locations' => ['/css', '/js', '/images', '/.well-known'], + 'buffer_output_size' => 4 * 1024 * 1024, + 'worker_num' => 4, + ]); + + $app = $this->app; + $app->map('stop', function (?int $code = null) use ($app) { + if ($code !== null) { + $app->response()->status($code); + } + }); + } + + protected function bindHttpEvent() { + $app = $this->app; + $AsyncBridge = new AsyncBridge($app); + + $this->Swoole->on('Start', function(SwooleServer $server) { + echo "Servidor HTTP Swoole iniciado em http://127.0.0.1:9501\n"; + }); + + $this->Swoole->on('Request', function (SwooleRequest $request, SwooleResponse $response) use ($AsyncBridge) { + $SwooleAsyncRequest = new SwooleAsyncRequest($request); + $SwooleAsyncResponse = new SwooleAsyncResponse($response); + + $AsyncBridge->processRequest($SwooleAsyncRequest, $SwooleAsyncResponse); + + $response->end(); + gc_collect_cycles(); + }); + } + + protected function bindWorkerEvents() { + $createPools = function() { + // criar pools de conexão específicos do worker aqui + }; + $closePools = function() { + // fechar pools / limpeza aqui + }; + $this->Swoole->on('WorkerStart', $createPools); + $this->Swoole->on('WorkerStop', $closePools); + $this->Swoole->on('WorkerError', $closePools); + } + + public function start() { + $this->Swoole->start(); + } +} +``` + +## Executando o servidor + +- Desenvolvimento (servidor integrado PHP / PHP-FPM): + - php -S localhost:8000 (ou adicione -t public/ se seu index estiver em public/) +- Produção (Swoole): + - php swoole_server.php + +Dica: Para produção, use um proxy reverso (Nginx) na frente do Swoole para lidar com TLS, arquivos estáticos e balanceamento de carga. + +## Notas de configuração + +O driver Swoole expõe várias opções de configuração: +- worker_num: número de processos de worker +- max_request: requisições por worker antes do reinício +- enable_coroutine: usar corrotinas para concorrência +- buffer_output_size: tamanho do buffer de saída + +Ajuste esses valores para se adequar aos recursos do seu host e padrões de tráfego. + +## Tratamento de erros + +AsyncBridge traduz erros do Flight em respostas HTTP adequadas. Você também pode adicionar tratamento de erros em nível de rota: + +```php +$app->route('/*', function() use ($app) { + try { + // lógica da rota + } catch (Exception $e) { + $app->response()->status(500); + $app->json(['error' => $e->getMessage()]); + } +}); +``` + +## AdapterMan e outros runtimes + +[AdapterMan](https://github.com/joanhey/adapterman) é suportado como um adaptador de runtime alternativo. O pacote é projetado para ser adaptável — adicionar ou usar outros adaptadores geralmente segue o mesmo padrão: converter a requisição/resposta do servidor em requisição/resposta do Flight via AsyncBridge e os adaptadores específicos do runtime. \ No newline at end of file diff --git a/content/v3/pt/awesome-plugins/awesome_plugins.md b/content/v3/pt/awesome-plugins/awesome_plugins.md index e8f167c9..13d2305d 100644 --- a/content/v3/pt/awesome-plugins/awesome_plugins.md +++ b/content/v3/pt/awesome-plugins/awesome_plugins.md @@ -12,78 +12,84 @@ A documentação de API é crucial para qualquer API. Ela ajuda os desenvolvedor ## Monitoramento de Desempenho de Aplicação (APM) O Monitoramento de Desempenho de Aplicação (APM) é crucial para qualquer aplicação. Ele ajuda você a entender como sua aplicação está se saindo e onde estão os gargalos. Existem vários ferramentas APM que podem ser usadas com Flight. -- oficial [flightphp/apm](/awesome-plugins/apm) - Flight APM é uma biblioteca APM simples que pode ser usada para monitorar suas aplicações Flight. Pode ser usada para monitorar o desempenho da sua aplicação e ajudá-lo a identificar gargalos. +- oficial [flightphp/apm](/awesome-plugins/apm) - Flight APM é uma biblioteca APM simples que pode ser usada para monitorar suas aplicações Flight. Ela pode ser usada para monitorar o desempenho da sua aplicação e ajudá-lo a identificar gargalos. + +## Async + +Flight já é um framework rápido, mas adicionar um motor turbo nele torna tudo mais divertido (e desafiador)! + +- [flightphp/async](/awesome-plugins/async) - Biblioteca Async oficial do Flight. Esta biblioteca é uma forma simples de adicionar processamento assíncrono à sua aplicação. Ela usa Swoole/Openswoole sob o capô para fornecer uma forma simples e eficaz de executar tarefas de forma assíncrona. ## Autorização/Permissões Autorização e Permissões são cruciais para qualquer aplicação que requer controles para quem pode acessar o quê. -- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca oficial de Permissões Flight. Esta biblioteca é uma maneira simples de adicionar permissões em nível de usuário e aplicação à sua aplicação. +- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca de Permissões oficial do Flight. Esta biblioteca é uma forma simples de adicionar permissões em nível de usuário e aplicação à sua aplicação. ## Cache -Cache é uma ótima maneira de acelerar sua aplicação. Existem várias bibliotecas de cache que podem ser usadas com Flight. +Cache é uma ótima forma de acelerar sua aplicação. Existem várias bibliotecas de cache que podem ser usadas com Flight. -- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Classe de cache PHP leve, simples e standalone em arquivo +- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Classe leve, simples e independente de cache em arquivo PHP ## CLI -Aplicações CLI são uma ótima maneira de interagir com sua aplicação. Você pode usá-las para gerar controladores, exibir todas as rotas e mais. +Aplicações CLI são uma ótima forma de interagir com sua aplicação. Você pode usá-las para gerar controladores, exibir todas as rotas e mais. - oficial [flightphp/runway](/awesome-plugins/runway) - Runway é uma aplicação CLI que ajuda você a gerenciar suas aplicações Flight. ## Cookies -Cookies são uma ótima maneira de armazenar pequenos pedaços de dados no lado do cliente. Eles podem ser usados para armazenar preferências de usuário, configurações de aplicação e mais. +Cookies são uma ótima forma de armazenar pequenos pedaços de dados no lado do cliente. Eles podem ser usados para armazenar preferências de usuário, configurações de aplicação e mais. -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie é uma biblioteca PHP que fornece uma maneira simples e eficaz de gerenciar cookies. +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie é uma biblioteca PHP que fornece uma forma simples e eficaz de gerenciar cookies. ## Depuração Depuração é crucial quando você está desenvolvendo em seu ambiente local. Existem alguns plugins que podem elevar sua experiência de depuração. -- [tracy/tracy](/awesome-plugins/tracy) - Esta é uma manipuladora de erros completa que pode ser usada com Flight. Ela tem vários painéis que podem ajudá-lo a depurar sua aplicação. Também é muito fácil de estender e adicionar seus próprios painéis. -- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usada com o manipulador de erros [Tracy](/awesome-plugins/tracy), este plugin adiciona alguns painéis extras para ajudar com a depuração especificamente para projetos Flight. +- [tracy/tracy](/awesome-plugins/tracy) - Esta é um manipulador de erros completo que pode ser usado com Flight. Ele tem vários painéis que podem ajudá-lo a depurar sua aplicação. Também é muito fácil de estender e adicionar seus próprios painéis. +- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado com o manipulador de erros [Tracy](/awesome-plugins/tracy), este plugin adiciona alguns painéis extras para ajudar com depuração especificamente para projetos Flight. ## Bancos de Dados Bancos de dados são o núcleo da maioria das aplicações. É assim que você armazena e recupera dados. Algumas bibliotecas de banco de dados são simplesmente wrappers para escrever consultas e algumas são ORMs completos. -- oficial [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper oficial PDO Flight que faz parte do núcleo. Este é um wrapper simples para ajudar a simplificar o processo de escrever consultas e executá-las. Não é um ORM. +- oficial [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO oficial do Flight que faz parte do núcleo. Este é um wrapper simples para ajudar a simplificar o processo de escrever consultas e executá-las. Não é um ORM. - oficial [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord oficial do Flight. Ótima biblioteca pequena para recuperar e armazenar dados facilmente em seu banco de dados. -- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para rastrear todas as alterações de banco de dados para seu projeto. +- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para manter o controle de todas as alterações de banco de dados para seu projeto. ## Criptografia Criptografia é crucial para qualquer aplicação que armazena dados sensíveis. Criptografar e descriptografar os dados não é terrivelmente difícil, mas armazenar corretamente a chave de criptografia [pode](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [ser](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difícil](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). A coisa mais importante é nunca armazenar sua chave de criptografia em um diretório público ou commitá-la em seu repositório de código. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Esta é uma biblioteca que pode ser usada para criptografar e descriptografar dados. Começar é bastante simples para começar a criptografar e descriptografar dados. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - Esta é uma biblioteca que pode ser usada para criptografar e descriptografar dados. Começar a usar é bastante simples para começar a criptografar e descriptografar dados. ## Fila de Tarefas -Filas de tarefas são realmente úteis para processar tarefas de forma assíncrona. Isso pode ser enviando e-mails, processando imagens ou qualquer coisa que não precise ser feita em tempo real. +Filas de tarefas são realmente úteis para processar tarefas de forma assíncrona. Isso pode ser enviar e-mails, processar imagens ou qualquer coisa que não precise ser feita em tempo real. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue é uma biblioteca que pode ser usada para processar tarefas de forma assíncrona. Pode ser usada com beanstalkd, MySQL/MariaDB, SQLite e PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue é uma biblioteca que pode ser usada para processar tarefas de forma assíncrona. Ela pode ser usada com beanstalkd, MySQL/MariaDB, SQLite e PostgreSQL. ## Sessão Sessões não são realmente úteis para APIs, mas para construir uma aplicação web, sessões podem ser cruciais para manter o estado e informações de login. -- oficial [flightphp/session](/awesome-plugins/session) - Biblioteca oficial de Sessão Flight. Esta é uma biblioteca de sessão simples que pode ser usada para armazenar e recuperar dados de sessão. Usa o manipulador de sessão integrado do PHP. +- oficial [flightphp/session](/awesome-plugins/session) - Biblioteca de Sessão oficial do Flight. Esta é uma biblioteca de sessão simples que pode ser usada para armazenar e recuperar dados de sessão. Ela usa o manipulador de sessão integrado do PHP. - [Ghostff/Session](/awesome-plugins/ghost-session) - Gerenciador de Sessão PHP (não bloqueante, flash, segmento, criptografia de sessão). Usa PHP open_ssl para criptografia/descriptografia opcional de dados de sessão. -## Modelagem +## Templating -Modelagem é o núcleo de qualquer aplicação web com uma UI. Existem vários motores de modelagem que podem ser usados com Flight. +Templating é o núcleo de qualquer aplicação web com uma UI. Existem vários motores de templating que podem ser usados com Flight. -- depreciado [flightphp/core View](/learn#views) - Este é um motor de modelagem muito básico que faz parte do núcleo. Não é recomendado usá-lo se você tiver mais de algumas páginas em seu projeto. -- [latte/latte](/awesome-plugins/latte) - Latte é um motor de modelagem completo que é muito fácil de usar e se sente mais próximo da sintaxe PHP do que Twig ou Smarty. Também é muito fácil de estender e adicionar seus próprios filtros e funções. +- deprecado [flightphp/core View](/learn#views) - Este é um motor de templating muito básico que faz parte do núcleo. Não é recomendado usá-lo se você tiver mais de algumas páginas em seu projeto. +- [latte/latte](/awesome-plugins/latte) - Latte é um motor de templating completo que é muito fácil de usar e se sente mais próximo da sintaxe PHP do que Twig ou Smarty. Também é muito fácil de estender e adicionar seus próprios filtros e funções. ## Integração com WordPress Quer usar Flight em seu projeto WordPress? Há um plugin prático para isso! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Este plugin WordPress permite que você execute Flight ao lado do WordPress. É perfeito para adicionar APIs personalizadas, microsserviços ou até aplicativos completos ao seu site WordPress usando o framework Flight. Super útil se você quiser o melhor dos dois mundos! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Este plugin do WordPress permite que você execute Flight ao lado do WordPress. É perfeito para adicionar APIs personalizadas, microsserviços ou até aplicativos completos ao seu site WordPress usando o framework Flight. Super útil se você quiser o melhor dos dois mundos! ## Contribuição diff --git a/content/v3/pt/examples.md b/content/v3/pt/examples.md index b0002f04..052b71e9 100644 --- a/content/v3/pt/examples.md +++ b/content/v3/pt/examples.md @@ -1,36 +1,37 @@ # Precisa de um início rápido? -Você tem duas opções para começar um novo projeto Flight: +Você tem duas opções para começar com um novo projeto Flight: -- [Boilerplate de Esqueleto Completo](https://github.com/flightphp/skeleton): Um exemplo mais completo com controladores e visões. -- [Boilerplate de Esqueleto de Arquivo Único](https://github.com/flightphp/skeleton-simple): Um arquivo único que inclui tudo o que você precisa para rodar seu aplicativo em um único arquivo simples. +- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Um exemplo mais completo com controladores e visualizações. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Um único arquivo que inclui tudo o que você precisa para executar seu app em um único arquivo simples. Exemplos contribuídos pela comunidade: -- [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP com diretórios Laravel, com ferramentas PHP + Ações GH -- [fleact](https://github.com/flightphp/fleact) - Um kit inicial do FlightPHP com integração ReactJS. -- [flastro](https://github.com/flightphp/flastro) - Um kit inicial do FlightPHP com integração Astro. -- [velt](https://github.com/flightphp/velt) - Velt é um modelo de inicialização rápido e fácil em Svelte com um backend FlightPHP. +- [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP com diretórios Laravel, com ferramentas PHP + GH Actions +- [fleact](https://github.com/flightphp/fleact) - Um kit inicial FlightPHP com integração ReactJS. +- [flastro](https://github.com/flightphp/flastro) - Um kit inicial FlightPHP com integração Astro. +- [velt](https://github.com/flightphp/velt) - Velt é um template inicial rápido e fácil para Svelte com backend FlightPHP. -## Precisa de Inspiração? +## Precisa de Alguma Inspiração? -Embora esses não sejam oficialmente patrocinados pela equipe Flight, eles podem lhe dar ideias sobre como estruturar seus próprios projetos que são construídos com o Flight! +Embora estes não sejam oficialmente patrocinados pela Equipe Flight, eles podem dar ideias sobre como estruturar seus próprios projetos construídos com Flight! +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental é uma aplicação web de aluguel de carros de página única, amigável para mobile, construída com PHP (FlightPHP), JavaScript e MySQL. Ela suporta registro de usuários, navegação e reserva de carros, enquanto administradores podem gerenciar carros, usuários e reservas. O app possui uma API REST, autenticação JWT e um design responsivo para uma experiência de aluguel moderna. - [Decay](https://github.com/boxybird/decay) - Flight v3 com HTMX e SleekDB tudo sobre zumbis! ([Demo](https://decay.andrewrhyand.com)) -- [Exemplo de Blog Flight](https://github.com/n0nag0n/flightphp-blog) - Flight v3 com Middleware, Controladores, Active Record e Latte. -- [API RESTful CRUD de Flight](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Projeto simples de API CRUD usando o framework Flight, que fornece uma estrutura básica para novos usuários configurarem rapidamente um aplicativo PHP com operações CRUD e conectividade de banco de dados. O projeto demonstra como usar o Flight para desenvolvimento de API RESTful, tornando-se uma ferramenta de aprendizado ideal para iniciantes e um kit inicial útil para desenvolvedores mais experientes. -- [Sistema de Gestão Escolar Flight](https://github.com/krmu/FlightPHP_School) - Flight v3 -- [Paste Bin com Comentários](https://github.com/n0nag0n/commie2) - Flight v3 -- [Aplicativo Básico de Esqueleto](https://github.com/markhughes/flight-skeleton) -- [Exemplo de Wiki](https://github.com/Skayo/FlightWiki) -- [A Aplicação do Framework PHP IT-Innovator](https://github.com/itinnovator/myphp-app) -- [LittleEducationalCMS (Espanhol)](https://github.com/casgin/LittleEducationalCMS) -- [API de Páginas Amarelas Italiana](https://github.com/chiccomagnus/PGAPI) -- [Sistema de Gerenciamento de Conteúdo Genérico (com....muito pouca documentação)](https://github.com/recepuncu/cms) -- [Um pequeno framework php baseado no Flight e medoo.](https://github.com/ycrao/tinyme) -- [Exemplo de Aplicativo MVC](https://github.com/paddypei/Flight-MVC) -- [Produção pronta para produção](https://github.com/madcoda9000/SecStore) - Estrutura de autenticação pronta para produção que poupa semanas de desenvolvimento. Oferece segurança de nível empresarial: 2FA/TOTP, integração com LDAP, SSO do Azure, limitação de taxa inteligente, impressão digital de sessão, proteção contra força bruta, painel de análise de segurança, registo de auditoria abrangente e controlo de acesso granular baseado em funções. +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 com Middleware, Controladores, Active Record e Latte. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Projeto simples de API CRUD usando o framework Flight, que fornece uma estrutura básica para novos usuários configurarem rapidamente uma aplicação PHP com operações CRUD e conectividade de banco de dados. O projeto demonstra como usar Flight para desenvolvimento de API RESTful, tornando-o uma ferramenta de aprendizado ideal para iniciantes e um kit inicial útil para desenvolvedores mais experientes. +- [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 +- [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 +- [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) +- [Example Wiki](https://github.com/Skayo/FlightWiki) +- [The IT-Innovator PHP Framework Application](https://github.com/itinnovator/myphp-app) +- [LittleEducationalCMS (Spanish)](https://github.com/casgin/LittleEducationalCMS) +- [Italian Yellow Pages API](https://github.com/chiccomagnus/PGAPI) +- [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) +- [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) +- [Example MVC Application](https://github.com/paddypei/Flight-MVC) +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework de autenticação pronto para produção que economiza semanas de desenvolvimento. Recursos de segurança de nível empresarial: 2FA/TOTP, integração LDAP, SSO Azure, limitação de taxa inteligente, fingerprinting de sessão, proteção contra força bruta, painel de análise de segurança, logging de auditoria abrangente e controle de acesso baseado em papéis granular. ## Quer Compartilhar Seu Próprio Exemplo? -Se você tem um projeto que gostaria de compartilhar, por favor envie um pull request para adicioná-lo a esta lista! \ No newline at end of file +Se você tiver um projeto que deseja compartilhar, por favor, envie um pull request para adicioná-lo a esta lista! \ No newline at end of file diff --git a/content/v3/pt/learn/requests.md b/content/v3/pt/learn/requests.md index 0274c59f..76b4eb9f 100644 --- a/content/v3/pt/learn/requests.md +++ b/content/v3/pt/learn/requests.md @@ -9,15 +9,15 @@ acessado fazendo: $request = Flight::request(); ``` -## Entendendo +## Compreendendo -Requisições HTTP são um dos aspectos principais a serem compreendidos sobre o ciclo de vida HTTP. Um usuário realiza uma ação em um navegador web ou cliente HTTP, e eles enviam uma série de cabeçalhos, corpo, URL, etc. para o seu projeto. Você pode capturar esses cabeçalhos (a linguagem do navegador, o tipo de compressão que eles podem lidar, o agente do usuário, etc.) e capturar o corpo e a URL que é enviada para a sua aplicação Flight. Essas requisições são essenciais para que o seu app entenda o que fazer em seguida. +As requisições HTTP são um dos aspectos principais a entender sobre o ciclo de vida HTTP. Um usuário realiza uma ação em um navegador web ou em um cliente HTTP, e eles enviam uma série de cabeçalhos, corpo, URL, etc. para o seu projeto. Você pode capturar esses cabeçalhos (a linguagem do navegador, que tipo de compressão eles podem lidar, o agente do usuário, etc.) e capturar o corpo e a URL que são enviados para a sua aplicação Flight. Essas requisições são essenciais para que o seu app entenda o que fazer em seguida. ## Uso Básico -PHP possui várias super globais incluindo `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` e `$_COOKIE`. Flight abstrai essas em coleções práticas [Collections](/learn/collections). Você pode acessar as propriedades `query`, `data`, `cookies` e `files` como arrays ou objetos. +PHP possui vários super globais, incluindo `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` e `$_COOKIE`. Flight abstrai esses em coleções práticas [Collections](/learn/collections). Você pode acessar as propriedades `query`, `data`, `cookies` e `files` como arrays ou objetos. -> **Nota:** É **ALTAMENTE** desencorajado usar essas super globais no seu projeto e elas devem ser referenciadas através do objeto `request()`. +> **Nota:** É **ALTAMENTE** desaconselhável usar esses super globais no seu projeto e eles devem ser referenciados através do objeto `request()`. > **Nota:** Não há abstração disponível para `$_ENV`. @@ -121,7 +121,7 @@ Flight::route('POST /upload', function(){ }); ``` -> **Nota de Segurança:** Sempre valide e sanitize a entrada do usuário, especialmente ao lidar com uploads de arquivos. Sempre valide o tipo de extensões que você permitirá ser enviadas, mas você também deve validar os "magic bytes" do arquivo para garantir que é realmente o tipo de arquivo que o usuário afirma ser. Há [artigos](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [e](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [bibliotecas](https://github.com/RikudouSage/MimeTypeDetector) disponíveis para ajudar com isso. +> **Nota de Segurança:** Sempre valide e sanitize a entrada do usuário, especialmente ao lidar com uploads de arquivos. Sempre valide o tipo de extensões que você permitirá ser enviado, mas você também deve validar os "magic bytes" do arquivo para garantir que é realmente o tipo de arquivo que o usuário afirma que é. Há [artigos](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [e](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [bibliotecas](https://github.com/RikudouSage/MimeTypeDetector) disponíveis para ajudar com isso. ### Corpo da Requisição @@ -138,7 +138,7 @@ Flight::route('POST /users/xml', function(){ ### Corpo JSON Se você receber uma requisição com o tipo de conteúdo `application/json` e os dados de exemplo `{"id": 123}` -ele estará disponível da propriedade `data`: +ele estará disponível na propriedade `data`: ```php $id = Flight::request()->data->id; @@ -173,9 +173,9 @@ $method = Flight::request()->getMethod(); **Nota:** O método `getMethod()` primeiro puxa o método de `$_SERVER['REQUEST_METHOD']`, então ele pode ser sobrescrito por `$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` se existir ou `$_REQUEST['_method']` se existir. -## Propriedades do Objeto de Requisição +## Propriedades do Objeto Request -O objeto de requisição fornece as seguintes propriedades: +O objeto request fornece as seguintes propriedades: - **body** - O corpo raw da requisição HTTP - **url** - A URL sendo requisitada @@ -188,19 +188,19 @@ O objeto de requisição fornece as seguintes propriedades: - **user_agent** - Informações do navegador - **type** - O tipo de conteúdo - **length** - O comprimento do conteúdo -- **query** - Parâmetros da string de consulta -- **data** - Dados post ou dados JSON +- **query** - Parâmetros da string de query +- **data** - Dados POST ou dados JSON - **cookies** - Dados de cookie - **files** - Arquivos enviados - **secure** - Se a conexão é segura -- **accept** - Parâmetros de aceitação HTTP +- **accept** - Parâmetros HTTP accept - **proxy_ip** - Endereço IP proxy do cliente. Escaneia o array `$_SERVER` por `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` nessa ordem. - **host** - O nome do host da requisição - **servername** - O SERVER_NAME de `$_SERVER` ## Métodos Auxiliares -Há alguns métodos auxiliares para montar partes de uma URL ou lidar com certos cabeçalhos. +Há alguns métodos auxiliares para juntar partes de uma URL, ou lidar com certos cabeçalhos. ### URL Completa @@ -219,19 +219,19 @@ Você pode acessar a URL base usando o método `getBaseUrl()`: // http://example.com/path/to/something/cool?query=yes+thanks $url = Flight::request()->getBaseUrl(); // https://example.com -// Note, sem barra final. +// Note, sem barra no final. ``` -## Análise de Consulta +## Análise de Query -Você pode passar uma URL para o método `parseQuery()` para analisar a string de consulta em um array associativo: +Você pode passar uma URL para o método `parseQuery()` para analisar a string de query em um array associativo: ```php $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` -## Negociar Tipos de Aceitação de Conteúdo +## Negociar Tipos de Conteúdo Aceitos _v3.17.2_ @@ -244,11 +244,11 @@ Você pode usar o método `negotiateContentType()` para determinar o melhor tipo $availableTypes = ['application/json', 'application/xml']; $typeToServe = Flight::request()->negotiateContentType($availableTypes); if ($typeToServe === 'application/json') { - // Servir resposta JSON + // Sirva resposta JSON } elseif ($typeToServe === 'application/xml') { - // Servir resposta XML + // Sirva resposta XML } else { - // Padrão para algo mais ou lançar um erro + // Padrão para algo mais ou lance um erro } ``` @@ -266,5 +266,5 @@ if ($typeToServe === 'application/json') { ## Changelog - v3.17.2 - Adicionado negotiateContentType() -- v3.12.0 - Adicionada capacidade de lidar com uploads de arquivos através do objeto de requisição. +- v3.12.0 - Adicionada capacidade de lidar com uploads de arquivos através do objeto request. - v1.0 - Lançamento inicial. \ No newline at end of file diff --git a/content/v3/pt/learn/routing.md b/content/v3/pt/learn/routing.md index b9adda56..6ff9ce1c 100644 --- a/content/v3/pt/learn/routing.md +++ b/content/v3/pt/learn/routing.md @@ -4,14 +4,14 @@ O roteamento no Flight PHP mapeia padrões de URL para funções de callback ou métodos de classe, permitindo o tratamento rápido e simples de requisições. Ele é projetado para sobrecarga mínima, uso amigável para iniciantes e extensibilidade sem dependências externas. ## Entendendo -O roteamento é o mecanismo central que conecta requisições HTTP à lógica da sua aplicação no Flight. Ao definir rotas, você especifica como diferentes URLs acionam código específico, seja através de funções, métodos de classe ou ações de controlador. O sistema de roteamento do Flight é flexível, suportando padrões básicos, parâmetros nomeados, expressões regulares e recursos avançados como injeção de dependência e roteamento resource-oriented. Essa abordagem mantém seu código organizado e fácil de manter, enquanto permanece rápido e simples para iniciantes e extensível para usuários avançados. +O roteamento é o mecanismo principal que conecta requisições HTTP à lógica da sua aplicação no Flight. Ao definir rotas, você especifica como diferentes URLs acionam código específico, seja por meio de funções, métodos de classe ou ações de controlador. O sistema de roteamento do Flight é flexível, suportando padrões básicos, parâmetros nomeados, expressões regulares e recursos avançados como injeção de dependência e roteamento de recursos. Essa abordagem mantém seu código organizado e fácil de manter, enquanto permanece rápido e simples para iniciantes e extensível para usuários avançados. -> **Nota:** Quer entender mais sobre roteamento? Confira a página ["por que um framework?](/learn/why-frameworks) para uma explicação mais aprofundada. +> **Nota:** Quer entender mais sobre roteamento? Confira a página ["por que um framework?](/learn/why-frameworks)" para uma explicação mais aprofundada. ## Uso Básico ### Definindo uma Rota Simples -O roteamento básico no Flight é feito ao combinar um padrão de URL com uma função de callback ou um array de uma classe e método. +O roteamento básico no Flight é feito combinando um padrão de URL com uma função de callback ou um array de classe e método. ```php Flight::route('/', function(){ @@ -79,9 +79,9 @@ Flight::route('/', [ $greeting, 'hello' ]); > **Nota:** Por padrão, quando um controlador é chamado dentro do framework, a classe `flight\Engine` é sempre injetada, a menos que você especifique através de um [contêiner de injeção de dependência](/learn/dependency-injection-container) -### Roteamento Específico de Método +### Roteamento Específico para Métodos -Por padrão, os padrões de rota são combinados contra todos os métodos de requisição. Você pode responder a métodos específicos colocando um identificador antes da URL. +Por padrão, os padrões de rota são combinados com todos os métodos de requisição. Você pode responder a métodos específicos colocando um identificador antes da URL. ```php Flight::route('GET /', function () { @@ -92,8 +92,8 @@ Flight::route('POST /', function () { echo 'I received a POST request.'; }); -// You cannot use Flight::get() for routes as that is a method -// to get variables, not create a route. +// Você não pode usar Flight::get() para rotas, pois esse é um método +// para obter variáveis, não para criar uma rota. Flight::post('/', function() { /* code */ }); Flight::patch('/', function() { /* code */ }); Flight::put('/', function() { /* code */ }); @@ -114,27 +114,27 @@ O Flight fornece tratamento integrado para requisições HTTP `HEAD` e `OPTIONS` #### Requisições HEAD -- **Requisições HEAD** são tratadas exatamente como requisições `GET`, mas o Flight remove automaticamente o corpo da resposta antes de enviá-lo ao cliente. +- **Requisições HEAD** são tratadas como requisições `GET`, mas o Flight remove automaticamente o corpo da resposta antes de enviá-lo para o cliente. - Isso significa que você pode definir uma rota para `GET`, e requisições HEAD para a mesma URL retornarão apenas cabeçalhos (sem conteúdo), conforme esperado pelos padrões HTTP. ```php Flight::route('GET /info', function() { echo 'This is some info!'; }); -// A HEAD request to /info will return the same headers, but no body. +// Uma requisição HEAD para /info retornará os mesmos cabeçalhos, mas sem corpo. ``` #### Requisições OPTIONS Requisições `OPTIONS` são tratadas automaticamente pelo Flight para qualquer rota definida. -- Quando uma requisição OPTIONS é recebida, o Flight responde com um status `204 No Content` e um cabeçalho `Allow` listando todos os métodos HTTP suportados para essa rota. -- Você não precisa definir uma rota separada para OPTIONS, a menos que queira um comportamento personalizado ou modificar a resposta. +- Quando uma requisição OPTIONS é recebida, o Flight responde com um status `204 No Content` e um cabeçalho `Allow` listando todos os métodos HTTP suportados para aquela rota. +- Você não precisa definir uma rota separada para OPTIONS. ```php -// For a route defined as: +// Para uma rota definida como: Flight::route('GET|POST /users', function() { /* ... */ }); -// An OPTIONS request to /users will respond with: +// Uma requisição OPTIONS para /users responderá com: // // Status: 204 No Content // Allow: GET, POST, HEAD, OPTIONS @@ -148,12 +148,12 @@ Adicionalmente, você pode obter o objeto Router, que tem alguns métodos auxili $router = Flight::router(); -// maps all methods just like Flight::route() +// mapeia todos os métodos como Flight::route() $router->map('/', function() { echo 'hello world!'; }); -// GET request +// requisição GET $router->get('/users', function() { echo 'users'; }); @@ -168,14 +168,14 @@ Você pode usar expressões regulares em suas rotas: ```php Flight::route('/user/[0-9]+', function () { - // This will match /user/1234 + // Isso combinará com /user/1234 }); ``` Embora esse método esteja disponível, é recomendado usar parâmetros nomeados, ou parâmetros nomeados com expressões regulares, pois eles são mais legíveis e fáceis de manter. ### Parâmetros Nomeados -Você pode especificar parâmetros nomeados em suas rotas, que serão passados para sua função de callback. **Isso é mais para a legibilidade da rota do que qualquer outra coisa. Por favor, veja a seção abaixo sobre uma ressalva importante.** +Você pode especificar parâmetros nomeados em suas rotas, que serão passados para sua função de callback. **Isso é mais para a legibilidade da rota do que qualquer outra coisa. Veja a seção abaixo sobre uma ressalva importante.** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -187,8 +187,8 @@ Você também pode incluir expressões regulares com seus parâmetros nomeados u ```php Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { - // This will match /bob/123 - // But will not match /bob/12345 + // Isso combinará com /bob/123 + // Mas não combinará com /bob/12345 }); ``` @@ -196,7 +196,7 @@ Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { #### Ressalva Importante -Embora no exemplo acima pareça que `@name` está diretamente ligado à variável `$name`, não é assim. A ordem dos parâmetros na função de callback é o que determina o que é passado para ela. Se você inverter a ordem dos parâmetros na função de callback, as variáveis também serão invertidas. Aqui está um exemplo: +Embora no exemplo acima pareça que `@name` está diretamente ligado à variável `$name`, não é o caso. A ordem dos parâmetros na função de callback é o que determina o que é passado para ela. Se você inverter a ordem dos parâmetros na função de callback, as variáveis também serão invertidas. Aqui está um exemplo: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -205,7 +205,7 @@ Flight::route('/@name/@id', function (string $id, string $name) { ``` E se você acessar a seguinte URL: `/bob/123`, a saída seria `hello, 123 (bob)!`. -_Por favor, tenha cuidado_ ao configurar suas rotas e funções de callback! +_Seja cuidadoso_ ao configurar suas rotas e funções de callback! ### Parâmetros Opcionais Você pode especificar parâmetros nomeados que são opcionais para combinação envolvendo segmentos em parênteses. @@ -214,7 +214,7 @@ Você pode especificar parâmetros nomeados que são opcionais para combinação Flight::route( '/blog(/@year(/@month(/@day)))', function(?string $year, ?string $month, ?string $day) { - // This will match the following URLS: + // Isso combinará com as seguintes URLs: // /blog/2012/12/10 // /blog/2012/12 // /blog/2012 @@ -225,12 +225,12 @@ Flight::route( Quaisquer parâmetros opcionais que não forem combinados serão passados como `NULL`. -### Roteamento Wildcard -A combinação é feita apenas em segmentos individuais de URL. Se você quiser combinar múltiplos segmentos, pode usar o wildcard `*`. +### Roteamento com Curinga +A combinação é feita apenas em segmentos individuais de URL. Se você quiser combinar múltiplos segmentos, pode usar o curinga `*`. ```php Flight::route('/blog/*', function () { - // This will match /blog/2000/02/01 + // Isso combinará com /blog/2000/02/01 }); ``` @@ -238,20 +238,20 @@ Para rotear todas as requisições para um único callback, você pode fazer: ```php Flight::route('*', function () { - // Do something + // Faça algo }); ``` ### Manipulador de 404 Não Encontrado -Por padrão, se uma URL não puder ser encontrada, o Flight enviará uma resposta `HTTP 404 Not Found` que é muito simples e simples. +Por padrão, se uma URL não puder ser encontrada, o Flight enviará uma resposta `HTTP 404 Not Found` que é muito simples e básica. Se você quiser uma resposta 404 mais personalizada, pode [mapear](/learn/extending) seu próprio método `notFound`: ```php Flight::map('notFound', function() { $url = Flight::request()->url; - // You could also use Flight::render() with a custom template. + // Você também poderia usar Flight::render() com um template personalizado. $output = <<My Custom 404 Not Found

The page you have requested {$url} could not be found.

@@ -267,7 +267,7 @@ Flight::map('notFound', function() { ### Manipulador de Método Não Encontrado -Por padrão, se uma URL for encontrada, mas o método não for permitido, o Flight enviará uma resposta `HTTP 405 Method Not Allowed` que é muito simples e simples (Ex: Method Not Allowed. Allowed Methods are: GET, POST). Ele também incluirá um cabeçalho `Allow` com os métodos permitidos para essa URL. +Por padrão, se uma URL for encontrada, mas o método não for permitido, o Flight enviará uma resposta `HTTP 405 Method Not Allowed` que é muito simples e básica (Ex: Method Not Allowed. Allowed Methods are: GET, POST). Ele também incluirá um cabeçalho `Allow` com os métodos permitidos para aquela URL. Se você quiser uma resposta 405 mais personalizada, pode [mapear](/learn/extending) seu próprio método `methodNotFound`: @@ -278,7 +278,7 @@ Flight::map('methodNotFound', function(Route $route) { $url = Flight::request()->url; $methods = implode(', ', $route->methods); - // You could also use Flight::render() with a custom template. + // Você também poderia usar Flight::render() com um template personalizado. $output = <<My Custom 405 Method Not Allowed

The method you have requested for {$url} is not allowed.

@@ -314,7 +314,7 @@ class Greeting } public function hello(int $id) { - // do something with $this->pdoWrapper + // faça algo com $this->pdoWrapper $name = $this->pdoWrapper->fetchField("SELECT name FROM users WHERE id = ?", [ $id ]); echo "Hello, world! My name is {$name}!"; } @@ -322,11 +322,11 @@ class Greeting // index.php -// Setup the container with whatever params you need -// See the Dependency Injection page for more information on PSR-11 +// Configure o contêiner com quaisquer parâmetros que você precisar +// Veja a página de Injeção de Dependência para mais informações sobre PSR-11 $dice = new \Dice\Dice(); -// Don't forget to reassign the variable with '$dice = '!!!!! +// Não esqueça de reatribuir a variável com '$dice = '!!!!! $dice = $dice->addRule('flight\database\PdoWrapper', [ 'shared' => true, 'constructParams' => [ @@ -336,57 +336,57 @@ $dice = $dice->addRule('flight\database\PdoWrapper', [ ] ]); -// Register the container handler +// Registre o manipulador do contêiner Flight::registerContainerHandler(function($class, $params) use ($dice) { return $dice->create($class, $params); }); -// Routes like normal +// Rotas como normal Flight::route('/hello/@id', [ 'Greeting', 'hello' ]); -// or +// ou Flight::route('/hello/@id', 'Greeting->hello'); -// or +// ou Flight::route('/hello/@id', 'Greeting::hello'); Flight::start(); ``` -### Passando Execução para a Próxima Rota -Deprecated -Você pode passar a execução para a próxima rota que combine retornando `true` da sua função de callback. +### Passando a Execução para a Próxima Rota +Depreciado +Você pode passar a execução para a próxima rota combinante retornando `true` da sua função de callback. ```php Flight::route('/user/@name', function (string $name) { - // Check some condition + // Verifique alguma condição if ($name !== "Bob") { - // Continue to next route + // Continue para a próxima rota return true; } }); Flight::route('/user/*', function () { - // This will get called + // Isso será chamado }); ``` Agora é recomendado usar [middleware](/learn/middleware) para lidar com casos de uso complexos como este. -### Apelidos de Rota -Ao atribuir um apelido a uma rota, você pode chamar esse apelido dinamicamente em sua aplicação para ser gerado mais tarde no seu código (ex: um link em um template HTML, ou gerando uma URL de redirecionamento). +### Aliasing de Rotas +Ao atribuir um alias a uma rota, você pode chamar esse alias dinamicamente em sua aplicação para ser gerado mais tarde no seu código (ex: um link em um template HTML, ou gerando uma URL de redirecionamento). ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); -// or +// ou Flight::route('/users/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view'); -// later in code somewhere +// mais tarde no código em algum lugar class UserController { public function update() { - // code to save user... - $id = $user['id']; // 5 for example + // código para salvar usuário... + $id = $user['id']; // 5 por exemplo - $redirectUrl = Flight::getUrl('user_view', [ 'id' => $id ]); // will return '/users/5' + $redirectUrl = Flight::getUrl('user_view', [ 'id' => $id ]); // retornará '/users/5' Flight::redirect($redirectUrl); } } @@ -394,92 +394,92 @@ class UserController { ``` Isso é especialmente útil se sua URL acontecer de mudar. No exemplo acima, digamos que users foi movido para `/admin/users/@id` em vez disso. -Com apelidos em vigor para a rota, você não precisa mais encontrar todas as URLs antigas no seu código e alterá-las porque o apelido agora retornará `/admin/users/5` como no exemplo acima. +Com o aliasing no lugar para a rota, você não precisa mais encontrar todas as URLs antigas no seu código e alterá-las porque o alias agora retornará `/admin/users/5` como no exemplo acima. -Apelidos de rota ainda funcionam em grupos também: +O aliasing de rotas ainda funciona em grupos também: ```php Flight::group('/users', function() { Flight::route('/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); - // or + // ou Flight::route('/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view'); }); ``` ### Inspecionando Informações de Rota -Se você quiser inspecionar as informações da rota combinada, há 2 maneiras de fazer isso: +Se você quiser inspecionar as informações da rota combinante, há 2 maneiras de fazer isso: 1. Você pode usar uma propriedade `executedRoute` no objeto `Flight::router()`. -2. Você pode solicitar que o objeto da rota seja passado para seu callback passando `true` como o terceiro parâmetro no método de rota. O objeto da rota sempre será o último parâmetro passado para sua função de callback. +2. Você pode solicitar que o objeto de rota seja passado para seu callback passando `true` como o terceiro parâmetro no método de rota. O objeto de rota sempre será o último parâmetro passado para sua função de callback. #### `executedRoute` ```php Flight::route('/', function() { $route = Flight::router()->executedRoute; - // Do something with $route - // Array of HTTP methods matched against + // Faça algo com $route + // Array de métodos HTTP combinados $route->methods; - // Array of named parameters + // Array de parâmetros nomeados $route->params; - // Matching regular expression + // Expressão regular combinante $route->regex; - // Contains the contents of any '*' used in the URL pattern + // Contém o conteúdo de qualquer '*' usado no padrão de URL $route->splat; - // Shows the url path....if you really need it + // Mostra o caminho da url....se você realmente precisar $route->pattern; - // Shows what middleware is assigned to this + // Mostra o middleware atribuído a isso $route->middleware; - // Shows the alias assigned to this route + // Mostra o alias atribuído a esta rota $route->alias; }); ``` -> **Nota:** A propriedade `executedRoute` só será definida após uma rota ter sido executada. Se você tentar acessá-la antes de uma rota ter sido executada, ela será `NULL`. Você também pode usar executedRoute em [middleware](/learn/middleware) também! +> **Nota:** A propriedade `executedRoute` só será definida após uma rota ter sido executada. Se você tentar acessá-la antes de uma rota ter sido executada, ela será `NULL`. Você também pode usar executedRoute em [middleware](/learn/middleware)! #### Passar `true` na definição de rota ```php Flight::route('/', function(\flight\net\Route $route) { - // Array of HTTP methods matched against + // Array de métodos HTTP combinados $route->methods; - // Array of named parameters + // Array de parâmetros nomeados $route->params; - // Matching regular expression + // Expressão regular combinante $route->regex; - // Contains the contents of any '*' used in the URL pattern + // Contém o conteúdo de qualquer '*' usado no padrão de URL $route->splat; - // Shows the url path....if you really need it + // Mostra o caminho da url....se você realmente precisar $route->pattern; - // Shows what middleware is assigned to this + // Mostra o middleware atribuído a isso $route->middleware; - // Shows the alias assigned to this route + // Mostra o alias atribuído a esta rota $route->alias; -}, true);// <-- This true parameter is what makes that happen +}, true);// <-- Este parâmetro true é o que faz isso acontecer ``` ### Agrupamento de Rotas e Middleware -Pode haver momentos em que você queira agrupar rotas relacionadas juntas (como `/api/v1`). +Pode haver vezes em que você queira agrupar rotas relacionadas juntas (como `/api/v1`). Você pode fazer isso usando o método `group`: ```php Flight::group('/api/v1', function () { Flight::route('/users', function () { - // Matches /api/v1/users + // Combina com /api/v1/users }); Flight::route('/posts', function () { - // Matches /api/v1/posts + // Combina com /api/v1/posts }); }); ``` @@ -489,24 +489,24 @@ Você pode até aninhar grupos de grupos: ```php Flight::group('/api', function () { Flight::group('/v1', function () { - // Flight::get() gets variables, it doesn't set a route! See object context below + // Flight::get() obtém variáveis, não define uma rota! Veja o contexto de objeto abaixo Flight::route('GET /users', function () { - // Matches GET /api/v1/users + // Combina com GET /api/v1/users }); Flight::post('/posts', function () { - // Matches POST /api/v1/posts + // Combina com POST /api/v1/posts }); Flight::put('/posts/1', function () { - // Matches PUT /api/v1/posts + // Combina com PUT /api/v1/posts }); }); Flight::group('/v2', function () { - // Flight::get() gets variables, it doesn't set a route! See object context below + // Flight::get() obtém variáveis, não define uma rota! Veja o contexto de objeto abaixo Flight::route('GET /users', function () { - // Matches GET /api/v2/users + // Combina com GET /api/v2/users }); }); }); @@ -521,13 +521,13 @@ $app = Flight::app(); $app->group('/api/v1', function (Router $router) { - // user the $router variable + // use a variável $router $router->get('/users', function () { - // Matches GET /api/v1/users + // Combina com GET /api/v1/users }); $router->post('/posts', function () { - // Matches POST /api/v1/posts + // Combina com POST /api/v1/posts }); }); ``` @@ -541,9 +541,9 @@ Você também pode atribuir middleware a um grupo de rotas: ```php Flight::group('/api/v1', function () { Flight::route('/users', function () { - // Matches /api/v1/users + // Combina com /api/v1/users }); -}, [ MyAuthMiddleware::class ]); // or [ new MyAuthMiddleware() ] if you want to use an instance +}, [ MyAuthMiddleware::class ]); // ou [ new MyAuthMiddleware() ] se você quiser usar uma instância ``` Veja mais detalhes na página [middleware de grupo](/learn/middleware#grouping-middleware). @@ -612,10 +612,12 @@ class UsersController Há algumas opções para configurar as rotas de recursos. -##### Base de Apelido +##### Base de Alias -Você pode configurar o `aliasBase`. Por padrão, o apelido é a última parte da URL especificada. -Por exemplo, `/users/` resultaria em um `aliasBase` de `users`. Quando essas rotas são criadas, os apelidos são `users.index`, `users.create`, etc. Se você quiser alterar o apelido, defina o `aliasBase` para o valor que deseja. +Você pode configurar o `aliasBase`. Por padrão, o alias é a última parte da URL especificada. +Por exemplo, `/users/` resultaria em um `aliasBase` de `users`. Quando essas rotas são criadas, +os aliases são `users.index`, `users.create`, etc. Se você quiser alterar o alias, defina o `aliasBase` +para o valor que deseja. ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); @@ -626,16 +628,16 @@ Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); Você também pode especificar quais rotas deseja criar usando as opções `only` e `except`. ```php -// Whitelist only these methods and blacklist the rest +// Lista branca apenas desses métodos e lista negra do resto Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' ] ]); ``` ```php -// Blacklist only these methods and whitelist the rest +// Lista negra apenas desses métodos e lista branca do resto Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` -Essas são basicamente opções de whitelisting e blacklisting para que você possa especificar quais rotas deseja criar. +Essas são basicamente opções de lista branca e lista negra para que você possa especificar quais rotas deseja criar. ##### Middleware @@ -651,7 +653,7 @@ Agora você pode transmitir respostas para o cliente usando `stream()` ou `strea Isso é útil para enviar arquivos grandes, processos de longa duração ou gerar respostas grandes. Transmitir uma rota é tratada um pouco diferente de uma rota regular. -> **Nota:** Respostas em streaming só estão disponíveis se você tiver [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) definido como `false`. +> **Nota:** Respostas em streaming estão disponíveis apenas se você tiver [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) definido como `false`. #### Stream com Cabeçalhos Manuais @@ -664,15 +666,15 @@ Flight::route('/@filename', function($filename) { $response = Flight::response(); - // obviously you would sanitize the path and whatnot. + // obviamente você sanitizaria o caminho e tal. $fileNameSafe = basename($filename); - // If you have additional headers to set here after the route has executed - // you must define them before anything is echoed out. - // They must all be a raw call to the header() function or - // a call to Flight::response()->setRealHeader() + // Se você tiver cabeçalhos adicionais para definir aqui após a rota ter sido executada + // você deve defini-los antes de qualquer coisa ser ecoada. + // Eles devem ser uma chamada raw para a função header() ou + // uma chamada para Flight::response()->setRealHeader() header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); - // or + // ou $response->setRealHeader('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); $filePath = '/some/path/to/files/'.$fileNameSafe; @@ -681,15 +683,15 @@ Flight::route('/@filename', function($filename) { Flight::halt(404, 'File not found'); } - // manually set the content length if you'd like + // defina manualmente o comprimento do conteúdo se quiser header('Content-Length: '.filesize($filePath)); - // or + // ou $response->setRealHeader('Content-Length: '.filesize($filePath)); - // Stream the file to the client as it's read + // Transmita o arquivo para o cliente conforme ele é lido readfile($filePath); -// This is the magic line here +// Esta é a linha mágica aqui })->stream(); ``` @@ -700,10 +702,10 @@ Você também pode usar o método `streamWithHeaders()` para definir os cabeçal ```php Flight::route('/stream-users', function() { - // you can add any additional headers you want here - // you just must use header() or Flight::response()->setRealHeader() + // você pode adicionar quaisquer cabeçalhos adicionais que quiser aqui + // você só deve usar header() ou Flight::response()->setRealHeader() - // however you pull your data, just as an example... + // no entanto, como você puxa seus dados, apenas como exemplo... $users_stmt = Flight::db()->query("SELECT id, first_name, last_name FROM users"); echo '{'; @@ -714,16 +716,16 @@ Flight::route('/stream-users', function() { echo ','; } - // This is required to send the data to the client + // Isso é necessário para enviar os dados para o cliente ob_flush(); } echo '}'; -// This is how you'll set the headers before you start streaming. +// É assim que você definirá os cabeçalhos antes de começar a transmitir. })->streamWithHeaders([ 'Content-Type' => 'application/json', 'Content-Disposition' => 'attachment; filename="users.json"', - // optional status code, defaults to 200 + // código de status opcional, padrão para 200 'status' => 200 ]); ``` @@ -738,21 +740,21 @@ Flight::route('/stream-users', function() { ## Solução de Problemas - Parâmetros de rota são combinados por ordem, não por nome. Certifique-se de que a ordem dos parâmetros do callback corresponda à definição da rota. - Usar `Flight::get()` não define uma rota; use `Flight::route('GET /...')` para roteamento ou o contexto do objeto Router em grupos (ex: `$router->get(...)`). -- A propriedade executedRoute só é definida após uma rota ser executada; ela é NULL antes da execução. -- Streaming requer que a funcionalidade de buffering de saída legada do Flight esteja desabilitada (`flight.v2.output_buffering = false`). +- A propriedade executedRoute só é definida após uma rota executar; ela é NULL antes da execução. +- Streaming requer que a funcionalidade de buffer de saída legada do Flight esteja desabilitada (`flight.v2.output_buffering = false`). - Para injeção de dependência, apenas certas definições de rota suportam instanciação baseada em contêiner. ### 404 Não Encontrado ou Comportamento Inesperado de Rota -Se você estiver vendo um erro 404 Não Encontrado (mas você jura pela sua vida que ele realmente está lá e não é um erro de digitação), isso na verdade pode ser um problema com você retornando um valor no seu endpoint de rota em vez de apenas ecoá-lo. A razão para isso é intencional, mas pode surpreender alguns desenvolvedores. +Se você estiver vendo um erro 404 Não Encontrado (mas você jura pela sua vida que ele está realmente lá e não é um erro de digitação), isso na verdade pode ser um problema com você retornando um valor no endpoint da sua rota em vez de apenas ecoá-lo. A razão para isso é intencional, mas pode surpreender alguns desenvolvedores. ```php Flight::route('/hello', function(){ - // This might cause a 404 Not Found error + // Isso pode causar um erro 404 Não Encontrado return 'Hello World'; }); -// What you probably want +// O que você provavelmente quer Flight::route('/hello', function(){ echo 'Hello World'; }); @@ -762,5 +764,5 @@ A razão para isso é por causa de um mecanismo especial incorporado no roteador Você pode ver o comportamento documentado na seção [Roteamento](/learn/routing#passing). ## Changelog -- v3: Adicionado roteamento de recursos, apelidos de rota e suporte a streaming, grupos de rota e suporte a middleware. +- v3: Adicionado roteamento de recursos, aliasing de rotas e suporte a streaming, grupos de rotas e suporte a middleware. - v1: A vasta maioria dos recursos básicos disponíveis. \ No newline at end of file diff --git a/content/v3/ru/awesome-plugins/async.md b/content/v3/ru/awesome-plugins/async.md new file mode 100644 index 00000000..90d8ac79 --- /dev/null +++ b/content/v3/ru/awesome-plugins/async.md @@ -0,0 +1,212 @@ +# Async + +Async — это небольшой пакет для фреймворка Flight, который позволяет запускать приложения Flight внутри асинхронных серверов и рантаймов, таких как Swoole, AdapterMan, ReactPHP, Amp, RoadRunner, Workerman и т.д. Из коробки он включает адаптеры для Swoole и AdapterMan. + +Цель: разрабатывать и отлаживать с PHP-FPM (или встроенным сервером) и переключаться на Swoole (или другой асинхронный драйвер) для продакшена с минимальными изменениями. + +## Требования + +- PHP 7.4 или выше +- Фреймворк Flight 3.16.1 или выше +- [Расширение Swoole](https://www.openswoole.com) + +## Установка + +Установите через composer: + +```bash +composer require flightphp/async +``` + +Если вы планируете запускать с Swoole, установите расширение: + +```bash +# используя pecl +pecl install swoole +# или openswoole +pecl install openswoole + +# или с помощью менеджера пакетов (пример для Debian/Ubuntu) +sudo apt-get install php-swoole +``` + +## Быстрый пример Swoole + +Ниже приведена минимальная настройка, которая показывает, как поддерживать как PHP-FPM (или встроенный сервер), так и Swoole, используя один и тот же код. + +Файлы, которые вам понадобятся в проекте: + +- index.php +- swoole_server.php +- SwooleServerDriver.php + +### index.php + +Этот файл представляет собой простой переключатель, который заставляет приложение работать в режиме PHP для разработки. + +```php +// index.php +route('/', function() use ($app) { + $app->json(['hello' => 'world']); +}); + +if (!defined('NOT_SWOOLE')) { + // Require the SwooleServerDriver class when running in Swoole mode. + require_once __DIR__ . '/SwooleServerDriver.php'; + + Swoole\Runtime::enableCoroutine(); + $Swoole_Server = new SwooleServerDriver('127.0.0.1', 9501, $app); + $Swoole_Server->start(); +} else { + $app->start(); +} +``` + +### SwooleServerDriver.php + +Краткий драйвер, показывающий, как связывать запросы Swoole с Flight с использованием AsyncBridge и адаптеров Swoole. + +```php +// SwooleServerDriver.php +Swoole = new SwooleServer($host, $port); + $this->app = $app; + + $this->setDefault(); + $this->bindWorkerEvents(); + $this->bindHttpEvent(); + } + + protected function setDefault() { + $this->Swoole->set([ + 'daemonize' => false, + 'dispatch_mode' => 1, + 'max_request' => 8000, + 'open_tcp_nodelay' => true, + 'reload_async' => true, + 'max_wait_time' => 60, + 'enable_reuse_port' => true, + 'enable_coroutine' => true, + 'http_compression' => false, + 'enable_static_handler' => true, + 'document_root' => __DIR__, + 'static_handler_locations' => ['/css', '/js', '/images', '/.well-known'], + 'buffer_output_size' => 4 * 1024 * 1024, + 'worker_num' => 4, + ]); + + $app = $this->app; + $app->map('stop', function (?int $code = null) use ($app) { + if ($code !== null) { + $app->response()->status($code); + } + }); + } + + protected function bindHttpEvent() { + $app = $this->app; + $AsyncBridge = new AsyncBridge($app); + + $this->Swoole->on('Start', function(SwooleServer $server) { + echo "Swoole http server is started at http://127.0.0.1:9501\n"; + }); + + $this->Swoole->on('Request', function (SwooleRequest $request, SwooleResponse $response) use ($AsyncBridge) { + $SwooleAsyncRequest = new SwooleAsyncRequest($request); + $SwooleAsyncResponse = new SwooleAsyncResponse($response); + + $AsyncBridge->processRequest($SwooleAsyncRequest, $SwooleAsyncResponse); + + $response->end(); + gc_collect_cycles(); + }); + } + + protected function bindWorkerEvents() { + $createPools = function() { + // create worker-specific connection pools here + }; + $closePools = function() { + // close pools / cleanup here + }; + $this->Swoole->on('WorkerStart', $createPools); + $this->Swoole->on('WorkerStop', $closePools); + $this->Swoole->on('WorkerError', $closePools); + } + + public function start() { + $this->Swoole->start(); + } +} +``` + +## Запуск сервера + +- Разработка (встроенный сервер PHP / PHP-FPM): + - php -S localhost:8000 (или добавьте -t public/, если ваш index находится в public/) +- Продакшен (Swoole): + - php swoole_server.php + +Совет: Для продакшена используйте обратный прокси (Nginx) перед Swoole для обработки TLS, статических файлов и балансировки нагрузки. + +## Заметки по конфигурации + +Драйвер Swoole предоставляет несколько опций конфигурации: +- worker_num: количество рабочих процессов +- max_request: запросов на работника перед перезапуском +- enable_coroutine: использование корутин для параллелизма +- buffer_output_size: размер буфера вывода + +Настройте эти параметры в соответствии с ресурсами хоста и шаблонами трафика. + +## Обработка ошибок + +AsyncBridge преобразует ошибки Flight в правильные HTTP-ответы. Вы также можете добавить обработку ошибок на уровне маршрута: + +```php +$app->route('/*', function() use ($app) { + try { + // route logic + } catch (Exception $e) { + $app->response()->status(500); + $app->json(['error' => $e->getMessage()]); + } +}); +``` + +## AdapterMan и другие рантаймы + +[AdapterMan](https://github.com/joanhey/adapterman) поддерживается как альтернативный адаптер рантайма. Пакет спроектирован для адаптивности — добавление или использование других адаптеров в целом следует тому же шаблону: преобразование запроса/ответа сервера в запрос/ответ Flight через AsyncBridge и адаптеры, специфичные для рантайма. \ No newline at end of file diff --git a/content/v3/ru/awesome-plugins/awesome_plugins.md b/content/v3/ru/awesome-plugins/awesome_plugins.md index a499b1cf..79487883 100644 --- a/content/v3/ru/awesome-plugins/awesome_plugins.md +++ b/content/v3/ru/awesome-plugins/awesome_plugins.md @@ -1,22 +1,28 @@ -# Крутая плагины +# Крутые плагины Flight невероятно расширяем. Существует множество плагинов, которые можно использовать для добавления функциональности в ваше приложение Flight. Некоторые из них официально поддерживаются командой Flight, а другие — это микро/лайт-библиотеки, чтобы помочь вам начать. ## Документация API -Документация API крайне важна для любого API. Она помогает разработчикам понять, как взаимодействовать с вашим API и чего ожидать в ответ. Есть несколько инструментов, доступных для помощи в генерации документации API для ваших проектов Flight. +Документация API крайне важна для любого API. Она помогает разработчикам понять, как взаимодействовать с вашим API и чего ожидать в ответ. Есть несколько инструментов, которые помогут вам генерировать документацию API для ваших проектов Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Пост в блоге, написанный Daniel Schreiber, о том, как использовать спецификацию OpenAPI с FlightPHP для создания вашего API с использованием подхода API first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI — отличный инструмент для помощи в генерации документации API для ваших проектов Flight. Его очень легко использовать, и его можно настроить под ваши нужды. Это PHP-библиотека для помощи в генерации документации Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Пост в блоге, написанный Даниэлем Шрайбером, о том, как использовать спецификацию OpenAPI с FlightPHP для построения вашего API с использованием подхода "API first". +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI — отличный инструмент для генерации документации API для ваших проектов Flight. Его очень легко использовать, и его можно настроить под ваши нужды. Это PHP-библиотека, которая поможет вам генерировать документацию Swagger. ## Мониторинг производительности приложений (APM) -Мониторинг производительности приложений (APM) крайне важен для любого приложения. Он помогает понять, как работает ваше приложение и где узкие места. Существует множество инструментов APM, которые можно использовать с Flight. -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM — простая библиотека APM, которую можно использовать для мониторинга приложений Flight. Ее можно использовать для мониторинга производительности вашего приложения и помощи в выявлении узких мест. +Мониторинг производительности приложений (APM) крайне важен для любого приложения. Он помогает понять, как работает ваше приложение и где находятся узкие места. Существует множество инструментов APM, которые можно использовать с Flight. +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM — это простая библиотека APM, которая может использоваться для мониторинга приложений Flight. Она может использоваться для мониторинга производительности вашего приложения и помощи в выявлении узких мест. + +## Асинхронность + +Flight уже является быстрым фреймворком, но добавление к нему турбо-двигателя делает всё ещё веселее (и сложнее)! + +- [flightphp/async](/awesome-plugins/async) - Официальная библиотека Flight Async. Эта библиотека — простой способ добавить асинхронную обработку в ваше приложение. Она использует Swoole/Openswoole под капотом, чтобы предоставить простой и эффективный способ запуска задач асинхронно. ## Авторизация/Разрешения -Авторизация и разрешения крайне важны для любого приложения, которое требует контроля за тем, кто может получить доступ к чему. +Авторизация и разрешения крайне важны для любого приложения, которое требует контроля над тем, кто может получить доступ к чему. - official [flightphp/permissions](/awesome-plugins/permissions) - Официальная библиотека Flight Permissions. Эта библиотека — простой способ добавить разрешения на уровне пользователя и приложения в ваше приложение. @@ -24,53 +30,53 @@ Flight невероятно расширяем. Существует множе Кэширование — отличный способ ускорить ваше приложение. Существует множество библиотек кэширования, которые можно использовать с Flight. -- official [flightphp/cache](/awesome-plugins/php-file-cache) - Легкий, простой и автономный PHP-класс для кэширования в файле +- official [flightphp/cache](/awesome-plugins/php-file-cache) - Лёгкий, простой и автономный класс PHP для кэширования в файлах ## CLI -CLI-приложения — отличный способ взаимодействовать с вашим приложением. Их можно использовать для генерации контроллеров, отображения всех маршрутов и многого другого. +CLI-приложения — отличный способ взаимодействовать с вашим приложением. Вы можете использовать их для генерации контроллеров, отображения всех маршрутов и многого другого. -- official [flightphp/runway](/awesome-plugins/runway) - Runway — CLI-приложение, которое помогает управлять приложениями Flight. +- official [flightphp/runway](/awesome-plugins/runway) - Runway — это CLI-приложение, которое помогает управлять вашими приложениями Flight. ## Куки -Куки — отличный способ хранить небольшие объемы данных на стороне клиента. Их можно использовать для хранения предпочтений пользователя, настроек приложения и многого другого. +Куки — отличный способ хранить небольшие объёмы данных на стороне клиента. Их можно использовать для хранения предпочтений пользователя, настроек приложения и многого другого. -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie — PHP-библиотека, которая предоставляет простой и эффективный способ управления куки. +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie — это PHP-библиотека, которая предоставляет простой и эффективный способ управления куки. ## Отладка -Отладка крайне важна при разработке в локальной среде. Существует несколько плагинов, которые могут улучшить ваш опыт отладки. +Отладка крайне важна при разработке в локальной среде. Есть несколько плагинов, которые могут улучшить ваш опыт отладки. -- [tracy/tracy](/awesome-plugins/tracy) - Это полнофункциональный обработчик ошибок, который можно использовать с Flight. У него есть несколько панелей, которые могут помочь вам отлаживать ваше приложение. Его также очень легко расширять и добавлять собственные панели. +- [tracy/tracy](/awesome-plugins/tracy) - Это полнофункциональный обработчик ошибок, который можно использовать с Flight. У него есть несколько панелей, которые помогут вам отлаживать ваше приложение. Его также очень легко расширять и добавлять собственные панели. - official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Используется с обработчиком ошибок [Tracy](/awesome-plugins/tracy), этот плагин добавляет несколько дополнительных панелей для помощи в отладке специально для проектов Flight. ## Базы данных -Базы данных — основа большинства приложений. Это способ хранения и извлечения данных. Некоторые библиотеки баз данных — просто обертки для написания запросов, а некоторые — полноценные ORM. +Базы данных — основа большинства приложений. Это способ хранения и извлечения данных. Некоторые библиотеки баз данных — просто обёртки для написания запросов, а некоторые — полноценные ORM. -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Официальная обертка Flight PDO, которая является частью ядра. Это простая обертка, чтобы упростить процесс написания запросов и их выполнения. Это не ORM. -- official [flightphp/active-record](/awesome-plugins/active-record) - Официальный ORM/Mapper Flight ActiveRecord. Отличная небольшая библиотека для легкого извлечения и хранения данных в вашей базе данных. -- [byjg/php-migration](/awesome-plugins/migrations) - Плагин для отслеживания всех изменений базы данных для вашего проекта. +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Официальная обёртка Flight PDO, которая является частью ядра. Это простая обёртка, которая помогает упростить процесс написания и выполнения запросов. Это не ORM. +- official [flightphp/active-record](/awesome-plugins/active-record) - Официальный ORM/Mapper Flight ActiveRecord. Отличная маленькая библиотека для лёгкого извлечения и хранения данных в вашей базе данных. +- [byjg/php-migration](/awesome-plugins/migrations) - Плагин для отслеживания всех изменений базы данных в вашем проекте. ## Шифрование -Шифрование крайне важно для любого приложения, которое хранит конфиденциальные данные. Шифрование и расшифровка данных не так уж сложны, но правильное хранение ключа шифрования [может](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [быть](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [сложным](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Самое важное — никогда не хранить ключ шифрования в публичной директории или коммитить его в репозиторий кода. +Шифрование крайне важно для любого приложения, которое хранит конфиденциальные данные. Шифрование и дешифрование данных не так уж сложно, но правильное хранение ключа шифрования [может](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [быть](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [сложным](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Самое важное — никогда не хранить ключ шифрования в публичной директории или коммитить его в репозиторий кода. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Это библиотека, которую можно использовать для шифрования и расшифровки данных. Запуск и использование довольно просты для начала шифрования и расшифровки данных. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - Это библиотека, которую можно использовать для шифрования и дешифрования данных. Запуск и работа с ней довольно просты для начала шифрования и дешифрования данных. ## Очередь заданий -Очереди заданий очень полезны для асинхронной обработки задач. Это может быть отправка email, обработка изображений или что угодно, что не нужно делать в реальном времени. +Очереди заданий очень полезны для асинхронной обработки задач. Это может быть отправка email, обработка изображений или что-то, что не требует выполнения в реальном времени. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue — библиотека, которую можно использовать для асинхронной обработки заданий. Ее можно использовать с beanstalkd, MySQL/MariaDB, SQLite и PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue — это библиотека, которую можно использовать для асинхронной обработки заданий. Её можно использовать с beanstalkd, MySQL/MariaDB, SQLite и PostgreSQL. ## Сессии -Сессии не очень полезны для API, но для создания веб-приложения сессии могут быть крайне важны для поддержания состояния и информации о входе. +Сессии не очень полезны для API, но для построения веб-приложения сессии могут быть крайне важны для поддержания состояния и информации о входе. - official [flightphp/session](/awesome-plugins/session) - Официальная библиотека Flight Session. Это простая библиотека сессий, которую можно использовать для хранения и извлечения данных сессии. Она использует встроенную обработку сессий PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (неблокирующий, flash, сегмент, шифрование сессии). Использует PHP open_ssl для опционального шифрования/расшифровки данных сессии. +- [Ghostff/Session](/awesome-plugins/ghost-session) - Менеджер сессий PHP (неблокирующий, flash, сегмент, шифрование сессий). Использует PHP open_ssl для опционального шифрования/дешифрования данных сессии. ## Шаблонизация @@ -81,7 +87,7 @@ CLI-приложения — отличный способ взаимодейс ## Интеграция с WordPress -Хотите использовать Flight в вашем проекте WordPress? Есть удобный плагин для этого! +Хотите использовать Flight в вашем проекте WordPress? Для этого есть удобный плагин! - [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Этот плагин WordPress позволяет запускать Flight прямо рядом с WordPress. Он идеален для добавления пользовательских API, микросервисов или даже полноценных приложений на ваш сайт WordPress с использованием фреймворка Flight. Супер полезно, если вы хотите лучшее из двух миров! diff --git a/content/v3/ru/examples.md b/content/v3/ru/examples.md index 9dcd2b58..9b7ef8ad 100644 --- a/content/v3/ru/examples.md +++ b/content/v3/ru/examples.md @@ -1,36 +1,37 @@ # Нужен быстрый старт? -У вас есть два варианта, чтобы начать новый проект на Flight: +У вас есть два варианта для начала работы с новым проектом Flight: -- [Полный скелетный каркас](https://github.com/flightphp/skeleton): более полный пример с контроллерами и представлениями. -- [Скелетный каркас в одном файле](https://github.com/flightphp/skeleton-simple): один файл, который включает все, что нужно для запуска вашего приложения в одном простом файле. +- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Более полный пример с контроллерами и представлениями. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Один файл, который включает всё необходимое для запуска вашего приложения в одном простом файле. -Примеры, предложенные сообществом: +Примеры, внесённые сообществом: - [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP с директориями Laravel, с инструментами PHP + GH Actions -- [fleact](https://github.com/flightphp/fleact) - Стартовый комплект FlightPHP с интеграцией ReactJS. -- [flastro](https://github.com/flightphp/flastro) - Стартовый комплект FlightPHP с интеграцией Astro. -- [velt](https://github.com/flightphp/velt) - Velt - это быстрый и простой шаблон Svelte с бэкендом на FlightPHP. - -## Нужна немного вдохновения? - -Хотя эти проекты не официально спонсированы командой Flight, они могут дать вам идеи о том, как структурировать собственные проекты, построенные с использованием Flight! - -- [Decay](https://github.com/boxybird/decay) - Flight v3 с HTMX и SleekDB, все о зомби! ([Демо](https://decay.andrewrhyand.com)) -- [Пример блога на Flight](https://github.com/n0nag0n/flightphp-blog) - Flight v3 с Middleware, контроллерами, Active Record и Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Простой проект CRUD API с использованием фреймворка Flight, который предоставляет базовую структуру для новых пользователей, чтобы быстро настроить PHP-приложение с операциями CRUD и подключением к базе данных. Проект демонстрирует, как использовать Flight для разработки RESTful API, что делает его идеальным учебным инструментом для начинающих и полезным стартовым комплектом для более опытных разработчиков. -- [Система управления школой на Flight](https://github.com/krmu/FlightPHP_School) - Flight v3 -- [Paste Bin с комментариями](https://github.com/n0nag0n/commie2) - Flight v3 -- [Базовое приложение Skeleton](https://github.com/markhughes/flight-skeleton) -- [Пример Wiki](https://github.com/Skayo/FlightWiki) -- [Приложение PHP фреймворка IT-Innovator](https://github.com/itinnovator/myphp-app) -- [LittleEducationalCMS (испанский)](https://github.com/casgin/LittleEducationalCMS) -- [API итальянских жёлтых страниц](https://github.com/chiccomagnus/PGAPI) -- [Универсальная система управления контентом (с....очень мало документации)](https://github.com/recepuncu/cms) -- [Маленький php фреймворк на основе Flight и medoo.](https://github.com/ycrao/tinyme) -- [Пример MVC приложения](https://github.com/paddypei/Flight-MVC) -- [Готовый шаблон Flight Boilerplate](https://github.com/madcoda9000/SecStore) — готовый к использованию фреймворк аутентификации, который сэкономит вам недели разработки. Обеспечивает безопасность корпоративного уровня: 2FA/TOTP, интеграция с LDAP, единый вход в Azure, интеллектуальное ограничение скорости, фингерпринтинг сеансов, защита от подбора паролей, панель аналитики безопасности, комплексное ведение журнала аудита и детальное управление доступом на основе ролей. +- [fleact](https://github.com/flightphp/fleact) - Стартовый набор FlightPHP с интеграцией ReactJS. +- [flastro](https://github.com/flightphp/flastro) - Стартовый набор FlightPHP с интеграцией Astro. +- [velt](https://github.com/flightphp/velt) - Velt — это быстрый и простой шаблон Svelte для старта с бэкендом на FlightPHP. + +## Нужен ли вам вдохновение? + +Хотя эти примеры не спонсируются официально командой Flight, они могут дать вам идеи о том, как структурировать свои собственные проекты, построенные на Flight! + +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental — это одностраничное, мобильно-дружественное веб-приложение для аренды автомобилей, построенное на PHP (FlightPHP), JavaScript и MySQL. Оно поддерживает регистрацию пользователей, просмотр и бронирование автомобилей, в то время как администраторы могут управлять автомобилями, пользователями и бронированиями. Приложение включает REST API, аутентификацию JWT и адаптивный дизайн для современного опыта аренды. +- [Decay](https://github.com/boxybird/decay) - Flight v3 с HTMX и SleekDB, всё о зомби! ([Demo](https://decay.andrewrhyand.com)) +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 с Middleware, Controllers, Active Record и Latte. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Простой проект CRUD API с использованием фреймворка Flight, который предоставляет базовую структуру для новых пользователей, чтобы быстро настроить PHP-приложение с операциями CRUD и подключением к базе данных. Проект демонстрирует, как использовать Flight для разработки RESTful API, делая его идеальным инструментом для обучения новичков и полезным стартовым набором для более опытных разработчиков. +- [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 +- [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 +- [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) +- [Example Wiki](https://github.com/Skayo/FlightWiki) +- [The IT-Innovator PHP Framework Application](https://github.com/itinnovator/myphp-app) +- [LittleEducationalCMS (Spanish)](https://github.com/casgin/LittleEducationalCMS) +- [Italian Yellow Pages API](https://github.com/chiccomagnus/PGAPI) +- [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) +- [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) +- [Example MVC Application](https://github.com/paddypei/Flight-MVC) +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Готовый к производству фреймворк аутентификации, который сэкономит вам недели разработки. Функции корпоративного уровня безопасности: 2FA/TOTP, интеграция LDAP, Azure SSO, интеллектуальное ограничение скорости, отпечатки сессий, защита от brute-force, панель аналитики безопасности, всестороннее логирование аудита и гранулярный контроль доступа на основе ролей. ## Хотите поделиться своим примером? -Если у вас есть проект, которым вы хотите поделиться, пожалуйста, отправьте запрос на слияние, чтобы добавить его в этот список! \ No newline at end of file +Если у вас есть проект, которым вы хотите поделиться, пожалуйста, отправьте pull request, чтобы добавить его в этот список! \ No newline at end of file diff --git a/content/v3/ru/learn/requests.md b/content/v3/ru/learn/requests.md index 6f517fcf..44da8295 100644 --- a/content/v3/ru/learn/requests.md +++ b/content/v3/ru/learn/requests.md @@ -10,15 +10,15 @@ $request = Flight::request(); ## Понимание -HTTP-запросы — это один из ключевых аспектов, которые нужно понять в жизненном цикле HTTP. Пользователь выполняет действие в веб-браузере или HTTP-клиенте, и они отправляют серию заголовков, тела, URL и т.д. в ваш проект. Вы можете захватить эти заголовки (язык браузера, тип сжатия, который они могут обрабатывать, пользовательский агент и т.д.) и захватить тело и URL, которые отправляются в ваше приложение Flight. Эти запросы необходимы для вашего приложения, чтобы понять, что делать дальше. +HTTP-запросы — это один из основных аспектов, которые нужно понять о жизненном цикле HTTP. Пользователь выполняет действие в веб-браузере или HTTP-клиенте, и они отправляют серию заголовков, тело, URL и т.д. в ваш проект. Вы можете захватить эти заголовки (язык браузера, тип сжатия, который они могут обрабатывать, пользовательский агент и т.д.) и захватить тело и URL, отправляемые в ваше приложение Flight. Эти запросы необходимы для вашего приложения, чтобы понять, что делать дальше. ## Основное использование PHP имеет несколько суперглобальных переменных, включая `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` и `$_COOKIE`. Flight абстрагирует их в удобные [Collections](/learn/collections). Вы можете обращаться к свойствам `query`, `data`, `cookies` и `files` как к массивам или объектам. -> **Примечание:** **СИЛЬНО** не рекомендуется использовать эти суперглобальные переменные в вашем проекте, и их следует ссылаться через объект `request()`. +> **Примечание:** **СТРОГО** не рекомендуется использовать эти суперглобальные переменные в вашем проекте; они должны ссылаться через объект `request()`. -> **Примечание:** Для `$_ENV` нет доступной абстракции. +> **Примечание:** Нет доступной абстракции для `$_ENV`. ### `$_GET` @@ -28,10 +28,10 @@ PHP имеет несколько суперглобальных перемен // GET /search?keyword=something Flight::route('/search', function(){ $keyword = Flight::request()->query['keyword']; - // или + // or $keyword = Flight::request()->query->keyword; - echo "Вы ищете: $keyword"; - // запрос к базе данных или что-то еще с $keyword + echo "You are searching for: $keyword"; + // query a database or something else with the $keyword }); ``` @@ -43,11 +43,11 @@ Flight::route('/search', function(){ Flight::route('POST /submit', function(){ $name = Flight::request()->data['name']; $email = Flight::request()->data['email']; - // или + // or $name = Flight::request()->data->name; $email = Flight::request()->data->email; - echo "Вы отправили: $name, $email"; - // сохранить в базу данных или что-то еще с $name и $email + echo "You submitted: $name, $email"; + // save to a database or something else with the $name and $email }); ``` @@ -58,9 +58,9 @@ Flight::route('POST /submit', function(){ ```php Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; - // или + // or $savedLogin = Flight::request()->cookies->myLoginCookie; - // проверить, действительно ли сохранено, и если да, автоматически войти + // check if it's really saved or not and if it is auto log them in if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -68,7 +68,7 @@ Flight::route('GET /login', function(){ }); ``` -Для помощи в установке новых значений cookie см. [overclokk/cookie](/awesome-plugins/php-cookie) +Для помощи по установке новых значений cookie см. [overclokk/cookie](/awesome-plugins/php-cookie) ### `$_SERVER` @@ -84,9 +84,9 @@ $host = Flight::request()->getVar('HTTP_HOST'); Вы можете получить доступ к загруженным файлам через свойство `files`: ```php -// прямой доступ к свойству $_FILES. См. ниже рекомендуемый подход +// raw access to $_FILES property. See below for recommended approach $uploadedFile = Flight::request()->files['myFile']; -// или +// or $uploadedFile = Flight::request()->files->myFile; ``` @@ -100,18 +100,18 @@ _v3.12.0_ ```php Flight::route('POST /upload', function(){ - // Если у вас есть поле ввода вроде + // If you had an input field like $uploadedFileData = Flight::request()->getUploadedFiles(); $uploadedFile = $uploadedFileData['myFile']; $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); }); ``` -Если у вас загружено несколько файлов, вы можете пройтись по ним циклом: +Если у вас загружено несколько файлов, вы можете перебрать их: ```php Flight::route('POST /upload', function(){ - // Если у вас есть поле ввода вроде + // If you had an input field like $uploadedFiles = Flight::request()->getUploadedFiles()['myFiles']; foreach ($uploadedFiles as $uploadedFile) { $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); @@ -119,7 +119,7 @@ Flight::route('POST /upload', function(){ }); ``` -> **Примечание по безопасности:** Всегда проверяйте и очищайте ввод пользователя, особенно при работе с загрузкой файлов. Всегда проверяйте типы расширений, которые вы разрешаете загружать, но также проверяйте "магические байты" файла, чтобы убедиться, что это действительно тип файла, который заявляет пользователь. Есть [статьи](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [и](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [библиотеки](https://github.com/RikudouSage/MimeTypeDetector), доступные для помощи в этом. +> **Примечание по безопасности:** Всегда проверяйте и очищайте пользовательский ввод, особенно при работе с загрузкой файлов. Всегда проверяйте типы расширений, которые вы разрешаете загружать, но также проверяйте "магические байты" файла, чтобы убедиться, что это действительно тип файла, который утверждает пользователь. Есть [статьи](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [и](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [библиотеки](https://github.com/RikudouSage/MimeTypeDetector), доступные для помощи в этом. ### Тело запроса @@ -128,7 +128,7 @@ Flight::route('POST /upload', function(){ ```php Flight::route('POST /users/xml', function(){ $xmlBody = Flight::request()->getBody(); - // сделать что-то с XML, который был отправлен. + // do something with the XML that was sent. }); ``` @@ -146,14 +146,14 @@ $id = Flight::request()->data->id; ```php -// Возможно, вам нужен заголовок Authorization +// Maybe you need Authorization header $host = Flight::request()->getHeader('Authorization'); -// или +// or $host = Flight::request()->header('Authorization'); -// Если нужно получить все заголовки +// If you need to grab all headers $headers = Flight::request()->getHeaders(); -// или +// or $headers = Flight::request()->headers(); ``` @@ -162,7 +162,7 @@ $headers = Flight::request()->headers(); Вы можете получить доступ к методу запроса с помощью свойства `method` или метода `getMethod()`: ```php -$method = Flight::request()->method; // фактически заполняется getMethod() +$method = Flight::request()->method; // actually populated by getMethod() $method = Flight::request()->getMethod(); ``` @@ -187,7 +187,7 @@ $method = Flight::request()->getMethod(); - **data** - Данные POST или JSON-данные - **cookies** - Данные cookie - **files** - Загруженные файлы -- **secure** - Является ли соединение защищенным +- **secure** - Является ли соединение безопасным - **accept** - Параметры HTTP accept - **proxy_ip** - IP-адрес прокси клиента. Сканирует массив `$_SERVER` на наличие `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` в этом порядке. - **host** - Имя хоста запроса @@ -214,7 +214,7 @@ $url = Flight::request()->getFullUrl(); // http://example.com/path/to/something/cool?query=yes+thanks $url = Flight::request()->getBaseUrl(); // https://example.com -// Обратите внимание, без завершающего слеша. +// Notice, no trailing slash. ``` ## Разбор запроса @@ -226,7 +226,7 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` -## Переговоры по типам принимаемого содержимого +## Переговоры по типам содержимого Accept _v3.17.2_ @@ -234,16 +234,16 @@ _v3.17.2_ ```php -// Пример заголовка Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 -// Ниже определяются поддерживаемые типы. +// Example Accept header: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 +// The below defines what you support. $availableTypes = ['application/json', 'application/xml']; $typeToServe = Flight::request()->negotiateContentType($availableTypes); if ($typeToServe === 'application/json') { - // Отправить JSON-ответ + // Serve JSON response } elseif ($typeToServe === 'application/xml') { - // Отправить XML-ответ + // Serve XML response } else { - // По умолчанию что-то другое или выбросить ошибку + // Default to something else or throw an error } ``` @@ -262,4 +262,4 @@ if ($typeToServe === 'application/json') { ## Журнал изменений - v3.17.2 - Добавлен negotiateContentType() - v3.12.0 - Добавлена возможность обработки загрузки файлов через объект запроса. -- v1.0 - Первоначальный выпуск. \ No newline at end of file +- v1.0 - Первое выпущение. \ No newline at end of file diff --git a/content/v3/ru/learn/routing.md b/content/v3/ru/learn/routing.md index a74d49e1..568502fd 100644 --- a/content/v3/ru/learn/routing.md +++ b/content/v3/ru/learn/routing.md @@ -1,10 +1,10 @@ # Маршрутизация ## Обзор -Маршрутизация в Flight PHP сопоставляет шаблоны URL с функциями обратного вызова или методами классов, обеспечивая быстрый и простой обработку запросов. Она разработана для минимальной нагрузки, удобства для начинающих и расширяемости без внешних зависимостей. +Маршрутизация в Flight PHP сопоставляет шаблоны URL с функциями обратного вызова или методами классов, обеспечивая быстрый и простой обработку запросов. Она разработана для минимальных накладных расходов, удобства для начинающих и расширяемости без внешних зависимостей. ## Понимание -Маршрутизация — это основной механизм, который соединяет HTTP-запросы с логикой вашего приложения в Flight. Определяя маршруты, вы указываете, как разные URL запускают конкретный код, будь то через функции, методы классов или действия контроллера. Система маршрутизации Flight гибкая, поддерживает базовые шаблоны, именованные параметры, регулярные выражения и продвинутые функции, такие как внедрение зависимостей и ресурсная маршрутизация. Этот подход позволяет держать код организованным и легким в поддержке, оставаясь быстрым и простым для начинающих и расширяемым для продвинутых пользователей. +Маршрутизация — это основной механизм, который соединяет HTTP-запросы с логикой вашего приложения в Flight. Определяя маршруты, вы указываете, как разные URL запускают конкретный код, будь то через функции, методы классов или действия контроллера. Система маршрутизации Flight гибкая, поддерживает базовые шаблоны, именованные параметры, регулярные выражения и продвинутые функции, такие как внедрение зависимостей и ресурсная маршрутизация. Этот подход сохраняет ваш код организованным и легким в обслуживании, оставаясь быстрым и простым для начинающих и расширяемым для продвинутых пользователей. > **Примечание:** Хотите узнать больше о маршрутизации? Посмотрите страницу ["почему фреймворк?"](/learn/why-frameworks) для более подробного объяснения. @@ -21,7 +21,7 @@ Flight::route('/', function(){ > Маршруты сопоставляются в порядке их определения. Первый маршрут, соответствующий запросу, будет вызван. -### Использование функций как обратных вызовов +### Использование функций в качестве обратных вызовов Обратный вызов может быть любым объектом, который можно вызвать. Таким образом, вы можете использовать обычную функцию: ```php @@ -32,7 +32,7 @@ function hello() { Flight::route('/', 'hello'); ``` -### Использование классов и методов как контроллера +### Использование классов и методов в качестве контроллера Вы также можете использовать метод (статический или нет) класса: ```php @@ -43,11 +43,11 @@ class GreetingController { } Flight::route('/', [ 'GreetingController','hello' ]); -// или -Flight::route('/', [ GreetingController::class, 'hello' ]); // предпочтительный метод -// или +// or +Flight::route('/', [ GreetingController::class, 'hello' ]); // preferred method +// or Flight::route('/', [ 'GreetingController::hello' ]); -// или +// or Flight::route('/', [ 'GreetingController->hello' ]); ``` @@ -92,8 +92,8 @@ Flight::route('POST /', function () { echo 'I received a POST request.'; }); -// Вы не можете использовать Flight::get() для маршрутов, поскольку это метод -// для получения переменных, а не создания маршрута. +// You cannot use Flight::get() for routes as that is a method +// to get variables, not create a route. Flight::post('/', function() { /* code */ }); Flight::patch('/', function() { /* code */ }); Flight::put('/', function() { /* code */ }); @@ -121,20 +121,20 @@ Flight предоставляет встроенную обработку HTTP- Flight::route('GET /info', function() { echo 'This is some info!'; }); -// Запрос HEAD к /info вернет те же заголовки, но без тела. +// A HEAD request to /info will return the same headers, but no body. ``` #### Запросы OPTIONS Запросы `OPTIONS` автоматически обрабатываются Flight для любого определенного маршрута. - Когда получен запрос OPTIONS, Flight отвечает статусом `204 No Content` и заголовком `Allow`, перечисляющим все поддерживаемые HTTP-методы для этого маршрута. -- Вам не нужно определять отдельный маршрут для OPTIONS, если вы не хотите кастомное поведение или изменить ответ. +- Вам не нужно определять отдельный маршрут для OPTIONS. ```php -// Для маршрута, определенного как: +// For a route defined as: Flight::route('GET|POST /users', function() { /* ... */ }); -// Запрос OPTIONS к /users ответит: +// An OPTIONS request to /users will respond with: // // Status: 204 No Content // Allow: GET, POST, HEAD, OPTIONS @@ -148,12 +148,12 @@ Flight::route('GET|POST /users', function() { /* ... */ }); $router = Flight::router(); -// сопоставляет все методы так же, как Flight::route() +// maps all methods just like Flight::route() $router->map('/', function() { echo 'hello world!'; }); -// GET-запрос +// GET request $router->get('/users', function() { echo 'users'; }); @@ -168,14 +168,14 @@ $router->patch('/users/@id', function() { /* code */}); ```php Flight::route('/user/[0-9]+', function () { - // Это будет соответствовать /user/1234 + // This will match /user/1234 }); ``` -Хотя этот метод доступен, рекомендуется использовать именованные параметры или именованные параметры с регулярными выражениями, поскольку они более читаемы и проще в поддержке. +Хотя этот метод доступен, рекомендуется использовать именованные параметры или именованные параметры с регулярными выражениями, поскольку они более читаемы и легче в обслуживании. ### Именованные параметры -Вы можете указать именованные параметры в своих маршрутах, которые будут переданы в вашу функцию обратного вызова. **Это больше для читаемости маршрута, чем что-либо еще. Пожалуйста, смотрите раздел ниже о важном предупреждении.** +Вы можете указать именованные параметры в своих маршрутах, которые будут переданы в вашу функцию обратного вызова. **Это больше для читаемости маршрута, чем для чего-либо другого. Пожалуйста, см. раздел ниже о важном предупреждении.** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -183,20 +183,20 @@ Flight::route('/@name/@id', function (string $name, string $id) { }); ``` -Вы также можете включить регулярные выражения с именованными параметрами, используя разделитель `:`: +Вы также можете включить регулярные выражения с вашими именованными параметрами, используя разделитель `:`: ```php Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { - // Это будет соответствовать /bob/123 - // Но не будет соответствовать /bob/12345 + // This will match /bob/123 + // But will not match /bob/12345 }); ``` -> **Примечание:** Сопоставление групп regex `()` с позиционными параметрами не поддерживается. Прим.: `:'\(` +> **Примечание:** Сопоставление групп regex `()` с позиционными параметрами не поддерживается. Ex: `:'\(` #### Важное предупреждение -Хотя в примере выше кажется, что `@name` напрямую связано с переменной `$name`, это не так. Порядок параметров в функции обратного вызова определяет, что передается в нее. Если вы поменяете порядок параметров в функции обратного вызова, переменные также поменяются. Вот пример: +Хотя в примере выше кажется, что `@name` напрямую связан с переменной `$name`, это не так. Порядок параметров в функции обратного вызова определяет, что передается в нее. Если вы поменяете порядок параметров в функции обратного вызова, переменные также поменяются. Вот пример: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -205,7 +205,7 @@ Flight::route('/@name/@id', function (string $id, string $name) { ``` И если вы перейдете по следующему URL: `/bob/123`, вывод будет `hello, 123 (bob)!`. -_Пожалуйста, будьте осторожны_ при настройке маршрутов и функций обратного вызова! +_Пожалуйста, будьте осторожны_ при настройке ваших маршрутов и функций обратного вызова! ### Необязательные параметры Вы можете указать именованные параметры, которые являются необязательными для сопоставления, обернув сегменты в скобки. @@ -214,7 +214,7 @@ _Пожалуйста, будьте осторожны_ при настройк Flight::route( '/blog(/@year(/@month(/@day)))', function(?string $year, ?string $month, ?string $day) { - // Это будет соответствовать следующим URL: + // This will match the following URLS: // /blog/2012/12/10 // /blog/2012/12 // /blog/2012 @@ -225,12 +225,12 @@ Flight::route( Любые необязательные параметры, которые не сопоставлены, будут переданы как `NULL`. -### Дикая маршрутизация +### Маршрутизация с подстановочным знаком Сопоставление выполняется только для отдельных сегментов URL. Если вы хотите сопоставить несколько сегментов, вы можете использовать подстановочный знак `*`. ```php Flight::route('/blog/*', function () { - // Это будет соответствовать /blog/2000/02/01 + // This will match /blog/2000/02/01 }); ``` @@ -238,20 +238,20 @@ Flight::route('/blog/*', function () { ```php Flight::route('*', function () { - // Сделайте что-то + // Do something }); ``` ### Обработчик 404 Not Found -По умолчанию, если URL не найден, Flight отправит простой и минималистичный ответ `HTTP 404 Not Found`. -Если вы хотите более кастомный ответ 404, вы можете [сопоставить](/learn/extending) свой собственный метод `notFound`: +По умолчанию, если URL не найден, Flight отправит простой и обычный ответ `HTTP 404 Not Found`. +Если вы хотите иметь более кастомный ответ 404, вы можете [сопоставить](/learn/extending) свой собственный метод `notFound`: ```php Flight::map('notFound', function() { $url = Flight::request()->url; - // Вы также можете использовать Flight::render() с кастомным шаблоном. + // You could also use Flight::render() with a custom template. $output = <<My Custom 404 Not Found

The page you have requested {$url} could not be found.

@@ -267,9 +267,9 @@ Flight::map('notFound', function() { ### Обработчик Method Not Found -По умолчанию, если URL найден, но метод не разрешен, Flight отправит простой и минималистичный ответ `HTTP 405 Method Not Allowed` (Пример: Method Not Allowed. Allowed Methods are: GET, POST). Он также включит заголовок `Allow` с разрешенными методами для этого URL. +По умолчанию, если URL найден, но метод не разрешен, Flight отправит простой и обычный ответ `HTTP 405 Method Not Allowed` (Ex: Method Not Allowed. Allowed Methods are: GET, POST). Он также включит заголовок `Allow` с разрешенными методами для этого URL. -Если вы хотите более кастомный ответ 405, вы можете [сопоставить](/learn/extending) свой собственный метод `methodNotFound`: +Если вы хотите иметь более кастомный ответ 405, вы можете [сопоставить](/learn/extending) свой собственный метод `methodNotFound`: ```php use flight\net\Route; @@ -278,7 +278,7 @@ Flight::map('methodNotFound', function(Route $route) { $url = Flight::request()->url; $methods = implode(', ', $route->methods); - // Вы также можете использовать Flight::render() с кастомным шаблоном. + // You could also use Flight::render() with a custom template. $output = <<My Custom 405 Method Not Allowed

The method you have requested for {$url} is not allowed.

@@ -314,7 +314,7 @@ class Greeting } public function hello(int $id) { - // сделайте что-то с $this->pdoWrapper + // do something with $this->pdoWrapper $name = $this->pdoWrapper->fetchField("SELECT name FROM users WHERE id = ?", [ $id ]); echo "Hello, world! My name is {$name}!"; } @@ -322,11 +322,11 @@ class Greeting // index.php -// Настройте контейнер с любыми параметрами, которые вам нужны -// Смотрите страницу Внедрение зависимостей для дополнительной информации о PSR-11 +// Setup the container with whatever params you need +// See the Dependency Injection page for more information on PSR-11 $dice = new \Dice\Dice(); -// Не забудьте переприсвоить переменную с '$dice = '!!!!! +// Don't forget to reassign the variable with '$dice = '!!!!! $dice = $dice->addRule('flight\database\PdoWrapper', [ 'shared' => true, 'constructParams' => [ @@ -336,16 +336,16 @@ $dice = $dice->addRule('flight\database\PdoWrapper', [ ] ]); -// Зарегистрируйте обработчик контейнера +// Register the container handler Flight::registerContainerHandler(function($class, $params) use ($dice) { return $dice->create($class, $params); }); -// Маршруты как обычно +// Routes like normal Flight::route('/hello/@id', [ 'Greeting', 'hello' ]); -// или +// or Flight::route('/hello/@id', 'Greeting->hello'); -// или +// or Flight::route('/hello/@id', 'Greeting::hello'); Flight::start(); @@ -357,85 +357,85 @@ Flight::start(); ```php Flight::route('/user/@name', function (string $name) { - // Проверьте какое-то условие + // Check some condition if ($name !== "Bob") { - // Продолжите к следующему маршруту + // Continue to next route return true; } }); Flight::route('/user/*', function () { - // Это будет вызвано + // This will get called }); ``` -Теперь рекомендуется использовать [middleware](/learn/middleware) для обработки сложных случаев, таких как этот. +Теперь рекомендуется использовать [middleware](/learn/middleware) для обработки сложных случаев вроде этого. ### Псевдонимы маршрутов -Присваивая псевдоним маршруту, вы можете позже динамически вызывать этот псевдоним в вашем приложении для генерации позже в коде (пример: ссылка в HTML-шаблоне или генерация URL перенаправления). +Присваивая псевдоним маршруту, вы можете позже динамически вызывать этот псевдоним в вашем приложении для генерации позже в вашем коде (например: ссылка в HTML-шаблоне или генерация URL для перенаправления). ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); -// или +// or Flight::route('/users/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view'); -// позже в коде где-то +// later in code somewhere class UserController { public function update() { - // код для сохранения пользователя... - $id = $user['id']; // 5 например + // code to save user... + $id = $user['id']; // 5 for example - $redirectUrl = Flight::getUrl('user_view', [ 'id' => $id ]); // вернет '/users/5' + $redirectUrl = Flight::getUrl('user_view', [ 'id' => $id ]); // will return '/users/5' Flight::redirect($redirectUrl); } } ``` -Это особенно полезно, если ваш URL изменится. В примере выше предположим, что пользователи перемещены в `/admin/users/@id` вместо этого. -С псевдонимами на месте для маршрута вам больше не нужно искать все старые URL в коде и изменять их, потому что псевдоним теперь вернет `/admin/users/5`, как в примере выше. +Это особенно полезно, если ваш URL изменится. В приведенном выше примере предположим, что пользователи перемещены в `/admin/users/@id` вместо. +С псевдонимами на месте для маршрута вам больше не нужно искать все старые URL в вашем коде и изменять их, потому что псевдоним теперь вернет `/admin/users/5`, как в примере выше. Псевдонимы маршрутов все еще работают в группах: ```php Flight::group('/users', function() { Flight::route('/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); - // или + // or Flight::route('/@id', function($id) { echo 'user:'.$id; })->setAlias('user_view'); }); ``` -### Осмотр информации о маршруте -Если вы хотите осмотреть информацию о соответствующем маршруте, есть 2 способа это сделать: +### Просмотр информации о маршруте +Если вы хотите просмотреть информацию о соответствующем маршруте, есть 2 способа это сделать: 1. Вы можете использовать свойство `executedRoute` на объекте `Flight::router()`. -2. Вы можете запросить, чтобы объект маршрута был передан в ваш обратный вызов, передав `true` в качестве третьего параметра в методе маршрута. Объект маршрута всегда будет последним параметром, переданным в вашу функцию обратного вызова. +2. Вы можете запросить передачу объекта маршрута в ваш обратный вызов, передав `true` в качестве третьего параметра в методе маршрута. Объект маршрута всегда будет последним параметром, переданным в вашу функцию обратного вызова. #### `executedRoute` ```php Flight::route('/', function() { $route = Flight::router()->executedRoute; - // Сделайте что-то с $route - // Массив HTTP-методов, сопоставленных с + // Do something with $route + // Array of HTTP methods matched against $route->methods; - // Массив именованных параметров + // Array of named parameters $route->params; - // Соответствующее регулярное выражение + // Matching regular expression $route->regex; - // Содержит содержимое любого '*' , использованного в шаблоне URL + // Contains the contents of any '*' used in the URL pattern $route->splat; - // Показывает путь URL....если вам это действительно нужно + // Shows the url path....if you really need it $route->pattern; - // Показывает, какое middleware назначено этому + // Shows what middleware is assigned to this $route->middleware; - // Показывает псевдоним, назначенный этому маршруту + // Shows the alias assigned to this route $route->alias; }); ``` @@ -445,41 +445,41 @@ Flight::route('/', function() { #### Передача `true` в определение маршрута ```php Flight::route('/', function(\flight\net\Route $route) { - // Массив HTTP-методов, сопоставленных с + // Array of HTTP methods matched against $route->methods; - // Массив именованных параметров + // Array of named parameters $route->params; - // Соответствующее регулярное выражение + // Matching regular expression $route->regex; - // Содержит содержимое любого '*' , использованного в шаблоне URL + // Contains the contents of any '*' used in the URL pattern $route->splat; - // Показывает путь URL....если вам это действительно нужно + // Shows the url path....if you really need it $route->pattern; - // Показывает, какое middleware назначено этому + // Shows what middleware is assigned to this $route->middleware; - // Показывает псевдоним, назначенный этому маршруту + // Shows the alias assigned to this route $route->alias; -}, true);// <-- Этот параметр true делает это возможным +}, true);// <-- This true parameter is what makes that happen ``` ### Группировка маршрутов и Middleware -Может быть время, когда вы хотите сгруппировать связанные маршруты вместе (например, `/api/v1`). +Могут быть случаи, когда вы хотите сгруппировать связанные маршруты вместе (например, `/api/v1`). Вы можете сделать это, используя метод `group`: ```php Flight::group('/api/v1', function () { Flight::route('/users', function () { - // Соответствует /api/v1/users + // Matches /api/v1/users }); Flight::route('/posts', function () { - // Соответствует /api/v1/posts + // Matches /api/v1/posts }); }); ``` @@ -489,24 +489,24 @@ Flight::group('/api/v1', function () { ```php Flight::group('/api', function () { Flight::group('/v1', function () { - // Flight::get() получает переменные, он не устанавливает маршрут! Смотрите контекст объекта ниже + // Flight::get() gets variables, it doesn't set a route! See object context below Flight::route('GET /users', function () { - // Соответствует GET /api/v1/users + // Matches GET /api/v1/users }); Flight::post('/posts', function () { - // Соответствует POST /api/v1/posts + // Matches POST /api/v1/posts }); Flight::put('/posts/1', function () { - // Соответствует PUT /api/v1/posts + // Matches PUT /api/v1/posts }); }); Flight::group('/v2', function () { - // Flight::get() получает переменные, он не устанавливает маршрут! Смотрите контекст объекта ниже + // Flight::get() gets variables, it doesn't set a route! See object context below Flight::route('GET /users', function () { - // Соответствует GET /api/v2/users + // Matches GET /api/v2/users }); }); }); @@ -521,13 +521,13 @@ $app = Flight::app(); $app->group('/api/v1', function (Router $router) { - // используйте переменную $router + // user the $router variable $router->get('/users', function () { - // Соответствует GET /api/v1/users + // Matches GET /api/v1/users }); $router->post('/posts', function () { - // Соответствует POST /api/v1/posts + // Matches POST /api/v1/posts }); }); ``` @@ -541,12 +541,12 @@ $app->group('/api/v1', function (Router $router) { ```php Flight::group('/api/v1', function () { Flight::route('/users', function () { - // Соответствует /api/v1/users + // Matches /api/v1/users }); -}, [ MyAuthMiddleware::class ]); // или [ new MyAuthMiddleware() ], если вы хотите использовать экземпляр +}, [ MyAuthMiddleware::class ]); // or [ new MyAuthMiddleware() ] if you want to use an instance ``` -Смотрите больше деталей на странице [групповое middleware](/learn/middleware#grouping-middleware). +См. больше деталей на странице [групповой middleware](/learn/middleware#grouping-middleware). ### Ресурсная маршрутизация Вы можете создать набор маршрутов для ресурса, используя метод `resource`. Это создаст набор маршрутов для ресурса, следующий RESTful-конвенциям. @@ -606,7 +606,7 @@ class UsersController } ``` -> **Примечание**: Вы можете просмотреть недавно добавленные маршруты с помощью `runway`, запустив `php runway routes`. +> **Примечание**: Вы можете просмотреть newly added routes с помощью `runway`, запустив `php runway routes`. #### Настройка ресурсных маршрутов @@ -615,7 +615,9 @@ class UsersController ##### Базовый псевдоним Вы можете настроить `aliasBase`. По умолчанию псевдоним — это последняя часть указанного URL. -Например, `/users/` приведет к `aliasBase` равному `users`. Когда эти маршруты созданы, псевдонимы — `users.index`, `users.create` и т.д. Если вы хотите изменить псевдоним, установите `aliasBase` в желаемое значение. +Например, `/users/` приведет к `aliasBase` равному `users`. Когда эти маршруты создаются, +псевдонимы — `users.index`, `users.create` и т.д. Если вы хотите изменить псевдоним, установите `aliasBase` +в желаемое значение. ```php Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); @@ -626,12 +628,12 @@ Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); Вы также можете указать, какие маршруты вы хотите создать, используя опции `only` и `except`. ```php -// Разрешите только эти методы и запретите остальные +// Whitelist only these methods and blacklist the rest Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' ] ]); ``` ```php -// Запретите только эти методы и разрешите остальные +// Blacklist only these methods and whitelist the rest Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` @@ -648,14 +650,14 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid ### Потоковые ответы Теперь вы можете передавать потоковые ответы клиенту с помощью `stream()` или `streamWithHeaders()`. -Это полезно для отправки больших файлов, долгосрочных процессов или генерации больших ответов. +Это полезно для отправки больших файлов, длительных процессов или генерации больших ответов. Потоковый маршрут обрабатывается немного иначе, чем обычный маршрут. > **Примечание:** Потоковые ответы доступны только если у вас установлен [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) в `false`. #### Поток с ручными заголовками -Вы можете передавать потоковый ответ клиенту, используя метод `stream()` на маршруте. Если вы +Вы можете передать потоковый ответ клиенту, используя метод `stream()` на маршруте. Если вы делаете это, вы должны установить все заголовки вручную перед выводом чего-либо клиенту. Это делается с помощью функции php `header()` или метода `Flight::response()->setRealHeader()`. @@ -664,15 +666,15 @@ Flight::route('/@filename', function($filename) { $response = Flight::response(); - // очевидно, вы бы очистили путь и т.д. + // obviously you would sanitize the path and whatnot. $fileNameSafe = basename($filename); - // Если у вас есть дополнительные заголовки для установки здесь после выполнения маршрута - // вы должны определить их до того, как что-либо будет выведено. - // Они должны быть прямым вызовом функции header() или - // вызовом Flight::response()->setRealHeader() + // If you have additional headers to set here after the route has executed + // you must define them before anything is echoed out. + // They must all be a raw call to the header() function or + // a call to Flight::response()->setRealHeader() header('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); - // или + // or $response->setRealHeader('Content-Disposition: attachment; filename="'.$fileNameSafe.'"'); $filePath = '/some/path/to/files/'.$fileNameSafe; @@ -681,29 +683,29 @@ Flight::route('/@filename', function($filename) { Flight::halt(404, 'File not found'); } - // вручную установите длину содержимого, если хотите + // manually set the content length if you'd like header('Content-Length: '.filesize($filePath)); - // или + // or $response->setRealHeader('Content-Length: '.filesize($filePath)); - // Потоково передайте файл клиенту по мере чтения + // Stream the file to the client as it's read readfile($filePath); -// Это магическая строка здесь +// This is the magic line here })->stream(); ``` #### Поток с заголовками -Вы также можете использовать метод `streamWithHeaders()` для установки заголовков перед началом потока. +Вы также можете использовать метод `streamWithHeaders()` для установки заголовков перед началом потоковой передачи. ```php Flight::route('/stream-users', function() { - // вы можете добавить любые дополнительные заголовки, которые хотите здесь - // вы просто должны использовать header() или Flight::response()->setRealHeader() + // you can add any additional headers you want here + // you just must use header() or Flight::response()->setRealHeader() - // однако вы получаете свои данные, просто как пример... + // however you pull your data, just as an example... $users_stmt = Flight::db()->query("SELECT id, first_name, last_name FROM users"); echo '{'; @@ -714,54 +716,54 @@ Flight::route('/stream-users', function() { echo ','; } - // Это требуется для отправки данных клиенту + // This is required to send the data to the client ob_flush(); } echo '}'; -// Вот как вы установите заголовки перед началом потока. +// This is how you'll set the headers before you start streaming. })->streamWithHeaders([ 'Content-Type' => 'application/json', 'Content-Disposition' => 'attachment; filename="users.json"', - // опциональный код статуса, по умолчанию 200 + // optional status code, defaults to 200 'status' => 200 ]); ``` ## См. также - [Middleware](/learn/middleware) - Использование middleware с маршрутами для аутентификации, логирования и т.д. -- [Внедрение зависимостей](/learn/dependency-injection-container) - Упрощение создания и управления объектами в маршрутах. -- [Почему фреймворк?](/learn/why-frameworks) - Понимание преимуществ использования фреймворка вроде Flight. -- [Расширение](/learn/extending) - Как расширить Flight своей собственной функциональностью, включая метод `notFound`. +- [Dependency Injection](/learn/dependency-injection-container) - Упрощение создания и управления объектами в маршрутах. +- [Why a Framework?](/learn/why-frameworks) - Понимание преимуществ использования фреймворка вроде Flight. +- [Extending](/learn/extending) - Как расширить Flight своей функциональностью, включая метод `notFound`. - [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - Функция PHP для сопоставления регулярных выражений. ## Устранение неисправностей - Параметры маршрута сопоставляются по порядку, а не по имени. Убедитесь, что порядок параметров обратного вызова соответствует определению маршрута. - Использование `Flight::get()` не определяет маршрут; используйте `Flight::route('GET /...')` для маршрутизации или контекст объекта Router в группах (например, `$router->get(...)`). -- Свойство executedRoute устанавливается только после выполнения маршрута; оно NULL до выполнения. +- Свойство executedRoute устанавливается только после выполнения маршрута; до выполнения оно NULL. - Для потоковой передачи требуется отключить устаревшую функциональность буферизации вывода Flight (`flight.v2.output_buffering = false`). - Для внедрения зависимостей только определенные определения маршрутов поддерживают создание на основе контейнера. ### 404 Not Found или неожиданное поведение маршрута -Если вы видите ошибку 404 Not Found (но вы клянетесь своей жизнью, что она действительно там и это не опечатка), это на самом деле может быть проблема -с тем, что вы возвращаете значение в конечной точке маршрута вместо простого вывода. Причина в этом намеренная, но может подкрасться к некоторым разработчикам. +Если вы видите ошибку 404 Not Found (но вы клянетесь своей жизнью, что это действительно там и это не опечатка), это на самом деле может быть проблема +с возвратом значения в вашем конечном маршруте вместо простого эха. Причина для этого намеренная, но может подкрасться к некоторым разработчикам. ```php Flight::route('/hello', function(){ - // Это может вызвать ошибку 404 Not Found + // This might cause a 404 Not Found error return 'Hello World'; }); -// То, что вы, вероятно, хотите +// What you probably want Flight::route('/hello', function(){ echo 'Hello World'; }); ``` -Причина в этом — специальный механизм, встроенный в роутер, который обрабатывает возвращаемый вывод как сигнал "перейти к следующему маршруту". -Вы можете увидеть поведение, описанное в разделе [Маршрутизация](/learn/routing#passing). +Причина в том, что есть специальный механизм, встроенный в роутер, который обрабатывает возвращаемый вывод как сигнал "перейти к следующему маршруту". +Вы можете увидеть поведение, документированное в разделе [Routing](/learn/routing#passing). ## Журнал изменений -- v3: Добавлена ресурсная маршрутизация, псевдонимы маршрутов и поддержка потоковой передачи, группы маршрутов и поддержка middleware. +- v3: Добавлена ресурсная маршрутизация, псевдонимы маршрутов, поддержка потоковой передачи, группы маршрутов и поддержка middleware. - v1: Большинство базовых функций доступны. \ No newline at end of file diff --git a/content/v3/uk/awesome-plugins/async.md b/content/v3/uk/awesome-plugins/async.md new file mode 100644 index 00000000..200c8afe --- /dev/null +++ b/content/v3/uk/awesome-plugins/async.md @@ -0,0 +1,212 @@ +# Async + +Async — це невеликий пакет для фреймворку Flight, який дозволяє запускати ваші додатки Flight у асинхронних серверах та середовищах виконання, таких як Swoole, AdapterMan, ReactPHP, Amp, RoadRunner, Workerman тощо. З коробки він включає адаптери для Swoole та AdapterMan. + +Мета: розробка та налагодження з PHP-FPM (або вбудованим сервером) та перехід на Swoole (або інший асинхронний драйвер) для продакшену з мінімальними змінами. + +## Вимоги + +- PHP 7.4 або вище +- Фреймворк Flight 3.16.1 або вище +- [Розширення Swoole](https://www.openswoole.com) + +## Встановлення + +Встановіть через composer: + +```bash +composer require flightphp/async +``` + +Якщо плануєте запускати з Swoole, встановіть розширення: + +```bash +# за допомогою pecl +pecl install swoole +# або openswoole +pecl install openswoole + +# або з менеджером пакетів (приклад для Debian/Ubuntu) +sudo apt-get install php-swoole +``` + +## Швидкий приклад Swoole + +Нижче наведено мінімальну конфігурацію, яка показує, як підтримувати як PHP-FPM (або вбудований сервер), так і Swoole, використовуючи один і той самий код. + +Файли, які знадобляться у вашому проєкті: + +- index.php +- swoole_server.php +- SwooleServerDriver.php + +### index.php + +Цей файл — проста перемикачка, яка змушує додаток працювати в режимі PHP для розробки. + +```php +// index.php +route('/', function() use ($app) { + $app->json(['hello' => 'world']); +}); + +if (!defined('NOT_SWOOLE')) { + // Require the SwooleServerDriver class when running in Swoole mode. + require_once __DIR__ . '/SwooleServerDriver.php'; + + Swoole\Runtime::enableCoroutine(); + $Swoole_Server = new SwooleServerDriver('127.0.0.1', 9501, $app); + $Swoole_Server->start(); +} else { + $app->start(); +} +``` + +### SwooleServerDriver.php + +Стислий драйвер, який показує, як передавати запити Swoole у Flight за допомогою AsyncBridge та адаптерів Swoole. + +```php +// SwooleServerDriver.php +Swoole = new SwooleServer($host, $port); + $this->app = $app; + + $this->setDefault(); + $this->bindWorkerEvents(); + $this->bindHttpEvent(); + } + + protected function setDefault() { + $this->Swoole->set([ + 'daemonize' => false, + 'dispatch_mode' => 1, + 'max_request' => 8000, + 'open_tcp_nodelay' => true, + 'reload_async' => true, + 'max_wait_time' => 60, + 'enable_reuse_port' => true, + 'enable_coroutine' => true, + 'http_compression' => false, + 'enable_static_handler' => true, + 'document_root' => __DIR__, + 'static_handler_locations' => ['/css', '/js', '/images', '/.well-known'], + 'buffer_output_size' => 4 * 1024 * 1024, + 'worker_num' => 4, + ]); + + $app = $this->app; + $app->map('stop', function (?int $code = null) use ($app) { + if ($code !== null) { + $app->response()->status($code); + } + }); + } + + protected function bindHttpEvent() { + $app = $this->app; + $AsyncBridge = new AsyncBridge($app); + + $this->Swoole->on('Start', function(SwooleServer $server) { + echo "Swoole http server is started at http://127.0.0.1:9501\n"; + }); + + $this->Swoole->on('Request', function (SwooleRequest $request, SwooleResponse $response) use ($AsyncBridge) { + $SwooleAsyncRequest = new SwooleAsyncRequest($request); + $SwooleAsyncResponse = new SwooleAsyncResponse($response); + + $AsyncBridge->processRequest($SwooleAsyncRequest, $SwooleAsyncResponse); + + $response->end(); + gc_collect_cycles(); + }); + } + + protected function bindWorkerEvents() { + $createPools = function() { + // create worker-specific connection pools here + }; + $closePools = function() { + // close pools / cleanup here + }; + $this->Swoole->on('WorkerStart', $createPools); + $this->Swoole->on('WorkerStop', $closePools); + $this->Swoole->on('WorkerError', $closePools); + } + + public function start() { + $this->Swoole->start(); + } +} +``` + +## Запуск сервера + +- Розробка (вбудований сервер PHP / PHP-FPM): + - php -S localhost:8000 (або додайте -t public/ якщо ваш index у public/) +- Продакшен (Swoole): + - php swoole_server.php + +Порада: Для продакшену використовуйте реверс-проксі (Nginx) перед Swoole для обробки TLS, статичних файлів та балансування навантаження. + +## Нотатки щодо конфігурації + +Драйвер Swoole надає кілька опцій конфігурації: +- worker_num: кількість процесів робочих +- max_request: запити на робочий перед перезапуском +- enable_coroutine: використання корутин для конкурентності +- buffer_output_size: розмір буфера виводу + +Налаштуйте ці параметри відповідно до ресурсів вашого хоста та шаблонів трафіку. + +## Обробка помилок + +AsyncBridge перетворює помилки Flight у правильні HTTP-відповіді. Ви також можете додати обробку помилок на рівні маршруту: + +```php +$app->route('/*', function() use ($app) { + try { + // route logic + } catch (Exception $e) { + $app->response()->status(500); + $app->json(['error' => $e->getMessage()]); + } +}); +``` + +## AdapterMan та інші середовища виконання + +[AdapterMan](https://github.com/joanhey/adapterman) підтримується як альтернативний адаптер середовища виконання. Пакет розроблено для адаптивності — додавання або використання інших адаптерів загалом слідує тому ж шаблону: перетворення серверного запиту/відповіді у запит/відповідь Flight через AsyncBridge та адаптери, специфічні для середовища. \ No newline at end of file diff --git a/content/v3/uk/awesome-plugins/awesome_plugins.md b/content/v3/uk/awesome-plugins/awesome_plugins.md index 2578c0dd..22a05c79 100644 --- a/content/v3/uk/awesome-plugins/awesome_plugins.md +++ b/content/v3/uk/awesome-plugins/awesome_plugins.md @@ -1,89 +1,95 @@ # Круті Плагіни -Flight є надзвичайно розширюваним. Існує низка плагінів, які можна використовувати для додавання функціональності до вашого додатку Flight. Деякі з них офіційно підтримуються командою Flight, а інші є мікро/лайт бібліотеками, щоб допомогти вам розпочати. +Flight є надзвичайно розширюваним. Існує низка плагінів, які можна використовувати для додавання функціональності до вашої програми Flight. Деякі з них офіційно підтримуються командою Flight, а інші є мікро/лайт бібліотеками, щоб допомогти вам розпочати. ## Документація API -Документація API є критичною для будь-якого API. Вона допомагає розробникам зрозуміти, як взаємодіяти з вашим API та що очікувати у відповідь. Існує кілька інструментів, доступних для допомоги у генерації документації API для ваших проєктів Flight. +Документація API є критичною для будь-якого API. Вона допомагає розробникам зрозуміти, як взаємодіяти з вашим API та що очікувати у відповідь. Існує кілька інструментів, доступних для допомоги у генерації документації API для ваших проектів Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Блог-пост, написаний Деніелом Шрайбером, про те, як використовувати специфікацію OpenAPI з FlightPHP для побудови вашого API з використанням підходу API first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI є чудовим інструментом для допомоги у генерації документації API для ваших проєктів Flight. Його дуже легко використовувати, і його можна налаштувати відповідно до ваших потреб. Це PHP-бібліотека для допомоги у генерації документації Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Публікація в блозі, написана Даніелем Шрайбером, про те, як використовувати специфікацію OpenAPI з FlightPHP для побудови вашого API з використанням підходу API first. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI є чудовим інструментом для допомоги у генерації документації API для ваших проектів Flight. Його дуже легко використовувати, і його можна налаштувати відповідно до ваших потреб. Це PHP-бібліотека для допомоги у генерації документації Swagger. -## Моніторинг Продуктивності Додатків (APM) +## Моніторинг Продуктивності Застосунку (APM) -Моніторинг продуктивності додатків (APM) є критичним для будь-якого додатку. Він допомагає вам зрозуміти, як працює ваш додаток і де знаходяться вузькі місця. Існує низка інструментів APM, які можна використовувати з Flight. -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM є простою бібліотекою APM, яка може використовуватися для моніторингу ваших додатків Flight. Її можна використовувати для моніторингу продуктивності вашого додатку та допомоги у виявленні вузьких місць. +Моніторинг продуктивності застосунку (APM) є критичним для будь-якого застосунку. Він допомагає вам зрозуміти, як працює ваш застосунок і де знаходяться вузькі місця. Існує низка інструментів APM, які можна використовувати з Flight. +- офіційний [flightphp/apm](/awesome-plugins/apm) - Flight APM є простою бібліотекою APM, яка може використовуватися для моніторингу ваших програм Flight. Її можна використовувати для моніторингу продуктивності вашого застосунку та допомоги у виявленні вузьких місць. + +## Асинхронність + +Flight вже є швидким фреймворком, але додавання до нього турбо-двигуна робить усе ще веселішим (і складнішим)! + +- [flightphp/async](/awesome-plugins/async) - Офіційна бібліотека Flight Async. Ця бібліотека є простим способом додати асинхронну обробку до вашого застосунку. Вона використовує Swoole/Openswoole під капотом, щоб надати простий та ефективний спосіб запуску завдань асинхронно. ## Авторизація/Дозволи -Авторизація та дозволи є критичними для будь-якого додатку, який вимагає контролю над тим, хто може отримати доступ до чого. +Авторизація та дозволи є критичними для будь-якого застосунку, який вимагає контролю за тим, хто може отримати доступ до чого. -- official [flightphp/permissions](/awesome-plugins/permissions) - Офіційна бібліотека Flight Permissions. Ця бібліотека є простим способом додавання дозволів на рівні користувача та додатку до вашого додатку. +- офіційний [flightphp/permissions](/awesome-plugins/permissions) - Офіційна бібліотека Flight Permissions. Ця бібліотека є простим способом додати дозволи на рівні користувача та застосунку до вашого застосунку. ## Кешування -Кешування є чудовим способом прискорити ваш додаток. Існує низка бібліотек кешування, які можна використовувати з Flight. +Кешування є чудовим способом прискорити ваш застосунок. Існує низка бібліотек кешування, які можна використовувати з Flight. -- official [flightphp/cache](/awesome-plugins/php-file-cache) - Легка, проста та автономна PHP-класа для кешування в файлі +- офіційний [flightphp/cache](/awesome-plugins/php-file-cache) - Легка, проста та автономна PHP-клас кешування в файлі ## CLI -CLI-додатки є чудовим способом взаємодіяти з вашим додатком. Ви можете використовувати їх для генерації контролерів, відображення всіх маршрутів та багато іншого. +CLI-застосунки є чудовим способом взаємодіяти з вашим застосунком. Ви можете використовувати їх для генерації контролерів, відображення всіх маршрутів та багато іншого. -- official [flightphp/runway](/awesome-plugins/runway) - Runway є CLI-додатком, який допомагає вам керувати вашими додатками Flight. +- офіційний [flightphp/runway](/awesome-plugins/runway) - Runway є CLI-застосунком, який допомагає вам керувати вашими програмами Flight. -## Кукі +## Куки -Кукі є чудовим способом зберігати невеликі фрагменти даних на стороні клієнта. Їх можна використовувати для зберігання уподобань користувача, налаштувань додатку та багато іншого. +Куки є чудовим способом зберігати малі шматки даних на стороні клієнта. Їх можна використовувати для зберігання уподобань користувача, налаштувань застосунку та багато іншого. -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie є PHP-бібліотекою, яка надає простий та ефективний спосіб керування кукі. +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie є PHP-бібліотекою, яка надає простий та ефективний спосіб керування куками. ## Налагодження Налагодження є критичним, коли ви розробляєте у локальному середовищі. Існує кілька плагінів, які можуть покращити ваш досвід налагодження. -- [tracy/tracy](/awesome-plugins/tracy) - Це повнофункціональний обробник помилок, який можна використовувати з Flight. Він має низку панелей, які можуть допомогти вам налагоджувати ваш додаток. Його також дуже легко розширювати та додавати власні панелі. -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Використовується з обробником помилок [Tracy](/awesome-plugins/tracy), цей плагін додає кілька додаткових панелей для допомоги у налагодженні, спеціально для проєктів Flight. +- [tracy/tracy](/awesome-plugins/tracy) - Це повнофункціональний обробник помилок, який можна використовувати з Flight. Він має низку панелей, які можуть допомогти вам налагоджувати ваш застосунок. Його також дуже легко розширювати та додавати власні панелі. +- офіційний [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Використовується з обробником помилок [Tracy](/awesome-plugins/tracy), цей плагін додає кілька додаткових панелей для допомоги з налагодженням спеціально для проектів Flight. ## Бази Даних -Бази даних є основою для більшості додатків. Це спосіб зберігати та отримувати дані. Деякі бібліотеки баз даних є просто обгортками для написання запитів, а деякі є повноцінними ORM. +Бази даних є основою для більшості застосунків. Це спосіб зберігати та отримувати дані. Деякі бібліотеки баз даних є просто обгортками для написання запитів, а деякі є повноцінними ORM. -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Офіційний обгортка Flight PDO, яка є частиною ядра. Це проста обгортка для спрощення процесу написання запитів та їх виконання. Це не ORM. -- official [flightphp/active-record](/awesome-plugins/active-record) - Офіційна ORM/Mapper Flight ActiveRecord. Чудова маленька бібліотека для легкого отримання та зберігання даних у вашій базі даних. -- [byjg/php-migration](/awesome-plugins/migrations) - Плагін для відстеження всіх змін бази даних для вашого проєкту. +- офіційний [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Офіційний обгорт Flight PDO, який є частиною ядра. Це проста обгортка, щоб спростити процес написання запитів та їх виконання. Це не ORM. +- офіційний [flightphp/active-record](/awesome-plugins/active-record) - Офіційний ORM/Mapper Flight ActiveRecord. Чудова маленька бібліотека для легкого отримання та зберігання даних у вашій базі даних. +- [byjg/php-migration](/awesome-plugins/migrations) - Плагін для відстеження всіх змін бази даних для вашого проекту. ## Шифрування -Шифрування є критичним для будь-якого додатку, який зберігає чутливі дані. Шифрування та дешифрування даних не є надто складними, але правильне зберігання ключа шифрування [може](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [бути](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [складним](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Найважливіше — ніколи не зберігати ключ шифрування у публічній директорії або комітити його до вашого репозиторію коду. +Шифрування є критичним для будь-якого застосунку, який зберігає чутливі дані. Шифрування та дешифрування даних не є надто складним, але правильне зберігання ключа шифрування [може](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [бути](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [складним](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Найважливіше — ніколи не зберігати ключ шифрування в публічній директорії або комітити його до вашого репозиторію коду. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Це бібліотека, яку можна використовувати для шифрування та дешифрування даних. Запуск та налаштування є досить простими для початку шифрування та дешифрування даних. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - Це бібліотека, яка може використовуватися для шифрування та дешифрування даних. Запуск та налаштування є досить простим для початку шифрування та дешифрування даних. ## Черга Завдань -Черги завдань дійсно корисні для асинхронної обробки завдань. Це може бути відправлення email, обробка зображень або будь-що, що не потребує виконання в реальному часі. +Черги завдань дійсно корисні для асинхронної обробки завдань. Це може бути відправка email, обробка зображень або будь-що, що не потребує виконання в реальному часі. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue є бібліотекою, яку можна використовувати для асинхронної обробки завдань. Її можна використовувати з beanstalkd, MySQL/MariaDB, SQLite та PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue є бібліотекою, яка може використовуватися для асинхронної обробки завдань. Її можна використовувати з beanstalkd, MySQL/MariaDB, SQLite та PostgreSQL. ## Сесії -Сесії не дуже корисні для API, але для побудови веб-додатку сесії можуть бути критичними для підтримки стану та інформації про вхід. +Сесії не дуже корисні для API, але для побудови веб-застосунку сесії можуть бути критичними для підтримки стану та інформації про вхід. -- official [flightphp/session](/awesome-plugins/session) - Офіційна бібліотека Flight Session. Це проста бібліотека сесій, яку можна використовувати для зберігання та отримання даних сесії. Вона використовує вбудоване керування сесіями PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (non-blocking, flash, segment, session encryption). Використовує PHP open_ssl для опціонального шифрування/дешифрування даних сесії. +- офіційний [flightphp/session](/awesome-plugins/session) - Офіційна бібліотека Flight Session. Це проста бібліотека сесій, яка може використовуватися для зберігання та отримання даних сесії. Вона використовує вбудоване керування сесіями PHP. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (неблокуючий, flash, сегмент, шифрування сесії). Використовує PHP open_ssl для необов'язкового шифрування/дешифрування даних сесії. ## Шаблонізація -Шаблонізація є основою для будь-якого веб-додатку з UI. Існує низка шаблонізаторів, які можна використовувати з Flight. +Шаблонізація є основою для будь-якого веб-застосунку з UI. Існує низка рушіїв шаблонізації, які можна використовувати з Flight. -- deprecated [flightphp/core View](/learn#views) - Це дуже базовий шаблонізатор, який є частиною ядра. Не рекомендується використовувати, якщо у вашому проєкті більше кількох сторінок. -- [latte/latte](/awesome-plugins/latte) - Latte є повнофункціональним шаблонізатором, який дуже легко використовувати та відчувається ближчим до синтаксису PHP, ніж Twig чи Smarty. Його також дуже легко розширювати та додавати власні фільтри та функції. +- застарілий [flightphp/core View](/learn#views) - Це дуже базовий рушій шаблонізації, який є частиною ядра. Не рекомендується використовувати, якщо у вашому проекті більше кількох сторінок. +- [latte/latte](/awesome-plugins/latte) - Latte є повнофункціональним рушієм шаблонізації, який дуже легко використовувати та відчувається ближчим до синтаксису PHP, ніж Twig чи Smarty. Його також дуже легко розширювати та додавати власні фільтри та функції. ## Інтеграція з WordPress -Хочете використовувати Flight у вашому проєкті WordPress? Є зручний плагін для цього! +Хочете використовувати Flight у вашому проекті WordPress? Є зручний плагін для цього! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Цей плагін WordPress дозволяє запускати Flight поруч з WordPress. Він ідеальний для додавання кастомних API, мікросервісів або навіть повноцінних додатків до вашого сайту WordPress з використанням фреймворку Flight. Надзвичайно корисний, якщо ви хочете найкраще з обох світів! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Цей плагін WordPress дозволяє запускати Flight поруч з WordPress. Він ідеальний для додавання кастомних API, мікросервісів або навіть повноцінних застосунків до вашого сайту WordPress з використанням фреймворку Flight. Надзвичайно корисний, якщо ви хочете найкраще з обох світів! ## Внесок diff --git a/content/v3/uk/examples.md b/content/v3/uk/examples.md index a81d45c4..415d826a 100644 --- a/content/v3/uk/examples.md +++ b/content/v3/uk/examples.md @@ -1,36 +1,37 @@ # Потрібен швидкий старт? -У вас є два варіанти, щоб почати новий проект на Flight: +У вас є два варіанти для початку роботи з новим проектом Flight: -- [Повний скелетний проект](https://github.com/flightphp/skeleton): Більш розгорнутий приклад з контролерами та видами. -- [Однофайловий скелетний проект](https://github.com/flightphp/skeleton-simple): Один файл, який включає все необхідне для запуску вашого додатку в одному простому файлі. +- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Більш повноцінний приклад з контролерами та видами. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Один файл, що містить усе необхідне для запуску вашого додатка в одному простому файлі. Приклади, надані спільнотою: -- [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP з директоріями Laravel, з PHP засобами + GH Actions -- [fleact](https://github.com/flightphp/fleact) - Стартовий набір для FlightPHP з інтеграцією ReactJS. -- [flastro](https://github.com/flightphp/flastro) - Стартовий набір для FlightPHP з інтеграцією Astro. -- [velt](https://github.com/flightphp/velt) - Velt - це швидкий та простий шаблон для Svelte з бекендом FlightPHP. - -## Потрібна трохи натхнення? - -Хоча ці проекти офіційно не спонсоруються командою Flight, вони можуть дати вам ідеї про те, як структуризувати власні проекти, побудовані на Flight! - -- [Decay](https://github.com/boxybird/decay) - Flight v3 з HTMX та SleekDB про зомбі! ([Демо](https://decay.andrewrhyand.com)) -- [Приклад блогу на Flight](https://github.com/n0nag0n/flightphp-blog) - Flight v3 з Middleware, контролерами, Active Record та Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Простий проект CRUD API, що використовує фреймворк Flight, який забезпечує базову структуру для нових користувачів, щоб швидко налаштувати PHP-додаток з операціями CRUD та підключенням до бази даних. Проект демонструє, як використовувати Flight для розробки RESTful API, що робить його ідеальним навчальним засобом для початківців та корисним стартовим набором для більш досвідчених розробників. -- [Система управління школою Flight](https://github.com/krmu/FlightPHP_School) - Flight v3 -- [Paste Bin з коментарями](https://github.com/n0nag0n/commie2) - Flight v3 -- [Базовий скелетний додаток](https://github.com/markhughes/flight-skeleton) -- [Приклад Вікі](https://github.com/Skayo/FlightWiki) -- [Застосунок PHP-фреймворку IT-Innovator](https://github.com/itinnovator/myphp-app) -- [LittleEducationalCMS (іспанською)](https://github.com/casgin/LittleEducationalCMS) -- [API жовтих сторінок Італії](https://github.com/chiccomagnus/PGAPI) -- [Універсальна система управління контентом (з....дуже малою документацією)](https://github.com/recepuncu/cms) -- [Маленький php фреймворк на основі Flight та medoo.](https://github.com/ycrao/tinyme) -- [Приклад MVC-додатку](https://github.com/paddypei/Flight-MVC) -- [Продукційно готовий шаблон Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Готовий до використання фреймворк автентифікації, який заощаджує вам тижні розробки. Забезпечує безпеку корпоративного рівня: 2FA/TOTP, інтеграцію LDAP, єдиний вхід Azure, інтелектуальне обмеження швидкості, відбитки сеансів, захист методом повного перебору, панель інструментів аналітики безпеки, комплексне ведення журналу аудиту та детальний контроль доступу на основі ролей. - -## Хочете поділитися власним прикладом? - -Якщо у вас є проект, яким ви хочете поділитися, будь ласка, подайте запит на злиття, щоб додати його до цього списку! \ No newline at end of file +- [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP з директоріями Laravel, з інструментами PHP + GH Actions +- [fleact](https://github.com/flightphp/fleact) - Стартові набір FlightPHP з інтеграцією ReactJS. +- [flastro](https://github.com/flightphp/flastro) - Стартові набір FlightPHP з інтеграцією Astro. +- [velt](https://github.com/flightphp/velt) - Velt — це швидкий і простий шаблон Svelte з бекендом на FlightPHP. + +## Потрібне натхнення? + +Хоча ці приклади не спонсоровані офіційно командою Flight, вони можуть дати вам ідеї щодо структуризації власних проектів, побудованих на Flight! + +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental — це односторінковий, мобільно-дружній веб-додаток для оренди автомобілів, побудований на PHP (FlightPHP), JavaScript та MySQL. Він підтримує реєстрацію користувачів, перегляд та бронювання автомобілів, тоді як адміністратори можуть керувати автомобілями, користувачами та бронюваннями. Додаток має REST API, JWT-аутентифікацію та адаптивний дизайн для сучасного досвіду оренди. +- [Decay](https://github.com/boxybird/decay) - Flight v3 з HTMX та SleekDB, все про зомбі! ([Demo](https://decay.andrewrhyand.com)) +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 з Middleware, Controllers, Active Record та Latte. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Простий проект CRUD API з використанням фреймворку Flight, який надає базову структуру для нових користувачів, щоб швидко налаштувати PHP-додаток з операціями CRUD та підключенням до бази даних. Проект демонструє, як використовувати Flight для розробки RESTful API, роблячи його ідеальним навчальним інструментом для початківців та корисним стартовим набором для більш досвідчених розробників. +- [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 +- [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 +- [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) +- [Example Wiki](https://github.com/Skayo/FlightWiki) +- [The IT-Innovator PHP Framework Application](https://github.com/itinnovator/myphp-app) +- [LittleEducationalCMS (Spanish)](https://github.com/casgin/LittleEducationalCMS) +- [Italian Yellow Pages API](https://github.com/chiccomagnus/PGAPI) +- [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) +- [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) +- [Example MVC Application](https://github.com/paddypei/Flight-MVC) +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Готовий до виробництва фреймворк аутентифікації, який заощаджує тижні розробки. Функції корпоративного рівня безпеки: 2FA/TOTP, інтеграція LDAP, Azure SSO, інтелектуальне обмеження швидкості, відбитки сесій, захист від brute-force, панель аналітики безпеки, всебічний аудит-логування та гранульний контроль доступу на основі ролей. + +## Хочете поділитися своїм прикладом? + +Якщо у вас є проект, яким ви хочете поділитися, будь ласка, надішліть pull request, щоб додати його до цього списку! \ No newline at end of file diff --git a/content/v3/uk/learn/requests.md b/content/v3/uk/learn/requests.md index d6b7b8a5..8659ad47 100644 --- a/content/v3/uk/learn/requests.md +++ b/content/v3/uk/learn/requests.md @@ -10,13 +10,13 @@ $request = Flight::request(); ## Розуміння -HTTP-запити є одним з основних аспектів, які потрібно розуміти про життєвий цикл HTTP. Користувач виконує дію в веб-браузері або HTTP-клієнті, і вони надсилають серію заголовків, тіла, URL тощо до вашого проекту. Ви можете захоплювати ці заголовки (мова браузера, тип стиснення, який вони можуть обробляти, user agent тощо) і захоплювати тіло та URL, що надсилається до вашої програми Flight. Ці запити є суттєвими для вашої програми, щоб зрозуміти, що робити далі. +HTTP-запити є одним з основних аспектів, які потрібно розуміти щодо життєвого циклу HTTP. Користувач виконує дію в веб-браузері або HTTP-клієнті, і вони надсилають серію заголовків, тіла, URL тощо до вашого проекту. Ви можете захоплювати ці заголовки (мова браузера, тип стиснення, який вони можуть обробляти, user agent тощо) і захоплювати тіло та URL, що надсилаються до вашої програми Flight. Ці запити є суттєвими для вашої програми, щоб зрозуміти, що робити далі. ## Базове використання PHP має кілька суперглобальних змінних, включаючи `$_GET`, `$_POST`, `$_REQUEST`, `$_SERVER`, `$_FILES` та `$_COOKIE`. Flight абстрагує їх у зручні [Collections](/learn/collections). Ви можете отримати доступ до властивостей `query`, `data`, `cookies` та `files` як до масивів або об'єктів. -> **Примітка:** **НАСТІЛЬКИ** не рекомендується використовувати ці суперглобальні змінні у вашому проекті, і вони повинні посилатися через об'єкт `request()`. +> **Примітка:** **НАЙКАТЕГОРІЧНІШЕ** не рекомендується використовувати ці суперглобальні змінні у вашому проекті, і їх слід посилатися через об'єкт `request()`. > **Примітка:** Немає доступної абстракції для `$_ENV`. @@ -68,7 +68,7 @@ Flight::route('GET /login', function(){ }); ``` -Для допомоги з встановленням нових значень cookie дивіться [overclokk/cookie](/awesome-plugins/php-cookie) +Для допомоги щодо встановлення нових значень cookie дивіться [overclokk/cookie](/awesome-plugins/php-cookie) ### `$_SERVER` @@ -107,7 +107,7 @@ Flight::route('POST /upload', function(){ }); ``` -Якщо у вас завантажено кілька файлів, ви можете перебрати їх: +Якщо у вас завантажено кілька файлів, ви можете перебирати їх: ```php Flight::route('POST /upload', function(){ @@ -119,7 +119,7 @@ Flight::route('POST /upload', function(){ }); ``` -> **Примітка щодо безпеки:** Завжди валідуйте та очищайте вхідні дані користувача, особливо при роботі з завантаженням файлів. Завжди валідуйте типи розширень, які ви дозволите завантажувати, але ви також повинні валідувати "магічні байти" файлу, щоб переконатися, що це дійсно тип файлу, який стверджує користувач. Є [статті](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [та](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [бібліотеки](https://github.com/RikudouSage/MimeTypeDetector), доступні для допомоги з цим. +> **Примітка щодо безпеки:** Завжди валідуйте та очищайте вхідні дані користувача, особливо при роботі з завантаженням файлів. Завжди валідуйте типи розширень, які ви дозволите завантажувати, але також валідуйте "магічні байти" файлу, щоб переконатися, що це дійсно тип файлу, який стверджує користувач. Є [статті](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [та](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [бібліотеки](https://github.com/RikudouSage/MimeTypeDetector), доступні для допомоги з цим. ### Тіло запиту @@ -187,11 +187,11 @@ $method = Flight::request()->getMethod(); - **type** - Тип вмісту - **length** - Довжина вмісту - **query** - Параметри рядка запиту -- **data** - Дані POST або JSON-дані +- **data** - Дані POST або JSON-даних - **cookies** - Дані cookie - **files** - Завантажені файли -- **secure** - Чи є з'єднання безпечним -- **accept** - Параметри HTTP accept +- **secure** - Чи є з'єднання захищеним +- **accept** - HTTP параметри accept - **proxy_ip** - IP-адреса проксі клієнта. Сканує масив `$_SERVER` на `HTTP_CLIENT_IP`, `HTTP_X_FORWARDED_FOR`, `HTTP_X_FORWARDED`, `HTTP_X_CLUSTER_CLIENT_IP`, `HTTP_FORWARDED_FOR`, `HTTP_FORWARDED` в такому порядку. - **host** - Ім'я хоста запиту - **servername** - SERVER_NAME з `$_SERVER` @@ -228,7 +228,7 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); // ['foo' => 'bar'] ``` -## Переговори щодо типів прийнятого вмісту +## Переговори щодо типів вмісту Accept _v3.17.2_ @@ -251,17 +251,17 @@ if ($typeToServe === 'application/json') { > **Примітка:** Якщо жоден з доступних типів не знайдено в заголовку `Accept`, метод поверне `null`. Якщо заголовок `Accept` не визначено, метод поверне перший тип у масиві `$availableTypes`. -## Дивіться також +## Див. також - [Routing](/learn/routing) - Дивіться, як відображати маршрути на контролери та рендерити види. - [Responses](/learn/responses) - Як налаштовувати HTTP-відповіді. - [Why a Framework?](/learn/why-frameworks) - Як запити вписуються в загальну картину. - [Collections](/learn/collections) - Робота з колекціями даних. - [Uploaded File Handler](/learn/uploaded-file) - Обробка завантаження файлів. -## Усунення несправностей -- `request()->ip` та `request()->proxy_ip` можуть відрізнятися, якщо ваш веб-сервер стоїть за проксі, балансувальником навантаження тощо. +## Вирішення проблем +- `request()->ip` та `request()->proxy_ip` можуть відрізнятися, якщо ваш веб-сервер знаходиться за проксі, балансувальником навантаження тощо. ## Журнал змін - v3.17.2 - Додано negotiateContentType() -- v3.12.0 - Додано можливість обробки завантаження файлів через об'єкт запиту. +- v3.12.0 - Додано можливість обробляти завантаження файлів через об'єкт запиту. - v1.0 - Початкове випущення. \ No newline at end of file diff --git a/content/v3/uk/learn/routing.md b/content/v3/uk/learn/routing.md index bdc5e869..e4239a50 100644 --- a/content/v3/uk/learn/routing.md +++ b/content/v3/uk/learn/routing.md @@ -1,17 +1,17 @@ # Маршрутизація ## Огляд -Маршрутизація в Flight PHP відображає шаблони URL на функції зворотного виклику або методи класів, що забезпечує швидку та просту обробку запитів. Вона розроблена для мінімального навантаження, зручного використання для початківців та розширюваності без зовнішніх залежностей. +Маршрутизація в Flight PHP відображає шаблони URL на функції зворотного виклику або методи класів, що забезпечує швидке та просте оброблення запитів. Вона розроблена для мінімального навантаження, зручного використання для початківців та розширюваності без зовнішніх залежностей. ## Розуміння -Маршрутизація є основним механізмом, який з'єднує HTTP-запити з логікою вашого додатка в Flight. Визначаючи маршрути, ви вказуєте, як різні URL запускають конкретний код, чи то через функції, методи класів, чи дії контролера. Система маршрутизації Flight гнучка, підтримує базові шаблони, іменовані параметри, регулярні вирази та розширені функції, такі як ін'єкція залежностей та ресурсна маршрутизація. Цей підхід тримає ваш код організованим та легким у підтримці, залишаючись швидким і простим для початківців та розширюваним для просунутих користувачів. +Маршрутизація є основним механізмом, який з'єднує HTTP-запити з логікою вашого додатка в Flight. Визначаючи маршрути, ви вказуєте, як різні URL викликають конкретний код, чи то через функції, методи класів, чи дії контролера. Система маршрутизації Flight є гнучкою, підтримує базові шаблони, іменовані параметри, регулярні вирази та розширені функції, такі як ін'єкція залежностей та ресурсна маршрутизація. Цей підхід тримає ваш код організованим і легким у підтримці, залишаючись швидким та простим для початківців і розширюваним для просунутих користувачів. -> **Примітка:** Хочете дізнатися більше про маршрутизацію? Перегляньте сторінку ["why a framework?"](/learn/why-frameworks) для детальнішого пояснення. +> **Примітка:** Хочете дізнатися більше про маршрутизацію? Перегляньте сторінку ["why a framework?"](/learn/why-frameworks) для більш детального пояснення. -## Базове використання +## Основне використання ### Визначення простого маршруту -Базова маршрутизація в Flight виконується шляхом співставлення шаблону URL з функцією зворотного виклику або масивом класу та методу. +Основна маршрутизація в Flight виконується шляхом співставлення шаблону URL з функцією зворотного виклику або масивом класу та методу. ```php Flight::route('/', function(){ @@ -22,7 +22,7 @@ Flight::route('/', function(){ > Маршрути співставляються в порядку їх визначення. Перший маршрут, що співпадає з запитом, буде викликаний. ### Використання функцій як зворотних викликів -Зворотний виклик може бути будь-яким об'єктом, який є викличним. Отже, ви можете використовувати звичайну функцію: +Зворотний виклик може бути будь-яким об'єктом, який є викликаним. Тому ви можете використовувати звичайну функцію: ```php function hello() { @@ -32,7 +32,7 @@ function hello() { Flight::route('/', 'hello'); ``` -### Використання класів та методів як контролера +### Використання класів і методів як контролера Ви також можете використовувати метод (статичний чи ні) класу: ```php @@ -77,11 +77,11 @@ $greeting = new GreetingController($app); Flight::route('/', [ $greeting, 'hello' ]); ``` -> **Примітка:** За замовчуванням, коли контролер викликається в рамках, клас `flight\Engine` завжди інжектується, якщо ви не вказуєте через [контейнер ін'єкції залежностей](/learn/dependency-injection-container) +> **Примітка:** За замовчуванням, коли контролер викликається в рамках фреймворку, клас `flight\Engine` завжди інжектується, якщо ви не вказуєте через [контейнер ін'єкції залежностей](/learn/dependency-injection-container) ### Маршрутизація, специфічна для методу -За замовчуванням шаблони маршрутів співставляються з усіма методами запитів. Ви можете реагувати на конкретні методи, розміщуючи ідентифікатор перед URL. +За замовчуванням шаблони маршрутів співставляються з усіма методами запитів. Ви можете відповідати на конкретні методи, розміщуючи ідентифікатор перед URL. ```php Flight::route('GET /', function () { @@ -114,8 +114,8 @@ Flight надає вбудовану обробку для HTTP-запитів ` #### Запити HEAD -- **Запити HEAD** обробляються так само, як запити `GET`, але Flight автоматично видаляє тіло відповіді перед відправкою її клієнту. -- Це означає, що ви можете визначити маршрут для `GET`, і запити HEAD до того самого URL повернуть лише заголовки (без вмісту), як очікується стандартами HTTP. +- **Запити HEAD** обробляються так само, як запити `GET`, але Flight автоматично видаляє тіло відповіді перед відправкою його клієнту. +- Це означає, що ви можете визначити маршрут для `GET`, і запити HEAD на той самий URL повертатимуть тільки заголовки (без вмісту), як очікується за стандартами HTTP. ```php Flight::route('GET /info', function() { @@ -128,7 +128,7 @@ Flight::route('GET /info', function() { Запити `OPTIONS` автоматично обробляються Flight для будь-якого визначеного маршруту. - Коли отримано запит OPTIONS, Flight відповідає статусом `204 No Content` та заголовком `Allow`, що перелічує всі підтримувані HTTP-методи для цього маршруту. -- Вам не потрібно визначати окремий маршрут для OPTIONS, якщо ви не хочете кастомну поведінку або модифікувати відповідь. +- Вам не потрібно визначати окремий маршрут для OPTIONS. ```php // For a route defined as: @@ -142,7 +142,7 @@ Flight::route('GET|POST /users', function() { /* ... */ }); ### Використання об'єкта Router -Крім того, ви можете отримати об'єкт Router, який має деякі допоміжні методи для вашого використання: +Крім того, ви можете отримати об'єкт Router, який має деякі допоміжні методи для використання: ```php @@ -172,10 +172,12 @@ Flight::route('/user/[0-9]+', function () { }); ``` -Хоча цей метод доступний, рекомендується використовувати іменовані параметри або іменовані параметри з регулярними виразами, оскільки вони більш читабельні та легші у підтримці. +Хоча цей метод доступний, рекомендується використовувати іменовані параметри або +іменовані параметри з регулярними виразами, оскільки вони більш читабельні та легші в підтримці. ### Іменовані параметри -Ви можете вказувати іменовані параметри у ваших маршрутах, які будуть передані до вашої функції зворотного виклику. **Це більше для читабельності маршруту, ніж для чогось іншого. Будь ласка, дивіться розділ нижче щодо важливого застереження.** +Ви можете вказувати іменовані параметри у ваших маршрутах, які будуть передані до +вашої функції зворотного виклику. **Це більше для читабельності маршруту, ніж для чогось іншого. Будь ласка, дивіться розділ нижче щодо важливого застереження.** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -183,7 +185,8 @@ Flight::route('/@name/@id', function (string $name, string $id) { }); ``` -Ви також можете включати регулярні вирази з вашими іменованими параметрами, використовуючи роздільник `:`: +Ви також можете включати регулярні вирази з вашими іменованими параметрами, використовуючи +роздільник `:`: ```php Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { @@ -192,11 +195,11 @@ Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { }); ``` -> **Примітка:** Співставлення груп regex `()` з позиційними параметрами не підтримується. Ex: `:'\(` +> **Примітка:** Співставлення груп regex `()` з позиційними параметрами не підтримується. Приклад: `:'\(` #### Важливе застереження -Хоча в прикладі вище здається, що `@name` безпосередньо пов'язаний з змінною `$name`, це не так. Порядок параметрів у функції зворотного виклику визначає, що передається до неї. Якщо ви поміняєте порядок параметрів у функції зворотного виклику, змінні також поміняються. Ось приклад: +Хоча в прикладі вище здається, що `@name` безпосередньо пов'язаний зі змінною `$name`, це не так. Порядок параметрів у функції зворотного виклику визначає, що передається до неї. Якщо ви зміните порядок параметрів у функції зворотного виклику, змінні також зміняться. Ось приклад: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -204,11 +207,12 @@ Flight::route('/@name/@id', function (string $id, string $name) { }); ``` -І якщо ви перейдете за наступним URL: `/bob/123`, вивід буде `hello, 123 (bob)!`. +І якщо ви перейдете за таким URL: `/bob/123`, вивід буде `hello, 123 (bob)!`. _Будьте обережні_ при налаштуванні ваших маршрутів та функцій зворотного виклику! ### Необов'язкові параметри -Ви можете вказувати іменовані параметри, які є необов'язковими для співставлення, обгортаючи сегменти в дужки. +Ви можете вказувати іменовані параметри, які є необов'язковими для співставлення, обгортаючи +сегменти в дужки. ```php Flight::route( @@ -225,8 +229,9 @@ Flight::route( Будь-які необов'язкові параметри, які не співпадають, будуть передані як `NULL`. -### Дикий символ у маршрутизації -Співставлення виконується лише для окремих сегментів URL. Якщо ви хочете співставити кілька сегментів, ви можете використовувати дикий символ `*`. +### Дикі карти в маршрутизації +Співставлення виконується тільки для окремих сегментів URL. Якщо ви хочете співставити кілька +сегментів, ви можете використовувати символ дикого `*`. ```php Flight::route('/blog/*', function () { @@ -234,7 +239,7 @@ Flight::route('/blog/*', function () { }); ``` -Щоб маршрутизувати всі запити до одного зворотного виклику, ви можете зробити: +Щоб маршрутизувати всі запити на один зворотний виклик, ви можете зробити: ```php Flight::route('*', function () { @@ -244,7 +249,7 @@ Flight::route('*', function () { ### Обробник 404 Not Found -За замовчуванням, якщо URL не знайдено, Flight надішле просту та звичайну відповідь `HTTP 404 Not Found`. +За замовчуванням, якщо URL не знайдено, Flight надішле відповідь `HTTP 404 Not Found`, яка є дуже простою та звичайною. Якщо ви хочете мати більш кастомізовану відповідь 404, ви можете [відобразити](/learn/extending) свій власний метод `notFound`: ```php @@ -267,7 +272,7 @@ Flight::map('notFound', function() { ### Обробник Method Not Found -За замовчуванням, якщо URL знайдено, але метод не дозволено, Flight надішле просту та звичайну відповідь `HTTP 405 Method Not Allowed` (Ex: Method Not Allowed. Allowed Methods are: GET, POST). Він також включить заголовок `Allow` з дозволеними методами для цього URL. +За замовчуванням, якщо URL знайдено, але метод не дозволено, Flight надішле відповідь `HTTP 405 Method Not Allowed`, яка є дуже простою та звичайною (Наприклад: Method Not Allowed. Allowed Methods are: GET, POST). Вона також включатиме заголовок `Allow` з дозволеними методами для цього URL. Якщо ви хочете мати більш кастомізовану відповідь 405, ви можете [відобразити](/learn/extending) свій власний метод `methodNotFound`: @@ -297,7 +302,8 @@ Flight::map('methodNotFound', function(Route $route) { ## Розширене використання ### Ін'єкція залежностей у маршрутах -Якщо ви хочете використовувати ін'єкцію залежностей через контейнер (PSR-11, PHP-DI, Dice тощо), єдиний тип маршрутів, де це доступно, — це безпосереднє створення об'єкта самостійно та використання контейнера для створення вашого об'єкта, або ви можете використовувати рядки для визначення класу та методу для виклику. Ви можете перейти на сторінку [Dependency Injection](/learn/dependency-injection-container) для отримання додаткової інформації. +Якщо ви хочете використовувати ін'єкцію залежностей через контейнер (PSR-11, PHP-DI, Dice тощо), єдиний тип маршрутів, де це доступно, — це або безпосереднє створення об'єкта самостійно та використання контейнера для створення вашого об'єкта, або ви можете використовувати рядки для визначення класу та методу для виклику. Ви можете перейти на сторінку [Dependency Injection](/learn/dependency-injection-container) для +більшої інформації. Ось швидкий приклад: @@ -353,7 +359,8 @@ Flight::start(); ### Передача виконання наступному маршруту Deprecated -Ви можете передати виконання наступному співставленому маршруту, повертаючи `true` з вашої функції зворотного виклику. +Ви можете передати виконання наступному співпадаючому маршруту, повертаючи `true` з +вашої функції зворотного виклику. ```php Flight::route('/user/@name', function (string $name) { @@ -372,7 +379,7 @@ Flight::route('/user/*', function () { Тепер рекомендується використовувати [middleware](/learn/middleware) для обробки складних випадків, як цей. ### Псевдоніми маршрутів -Призначаючи псевдонім маршруту, ви можете пізніше динамічно викликати цей псевдонім у вашому додатку, щоб згенерувати його пізніше у вашому коді (наприклад: посилання в HTML-шаблоні або генерація URL для перенаправлення). +Призначаючи псевдонім маршруту, ви можете пізніше динамічно викликати цей псевдонім у вашому додатку, щоб згенерувати його пізніше в коді (наприклад: посилання в HTML-шаблоні або генерація URL для перенаправлення). ```php Flight::route('/users/@id', function($id) { echo 'user:'.$id; }, false, 'user_view'); @@ -393,10 +400,10 @@ class UserController { ``` -Це особливо корисно, якщо ваш URL змінюється. У прикладі вище, припустимо, що users переміщено до `/admin/users/@id` замість. +Це особливо корисно, якщо ваш URL змінюється. У прикладі вище, припустимо, що користувачі переміщені до `/admin/users/@id` замість. З псевдонімами на місці для маршруту, вам більше не потрібно шукати всі старі URL у вашому коді та змінювати їх, оскільки псевдонім тепер поверне `/admin/users/5`, як у прикладі вище. -Псевдоніми маршрутів все ще працюють у групах: +Псевдоніми маршрутів також працюють у групах: ```php Flight::group('/users', function() { @@ -407,10 +414,10 @@ Flight::group('/users', function() { ``` ### Перевірка інформації про маршрут -Якщо ви хочете перевірити інформацію про співставлений маршрут, є 2 способи це зробити: +Якщо ви хочете перевірити інформацію про співпадаючий маршрут, є 2 способи це зробити: 1. Ви можете використовувати властивість `executedRoute` на об'єкті `Flight::router()`. -2. Ви можете запросити об'єкт маршруту для передачі до вашого зворотного виклику, передаючи `true` як третій параметр у методі маршруту. Об'єкт маршруту завжди буде останнім параметром, переданим до вашої функції зворотного виклику. +2. Ви можете запросити передачу об'єкта маршруту до вашого зворотного виклику, передавши `true` як третій параметр у методі маршруту. Об'єкт маршруту завжди буде останнім параметром, переданим до вашої функції зворотного виклику. #### `executedRoute` ```php @@ -440,7 +447,7 @@ Flight::route('/', function() { }); ``` -> **Примітка:** Властивість `executedRoute` буде встановлена лише після виконання маршруту. Якщо ви спробуєте отримати до неї доступ до виконання маршруту, вона буде `NULL`. Ви також можете використовувати executedRoute у [middleware](/learn/middleware)! +> **Примітка:** Властивість `executedRoute` буде встановлена тільки після виконання маршруту. Якщо ви спробуєте отримати доступ до неї перед виконанням маршруту, вона буде `NULL`. Ви також можете використовувати executedRoute у [middleware](/learn/middleware)! #### Передача `true` до визначення маршруту ```php @@ -532,7 +539,7 @@ $app->group('/api/v1', function (Router $router) { }); ``` -> **Примітка:** Це перевага метод визначення маршрутів та груп з об'єктом `$router`. +> **Примітка:** Це перевага метод визначення маршрутів і груп з об'єктом `$router`. #### Групування з Middleware @@ -549,7 +556,8 @@ Flight::group('/api/v1', function () { Дивіться більше деталей на сторінці [group middleware](/learn/middleware#grouping-middleware). ### Ресурсна маршрутизація -Ви можете створити набір маршрутів для ресурсу, використовуючи метод `resource`. Це створить набір маршрутів для ресурсу, що слідує конвенціям RESTful. +Ви можете створювати набір маршрутів для ресурсу, використовуючи метод `resource`. Це створить +набір маршрутів для ресурсу, що відповідає RESTful-конвенціям. Щоб створити ресурс, зробіть наступне: @@ -557,7 +565,7 @@ Flight::group('/api/v1', function () { Flight::resource('/users', UsersController::class); ``` -І те, що станеться в тлі, — це створення наступних маршрутів: +І що станеться в фоні — це створення наступних маршрутів: ```php [ @@ -606,11 +614,11 @@ class UsersController } ``` -> **Примітка**: Ви можете переглянути новододаноти маршрути з `runway`, запустивши `php runway routes`. +> **Примітка**: Ви можете переглядати щойно додані маршрути з `runway`, запустивши `php runway routes`. -#### Налаштування ресурсів маршрутів +#### Налаштування ресурсних маршрутів -Є кілька опцій для налаштування ресурсів маршрутів. +Є кілька опцій для налаштування ресурсних маршрутів. ##### Базовий псевдонім @@ -641,7 +649,7 @@ Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'st ##### Middleware -Ви також можете вказати middleware для виконання на кожному з маршрутів, створених методом `resource`. +Ви також можете вказати middleware, яке буде виконуватися для кожного з маршрутів, створених методом `resource`. ```php Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMiddleware::class ] ]); @@ -649,17 +657,17 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid ### Потокові відповіді -Ви тепер можете потокувати відповіді клієнту, використовуючи `stream()` або `streamWithHeaders()`. +Ви тепер можете потоково передавати відповіді клієнту, використовуючи `stream()` або `streamWithHeaders()`. Це корисно для відправки великих файлів, довготривалих процесів або генерації великих відповідей. -Потокування маршруту обробляється трохи інакше, ніж звичайний маршрут. +Потокова передача маршруту обробляється трохи інакше, ніж звичайний маршрут. -> **Примітка:** Потокові відповіді доступні лише якщо у вас встановлено [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) на `false`. +> **Примітка:** Потокові відповіді доступні тільки якщо у вас встановлено [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) на `false`. -#### Поток з ручними заголовками +#### Потік з ручними заголовками -Ви можете потокувати відповідь клієнту, використовуючи метод `stream()` на маршруті. Якщо ви +Ви можете потоково передавати відповідь клієнту, використовуючи метод `stream()` на маршруті. Якщо ви зробите це, ви мусите встановити всі заголовки вручну перед тим, як вивести щось клієнту. -Це робиться з функцією php `header()` або методом `Flight::response()->setRealHeader()`. +Це робиться з функцією `header()` php або методом `Flight::response()->setRealHeader()`. ```php Flight::route('/@filename', function($filename) { @@ -695,9 +703,9 @@ Flight::route('/@filename', function($filename) { })->stream(); ``` -#### Поток з заголовками +#### Потік з заголовками -Ви також можете використовувати метод `streamWithHeaders()` для встановлення заголовків перед початком потокування. +Ви також можете використовувати метод `streamWithHeaders()`, щоб встановити заголовки перед початком потокової передачі. ```php Flight::route('/stream-users', function() { @@ -734,19 +742,20 @@ Flight::route('/stream-users', function() { - [Middleware](/learn/middleware) - Використання middleware з маршрутами для аутентифікації, логування тощо. - [Dependency Injection](/learn/dependency-injection-container) - Спрощення створення та керування об'єктами в маршрутах. - [Why a Framework?](/learn/why-frameworks) - Розуміння переваг використання фреймворку, як Flight. -- [Extending](/learn/extending) - Як розширити Flight своєю функціональністю, включаючи метод `notFound`. +- [Extending](/learn/extending) - Як розширити Flight власною функціональністю, включаючи метод `notFound`. - [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - Функція PHP для співставлення регулярних виразів. -## Усунення несправностей -- Параметри маршруту співставляються за порядком, а не за іменем. Переконайтеся, що порядок параметрів зворотного виклику відповідає визначенню маршруту. +## Вирішення проблем +- Параметри маршруту співставляються за порядком, а не за ім'ям. Переконайтеся, що порядок параметрів зворотного виклику відповідає визначенню маршруту. - Використання `Flight::get()` не визначає маршрут; використовуйте `Flight::route('GET /...')` для маршрутизації або контекст об'єкта Router у групах (наприклад, `$router->get(...)`). -- Властивість executedRoute встановлюється лише після виконання маршруту; вона NULL перед виконанням. -- Потокування вимагає вимкнення функціональності буферизації виводу Flight (`flight.v2.output_buffering = false`). -- Для ін'єкції залежностей лише певні визначення маршрутів підтримують інстанціювання на основі контейнера. +- Властивість executedRoute встановлюється тільки після виконання маршруту; вона NULL перед виконанням. +- Потокова передача вимагає відключення функціональності буферизації виводу Flight (`flight.v2.output_buffering = false`). +- Для ін'єкції залежностей тільки певні визначення маршрутів підтримують інстанціацію на основі контейнера. ### 404 Not Found або несподівана поведінка маршруту -Якщо ви бачите помилку 404 Not Found (але ви присягаєтеся своїм життям, що вона дійсно там і це не помилка друку), це насправді може бути проблема з тим, що ви повертаєте значення в ендпоінті маршруту замість просто виведення його. Причина для цього навмисна, але може заскочити деяких розробників. +Якщо ви бачите помилку 404 Not Found (але ви присягаєтеся своїм життям, що вона дійсно там і це не помилка друку), це насправді може бути проблема +з поверненням значення у вашому кінцевому пункті маршруту замість простого виведення. Причина для цього навмисна, але може заскочити деяких розробників. ```php Flight::route('/hello', function(){ @@ -760,9 +769,9 @@ Flight::route('/hello', function(){ }); ``` -Причина для цього полягає в спеціальному механізмі, вбудованому в роутер, який обробляє повернений вивід як сигнал "перейти до наступного маршруту". +Причина для цього — спеціальний механізм, вбудований у роутер, який обробляє вивід повернення як сигнал "перейти до наступного маршруту". Ви можете побачити поведінку, документовану в розділі [Routing](/learn/routing#passing). ## Журнал змін -- v3: Додано ресурсну маршрутизацію, псевдоніми маршрутів та підтримку потокування, групи маршрутів та підтримку middleware. +- v3: Додано ресурсну маршрутизацію, псевдоніми маршрутів, підтримку потокової передачі, групи маршрутів та підтримку middleware. - v1: Більшість базових функцій доступні. \ No newline at end of file diff --git a/content/v3/zh/awesome-plugins/async.md b/content/v3/zh/awesome-plugins/async.md new file mode 100644 index 00000000..dceb761f --- /dev/null +++ b/content/v3/zh/awesome-plugins/async.md @@ -0,0 +1,212 @@ +# 异步 + +Async 是 Flight 框架的一个小型包,它允许您在异步服务器和运行时环境中运行 Flight 应用,例如 Swoole、AdapterMan、ReactPHP、Amp、RoadRunner、Workerman 等。开箱即用,它包含 Swoole 和 AdapterMan 的适配器。 + +目标:使用 PHP-FPM(或内置服务器)进行开发和调试,并在生产环境中切换到 Swoole(或其他异步驱动程序),只需最少的更改。 + +## 要求 + +- PHP 7.4 或更高版本 +- Flight 框架 3.16.1 或更高版本 +- [Swoole 扩展](https://www.openswoole.com) + +## 安装 + +通过 Composer 安装: + +```bash +composer require flightphp/async +``` + +如果您计划使用 Swoole 运行,请安装扩展: + +```bash +# 使用 pecl +pecl install swoole +# 或 openswoole +pecl install openswoole + +# 或使用包管理器(Debian/Ubuntu 示例) +sudo apt-get install php-swoole +``` + +## Swoole 快速示例 + +下面是一个最小设置示例,展示如何使用相同的代码库支持 PHP-FPM(或内置服务器)和 Swoole。 + +您项目中需要以下文件: + +- index.php +- swoole_server.php +- SwooleServerDriver.php + +### index.php + +此文件是一个简单的开关,用于在开发模式下强制应用以 PHP 模式运行。 + +```php +// index.php +route('/', function() use ($app) { + $app->json(['hello' => 'world']); +}); + +if (!defined('NOT_SWOOLE')) { + // 在 Swoole 模式下运行时要求 SwooleServerDriver 类。 + require_once __DIR__ . '/SwooleServerDriver.php'; + + Swoole\Runtime::enableCoroutine(); + $Swoole_Server = new SwooleServerDriver('127.0.0.1', 9501, $app); + $Swoole_Server->start(); +} else { + $app->start(); +} +``` + +### SwooleServerDriver.php + +一个简洁的驱动程序,展示如何使用 AsyncBridge 和 Swoole 适配器将 Swoole 请求桥接到 Flight。 + +```php +// SwooleServerDriver.php +Swoole = new SwooleServer($host, $port); + $this->app = $app; + + $this->setDefault(); + $this->bindWorkerEvents(); + $this->bindHttpEvent(); + } + + protected function setDefault() { + $this->Swoole->set([ + 'daemonize' => false, + 'dispatch_mode' => 1, + 'max_request' => 8000, + 'open_tcp_nodelay' => true, + 'reload_async' => true, + 'max_wait_time' => 60, + 'enable_reuse_port' => true, + 'enable_coroutine' => true, + 'http_compression' => false, + 'enable_static_handler' => true, + 'document_root' => __DIR__, + 'static_handler_locations' => ['/css', '/js', '/images', '/.well-known'], + 'buffer_output_size' => 4 * 1024 * 1024, + 'worker_num' => 4, + ]); + + $app = $this->app; + $app->map('stop', function (?int $code = null) use ($app) { + if ($code !== null) { + $app->response()->status($code); + } + }); + } + + protected function bindHttpEvent() { + $app = $this->app; + $AsyncBridge = new AsyncBridge($app); + + $this->Swoole->on('Start', function(SwooleServer $server) { + echo "Swoole http server is started at http://127.0.0.1:9501\n"; + }); + + $this->Swoole->on('Request', function (SwooleRequest $request, SwooleResponse $response) use ($AsyncBridge) { + $SwooleAsyncRequest = new SwooleAsyncRequest($request); + $SwooleAsyncResponse = new SwooleAsyncResponse($response); + + $AsyncBridge->processRequest($SwooleAsyncRequest, $SwooleAsyncResponse); + + $response->end(); + gc_collect_cycles(); + }); + } + + protected function bindWorkerEvents() { + $createPools = function() { + // 在此处创建特定于工作进程的连接池 + }; + $closePools = function() { + // 在此处关闭池 / 清理 + }; + $this->Swoole->on('WorkerStart', $createPools); + $this->Swoole->on('WorkerStop', $closePools); + $this->Swoole->on('WorkerError', $closePools); + } + + public function start() { + $this->Swoole->start(); + } +} +``` + +## 运行服务器 + +- 开发(PHP 内置服务器 / PHP-FPM): + - php -S localhost:8000(如果您的 index 在 public/ 中,请添加 -t public/) +- 生产(Swoole): + - php swoole_server.php + +提示:对于生产环境,请在 Swoole 前使用反向代理(Nginx)来处理 TLS、静态文件和负载均衡。 + +## 配置说明 + +Swoole 驱动程序暴露了几个配置选项: +- worker_num:工作进程数量 +- max_request:每个工作进程的重启前请求数 +- enable_coroutine:使用协程进行并发 +- buffer_output_size:输出缓冲区大小 + +根据您的主机资源和流量模式调整这些设置。 + +## 错误处理 + +AsyncBridge 将 Flight 错误转换为正确的 HTTP 响应。您还可以添加路由级别的错误处理: + +```php +$app->route('/*', function() use ($app) { + try { + // 路由逻辑 + } catch (Exception $e) { + $app->response()->status(500); + $app->json(['error' => $e->getMessage()]); + } +}); +``` + +## AdapterMan 和其他运行时 + +[AdapterMan](https://github.com/joanhey/adapterman) 被支持作为替代运行时适配器。该包设计为可适配的——添加或使用其他适配器通常遵循相同的模式:通过 AsyncBridge 和特定于运行时的适配器将服务器请求/响应转换为 Flight 的请求/响应。 \ No newline at end of file diff --git a/content/v3/zh/awesome-plugins/awesome_plugins.md b/content/v3/zh/awesome-plugins/awesome_plugins.md index 444d34e6..fc6415de 100644 --- a/content/v3/zh/awesome-plugins/awesome_plugins.md +++ b/content/v3/zh/awesome-plugins/awesome_plugins.md @@ -1,24 +1,30 @@ -# 优秀插件 +# 精彩插件 -Flight 具有极强的可扩展性。有许多插件可用于为您的 Flight 应用程序添加功能。其中一些由 Flight 团队官方支持,其他则是一些微型/轻量级库,帮助您快速上手。 +Flight 极具可扩展性。有许多插件可用于为您的 Flight 应用程序添加功能。其中一些由 Flight 团队正式支持,其他则是帮助您入门的小型/轻量级库。 ## API 文档 -API 文档对于任何 API 都至关重要。它帮助开发者理解如何与您的 API 交互以及预期返回结果。有一些工具可用于帮助您为 Flight 项目生成 API 文档。 +API 文档对任何 API 都至关重要。它帮助开发者理解如何与您的 API 交互以及期望返回的内容。有几个工具可用于帮助您为 Flight 项目生成 API 文档。 -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - 由 Daniel Schreiber 撰写的博客文章,介绍如何使用 OpenAPI 规范与 FlightPHP 结合,采用 API 优先方法构建您的 API。 +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - 由 Daniel Schreiber 撰写的博客文章,介绍如何使用 OpenAPI 规范与 FlightPHP 结合,以 API 优先方法构建您的 API。 - [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI 是一个优秀的工具,可帮助您为 Flight 项目生成 API 文档。它非常易用,并且可以自定义以满足您的需求。这是用于生成 Swagger 文档的 PHP 库。 ## 应用程序性能监控 (APM) -应用程序性能监控 (APM) 对于任何应用程序都至关重要。它帮助您了解应用程序的性能表现以及瓶颈所在。有许多 APM 工具可与 Flight 一起使用。 +应用程序性能监控 (APM) 对任何应用程序都至关重要。它帮助您了解应用程序的性能以及瓶颈所在。有许多 APM 工具可与 Flight 一起使用。 - official [flightphp/apm](/awesome-plugins/apm) - Flight APM 是一个简单的 APM 库,可用于监控您的 Flight 应用程序。它可用于监控应用程序性能并帮助您识别瓶颈。 +## 异步 + +Flight 已经是一个快速的框架,但为其添加涡轮引擎会让一切变得更有趣(且具挑战性)! + +- [flightphp/async](/awesome-plugins/async) - 官方 Flight Async 库。此库是一种简单的方式,可为您的应用程序添加异步处理。它在底层使用 Swoole/Openswoole,提供简单有效的任务异步运行方式。 + ## 授权/权限 -授权和权限对于任何需要控制访问权限的应用程序都至关重要。 +授权和权限对任何需要控制访问权限的应用程序都至关重要。 -- official [flightphp/permissions](/awesome-plugins/permissions) - 官方 Flight 权限库。该库是一种简单的方式,为您的应用程序添加用户和应用程序级别的权限。 +- official [flightphp/permissions](/awesome-plugins/permissions) - 官方 Flight Permissions 库。此库是一种简单的方式,可为您的应用程序添加用户和应用程序级别的权限。 ## 缓存 @@ -32,36 +38,36 @@ CLI 应用程序是与您的应用程序交互的绝佳方式。您可以使用 - official [flightphp/runway](/awesome-plugins/runway) - Runway 是一个 CLI 应用程序,帮助您管理 Flight 应用程序。 -## Cookie +## Cookies -Cookie 是存储客户端小块数据的绝佳方式。它们可用于存储用户偏好、应用程序设置等。 +Cookies 是存储客户端小量数据的绝佳方式。它们可用于存储用户偏好、应用程序设置等。 -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie 是一个 PHP 库,提供了一种简单有效的管理 Cookie 的方式。 +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie 是一个 PHP 库,提供简单有效的 cookies 管理方式。 ## 调试 在本地环境中开发时,调试至关重要。有几个插件可以提升您的调试体验。 -- [tracy/tracy](/awesome-plugins/tracy) - 这是一个功能齐全的错误处理器,可与 Flight 一起使用。它有多个面板可帮助您调试应用程序。它也非常易于扩展并添加您自己的面板。 -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - 与 [Tracy](/awesome-plugins/tracy) 错误处理器一起使用,该插件添加了一些额外的面板,专门帮助调试 Flight 项目。 +- [tracy/tracy](/awesome-plugins/tracy) - 这是一个功能齐全的错误处理程序,可与 Flight 一起使用。它有多个面板可帮助您调试应用程序。它也非常易于扩展并添加您自己的面板。 +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - 与 [Tracy](/awesome-plugins/tracy) 错误处理程序一起使用,此插件添加了一些额外的面板,专门帮助调试 Flight 项目。 ## 数据库 数据库是大多数应用程序的核心。这是存储和检索数据的方式。有些数据库库只是用于编写查询的包装器,有些则是完整的 ORM。 -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 官方 Flight PDO 包装器,是核心的一部分。这是一个简单的包装器,帮助简化编写和执行查询的过程。它不是 ORM。 -- official [flightphp/active-record](/awesome-plugins/active-record) - 官方 Flight ActiveRecord ORM/映射器。一个优秀的库,用于轻松检索和存储数据库中的数据。 -- [byjg/php-migration](/awesome-plugins/migrations) - 用于跟踪项目中所有数据库变更的插件。 +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 官方 Flight PDO Wrapper,是核心的一部分。这是一个简单的包装器,帮助简化编写和执行查询的过程。它不是 ORM。 +- official [flightphp/active-record](/awesome-plugins/active-record) - 官方 Flight ActiveRecord ORM/Mapper。优秀的库,用于轻松检索和存储数据库中的数据。 +- [byjg/php-migration](/awesome-plugins/migrations) - 用于跟踪项目所有数据库变更的插件。 ## 加密 -对于任何存储敏感数据的应用程序,加密至关重要。加密和解密数据并不难,但正确存储加密密钥 [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [很](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [困难](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)。最重要的是,切勿将加密密钥存储在公共目录中或提交到您的代码仓库。 +加密对任何存储敏感数据的应用程序都至关重要。加密和解密数据并不太难,但正确存储加密密钥 [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [会](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [困难](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)。最重要的是,切勿将加密密钥存储在公共目录中或提交到代码仓库。 - [defuse/php-encryption](/awesome-plugins/php-encryption) - 这是一个可用于加密和解密数据的库。启动并运行非常简单,即可开始加密和解密数据。 ## 作业队列 -作业队列对于异步处理任务非常有用。这可以是发送电子邮件、处理图像或任何不需要实时完成的任务。 +作业队列对于异步处理任务非常有帮助。这可以包括发送电子邮件、处理图像或任何不需要实时完成的任务。 - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue 是一个库,可用于异步处理作业。它可与 beanstalkd、MySQL/MariaDB、SQLite 和 PostgreSQL 一起使用。 @@ -69,21 +75,21 @@ Cookie 是存储客户端小块数据的绝佳方式。它们可用于存储用 会话对于 API 并不太有用,但对于构建 Web 应用程序,会话对于维护状态和登录信息至关重要。 -- official [flightphp/session](/awesome-plugins/session) - 官方 Flight 会话库。这是一个简单的会话库,可用于存储和检索会话数据。它使用 PHP 内置的会话处理。 -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 会话管理器(非阻塞、闪存、段、会话加密)。使用 PHP open_ssl 可选地加密/解密会话数据。 +- official [flightphp/session](/awesome-plugins/session) - 官方 Flight Session 库。这是一个简单的会话库,可用于存储和检索会话数据。它使用 PHP 内置的会话处理。 +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager(非阻塞、闪存、分段、会话加密)。使用 PHP open_ssl 进行可选的会话数据加密/解密。 ## 模板 模板是任何具有 UI 的 Web 应用程序的核心。有许多模板引擎可与 Flight 一起使用。 -- deprecated [flightphp/core View](/learn#views) - 这是一个非常基本的模板引擎,是核心的一部分。如果您的项目有超过几个页面,不推荐使用。 -- [latte/latte](/awesome-plugins/latte) - Latte 是一个功能齐全的模板引擎,非常易用,其语法更接近 PHP 而非 Twig 或 Smarty。它也非常易于扩展并添加您自己的过滤器和函数。 +- deprecated [flightphp/core View](/learn#views) - 这是一个非常基本的模板引擎,是核心的一部分。如果您的项目有超过几页,不推荐使用。 +- [latte/latte](/awesome-plugins/latte) - Latte 是一个功能齐全的模板引擎,非常易用,其语法比 Twig 或 Smarty 更接近 PHP。它也非常易于扩展并添加您自己的过滤器和函数。 ## WordPress 集成 想在您的 WordPress 项目中使用 Flight 吗?有一个方便的插件可供使用! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 这个 WordPress 插件让您可以与 WordPress 并行运行 Flight。它非常适合使用 Flight 框架为您的 WordPress 站点添加自定义 API、微服务甚至完整应用程序。如果您想兼顾两者,这是超级有用的! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 此 WordPress 插件允许您在 WordPress 旁边运行 Flight。它非常适合使用 Flight 框架为您的 WordPress 站点添加自定义 API、微服务,甚至完整应用程序。如果您想兼得两者的优点,这超级有用! ## 贡献 diff --git a/content/v3/zh/examples.md b/content/v3/zh/examples.md index ff9e24c7..4bf23702 100644 --- a/content/v3/zh/examples.md +++ b/content/v3/zh/examples.md @@ -1,36 +1,37 @@ -# 需要快速入门吗? +# 需要快速开始吗? -您有两种选择可以开始一个新的 Flight 项目: +您有两种选项来开始一个新的 Flight 项目: -- [完整骨架样板](https://github.com/flightphp/skeleton):一个更完整的示例,包含控制器和视图。 -- [单文件骨架样板](https://github.com/flightphp/skeleton-simple):一个包含运行您的应用所需所有内容的单一简单文件。 +- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton):一个更完整的示例,包括控制器和视图。 +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple):一个单一文件,包含运行您的应用程序所需的一切,简单易用。 社区贡献的示例: -- [flightravel](https://github.com/fadrian06-templates/flighravel):带有 PHP 工具 + GH Actions 的 FlightPHP 和 Laravel 目录 -- [fleact](https://github.com/flightphp/fleact) - 带有 ReactJS 集成的 FlightPHP 启动工具包。 -- [flastro](https://github.com/flightphp/flastro) - 带有 Astro 集成的 FlightPHP 启动工具包。 -- [velt](https://github.com/flightphp/velt) - Velt 是一个快速简单的 Svelte 启动模板,带有 FlightPHP 后端。 +- [flightravel](https://github.com/fadrian06-templates/flighravel):FlightPHP 与 Laravel 目录结合,带有 PHP 工具 + GH Actions +- [fleact](https://github.com/flightphp/fleact) - 一个带有 ReactJS 集成的 FlightPHP 启动套件。 +- [flastro](https://github.com/flightphp/flastro) - 一个带有 Astro 集成的 FlightPHP 启动套件。 +- [velt](https://github.com/flightphp/velt) - Velt 是一个快速易用的 Svelte 启动模板,带有 FlightPHP 后端。 ## 需要一些灵感吗? -虽然这些不是官方由 Flight 团队赞助的,但它们可以给您一些构建自己的 Flight 项目结构的想法! - -- [Decay](https://github.com/boxybird/decay) - Flight v3,使用 HTMX 和 SleekDB,主题为僵尸! ([演示](https://decay.andrewrhyand.com)) -- [Flight 示例博客](https://github.com/n0nag0n/flightphp-blog) - Flight v3,使用中间件、控制器、活动记录和 Latte。 -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - 使用 Flight 框架的简单 CRUD API 项目,为新用户提供一个基本结构,以快速设置带有 CRUD 操作和数据库连接的 PHP 应用。该项目演示了如何使用 Flight 进行 RESTful API 开发,使其成为初学者的理想学习工具,以及对于更有经验的开发人员来说是一个有用的启动工具包。 -- [Flight 学校管理系统](https://github.com/krmu/FlightPHP_School) - Flight v3 -- [带评论的 Paste Bin](https://github.com/n0nag0n/commie2) - Flight v3 -- [基本骨架应用](https://github.com/markhughes/flight-skeleton) -- [示例 Wiki](https://github.com/Skayo/FlightWiki) -- [IT创新者 PHP 框架应用](https://github.com/itinnovator/myphp-app) -- [LittleEducationalCMS (西班牙语)](https://github.com/casgin/LittleEducationalCMS) -- [意大利黄页 API](https://github.com/chiccomagnus/PGAPI) -- [通用内容管理系统(带有……非常少的文档)](https://github.com/recepuncu/cms) -- [基于 Flight 和 medoo 的小型 PHP 框架。](https://github.com/ycrao/tinyme) -- [示例 MVC 应用](https://github.com/paddypei/Flight-MVC) -- [生產就緒的 Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 一款生產就緒的驗證框架,可為您節省數週的開發時間。它具備企業級安全性:2FA/TOTP、LDAP 整合、Azure SSO、智慧限速、會話指紋辨識、暴力破解保護、安全分析儀表板、全面的稽核日誌記錄以及基於角色的細粒度存取控制。 - -## 想要分享您自己的示例吗? - -如果您有一个项目想要分享,请提交拉取请求以将其添加到此列表中! \ No newline at end of file +虽然这些并非由 Flight 团队正式赞助,但它们可以为您构建基于 Flight 的项目提供结构思路! + +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental 是一个单页、移动友好的汽车租赁 Web 应用程序,使用 PHP (FlightPHP)、JavaScript 和 MySQL 构建。它支持用户注册、浏览和预订汽车,而管理员可以管理汽车、用户和预订。该应用程序具有 REST API、JWT 认证和响应式设计,提供现代租赁体验。 +- [Decay](https://github.com/boxybird/decay) - Flight v3 与 HTMX 和 SleekDB 结合,全是关于僵尸的!([Demo](https://decay.andrewrhyand.com)) +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 带有中间件、控制器、Active Record 和 Latte。 +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - 使用 Flight 框架的简单 CRUD API 项目,为新用户提供基本结构,快速设置带有 CRUD 操作和数据库连接的 PHP 应用程序。该项目演示了如何使用 Flight 进行 RESTful API 开发,是初学者理想的学习工具,也是经验丰富的开发者的有用启动套件。 +- [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 +- [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 +- [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) +- [Example Wiki](https://github.com/Skayo/FlightWiki) +- [The IT-Innovator PHP Framework Application](https://github.com/itinnovator/myphp-app) +- [LittleEducationalCMS (Spanish)](https://github.com/casgin/LittleEducationalCMS) +- [Italian Yellow Pages API](https://github.com/chiccomagnus/PGAPI) +- [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) +- [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) +- [Example MVC Application](https://github.com/paddypei/Flight-MVC) +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 生产就绪的认证框架,可节省数周开发时间。具有企业级安全功能:2FA/TOTP、LDAP 集成、Azure SSO、智能速率限制、会话指纹识别、暴力破解保护、安全分析仪表板、全面审计日志以及细粒度基于角色的访问控制。 + +## 想分享您自己的示例吗? + +如果您有一个想分享的项目,请提交拉取请求将其添加到此列表中! \ No newline at end of file diff --git a/content/v3/zh/learn/requests.md b/content/v3/zh/learn/requests.md index 948cd115..e2147e22 100644 --- a/content/v3/zh/learn/requests.md +++ b/content/v3/zh/learn/requests.md @@ -2,7 +2,7 @@ ## 概述 -Flight 将 HTTP 请求封装到一个对象中,可以通过以下方式访问: +Flight 将 HTTP 请求封装成一个单一的对象,可以通过以下方式访问: ```php $request = Flight::request(); @@ -10,19 +10,19 @@ $request = Flight::request(); ## 理解 -HTTP 请求是理解 HTTP 生命周期的核心方面之一。用户在 Web 浏览器或 HTTP 客户端上执行操作,他们会向您的项目发送一系列头部、主体、URL 等。您可以捕获这些头部(浏览器的语言、他们能处理的压缩类型、用户代理等),并捕获发送到您的 Flight 应用程序的主体和 URL。这些请求对于您的应用程序了解下一步该做什么至关重要。 +HTTP 请求是理解 HTTP 生命周期的核心方面之一。用户在网页浏览器或 HTTP 客户端上执行一个操作,他们会向你的项目发送一系列头部、主体、URL 等。你可以捕获这些头部(浏览器的语言、他们能处理的压缩类型、用户代理等),并捕获发送到你的 Flight 应用程序的主体和 URL。这些请求对于你的应用程序了解下一步该做什么至关重要。 ## 基本用法 -PHP 有几个超级全局变量,包括 `$_GET`、`$_POST`、`$_REQUEST`、`$_SERVER`、`$_FILES` 和 `$_COOKIE`。Flight 将这些抽象为方便的 [Collections](/learn/collections)。您可以像数组或对象一样访问 `query`、`data`、`cookies` 和 `files` 属性。 +PHP 有几个超级全局变量,包括 `$_GET`、`$_POST`、`$_REQUEST`、`$_SERVER`、`$_FILES` 和 `$_COOKIE`。Flight 将这些抽象成方便的 [Collections](/learn/collections)。你可以将 `query`、`data`、`cookies` 和 `files` 属性访问为数组或对象。 -> **注意:** 强烈不鼓励在您的项目中使用这些超级全局变量,应该通过 `request()` 对象来引用它们。 +> **注意:** 强烈不鼓励在你的项目中使用这些超级全局变量,应该通过 `request()` 对象来引用它们。 > **注意:** `$_ENV` 没有可用的抽象。 ### `$_GET` -您可以通过 `query` 属性访问 `$_GET` 数组: +你可以通过 `query` 属性访问 `$_GET` 数组: ```php // GET /search?keyword=something @@ -30,14 +30,14 @@ Flight::route('/search', function(){ $keyword = Flight::request()->query['keyword']; // 或 $keyword = Flight::request()->query->keyword; - echo "您正在搜索:$keyword"; + echo "You are searching for: $keyword"; // 使用 $keyword 查询数据库或其他内容 }); ``` ### `$_POST` -您可以通过 `data` 属性访问 `$_POST` 数组: +你可以通过 `data` 属性访问 `$_POST` 数组: ```php Flight::route('POST /submit', function(){ @@ -46,21 +46,21 @@ Flight::route('POST /submit', function(){ // 或 $name = Flight::request()->data->name; $email = Flight::request()->data->email; - echo "您提交了:$name, $email"; + echo "You submitted: $name, $email"; // 使用 $name 和 $email 保存到数据库或其他内容 }); ``` ### `$_COOKIE` -您可以通过 `cookies` 属性访问 `$_COOKIE` 数组: +你可以通过 `cookies` 属性访问 `$_COOKIE` 数组: ```php Flight::route('GET /login', function(){ $savedLogin = Flight::request()->cookies['myLoginCookie']; // 或 $savedLogin = Flight::request()->cookies->myLoginCookie; - // 检查是否真的保存了,如果是则自动登录 + // 检查它是否真的保存了,如果是则自动登录 if($savedLogin) { Flight::redirect('/dashboard'); return; @@ -81,10 +81,10 @@ $host = Flight::request()->getVar('HTTP_HOST'); ### `$_FILES` -您可以通过 `files` 属性访问上传的文件: +你可以通过 `files` 属性访问上传的文件: ```php -// 直接访问 $_FILES 属性。有关推荐方法,请参阅下方 +// 直接访问 $_FILES 属性。以下是推荐的方法 $uploadedFile = Flight::request()->files['myFile']; // 或 $uploadedFile = Flight::request()->files->myFile; @@ -96,22 +96,22 @@ $uploadedFile = Flight::request()->files->myFile; _v3.12.0_ -您可以使用框架的一些辅助方法来处理文件上传。它基本上归结为从请求中拉取文件数据,并将其移动到新位置。 +你可以使用框架的一些辅助方法来处理文件上传。它基本上归结为从请求中拉取文件数据,并将其移动到新位置。 ```php Flight::route('POST /upload', function(){ - // 如果您有一个像 这样的输入字段 + // 如果你有一个输入字段如 $uploadedFileData = Flight::request()->getUploadedFiles(); $uploadedFile = $uploadedFileData['myFile']; $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); }); ``` -如果您上传了多个文件,可以循环遍历它们: +如果你有多个文件上传,可以循环遍历它们: ```php Flight::route('POST /upload', function(){ - // 如果您有一个像 这样的输入字段 + // 如果你有一个输入字段如 $uploadedFiles = Flight::request()->getUploadedFiles()['myFiles']; foreach ($uploadedFiles as $uploadedFile) { $uploadedFile->moveTo('/path/to/uploads/' . $uploadedFile->getClientFilename()); @@ -119,11 +119,11 @@ Flight::route('POST /upload', function(){ }); ``` -> **安全注意:** 始终验证和清理用户输入,尤其是在处理文件上传时。始终验证您允许上传的扩展类型,但您还应该验证文件的“魔术字节”以确保它是用户声称的文件类型。有 [文章](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [和](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [库](https://github.com/RikudouSage/MimeTypeDetector) 可帮助您完成此操作。 +> **安全注意:** 始终验证和清理用户输入,特别是处理文件上传时。始终验证你允许上传的扩展类型,但你还应该验证文件的“魔术字节”以确保它是用户声称的文件类型。有 [文章](https://dev.to/yasuie/php-file-upload-check-uploaded-files-with-magic-bytes-54oe) [和](https://amazingalgorithms.com/snippets/php/detecting-the-mime-type-of-an-uploaded-file-using-magic-bytes/) [库](https://github.com/RikudouSage/MimeTypeDetector) 可帮助处理此问题。 ### 请求主体 -要获取原始 HTTP 请求主体,例如在处理 POST/PUT 请求时,可以这样做: +要获取原始 HTTP 请求主体,例如处理 POST/PUT 请求时,你可以这样做: ```php Flight::route('POST /users/xml', function(){ @@ -134,7 +134,7 @@ Flight::route('POST /users/xml', function(){ ### JSON 主体 -如果您收到内容类型为 `application/json` 的请求,并且示例数据为 `{"id": 123}`,它将从 `data` 属性可用: +如果你收到内容类型为 `application/json` 的请求,并且示例数据为 `{"id": 123}`,它将从 `data` 属性可用: ```php $id = Flight::request()->data->id; @@ -142,16 +142,16 @@ $id = Flight::request()->data->id; ### 请求头部 -您可以使用 `getHeader()` 或 `getHeaders()` 方法访问请求头部: +你可以使用 `getHeader()` 或 `getHeaders()` 方法访问请求头部: ```php -// 也许您需要 Authorization 头部 +// 也许你需要 Authorization 头部 $host = Flight::request()->getHeader('Authorization'); // 或 $host = Flight::request()->header('Authorization'); -// 如果您需要获取所有头部 +// 如果你需要获取所有头部 $headers = Flight::request()->getHeaders(); // 或 $headers = Flight::request()->headers(); @@ -159,10 +159,10 @@ $headers = Flight::request()->headers(); ### 请求方法 -您可以使用 `method` 属性或 `getMethod()` 方法访问请求方法: +你可以使用 `method` 属性或 `getMethod()` 方法访问请求方法: ```php -$method = Flight::request()->method; // 实际由 getMethod() 填充 +$method = Flight::request()->method; // 实际上由 getMethod() 填充 $method = Flight::request()->getMethod(); ``` @@ -178,7 +178,7 @@ $method = Flight::request()->getMethod(); - **method** - 请求方法 (GET, POST, PUT, DELETE) - **referrer** - 引用 URL - **ip** - 客户端 IP 地址 -- **ajax** - 是否为 AJAX 请求 +- **ajax** - 请求是否为 AJAX 请求 - **scheme** - 服务器协议 (http, https) - **user_agent** - 浏览器信息 - **type** - 内容类型 @@ -187,9 +187,9 @@ $method = Flight::request()->getMethod(); - **data** - 帖子数据或 JSON 数据 - **cookies** - Cookie 数据 - **files** - 上传的文件 -- **secure** - 是否为安全连接 +- **secure** - 连接是否安全 - **accept** - HTTP 接受参数 -- **proxy_ip** - 客户端代理 IP 地址。按顺序扫描 `$_SERVER` 数组中的 `HTTP_CLIENT_IP`、`HTTP_X_FORWARDED_FOR`、`HTTP_X_FORWARDED`、`HTTP_X_CLUSTER_CLIENT_IP`、`HTTP_FORWARDED_FOR`、`HTTP_FORWARDED`。 +- **proxy_ip** - 客户端的代理 IP 地址。按顺序扫描 `$_SERVER` 数组中的 `HTTP_CLIENT_IP`、`HTTP_X_FORWARDED_FOR`、`HTTP_X_FORWARDED`、`HTTP_X_CLUSTER_CLIENT_IP`、`HTTP_FORWARDED_FOR`、`HTTP_FORWARDED`。 - **host** - 请求主机名 - **servername** - 来自 `$_SERVER` 的 SERVER_NAME @@ -199,7 +199,7 @@ $method = Flight::request()->getMethod(); ### 完整 URL -您可以使用 `getFullUrl()` 方法访问完整的请求 URL: +你可以使用 `getFullUrl()` 方法访问完整的请求 URL: ```php $url = Flight::request()->getFullUrl(); @@ -208,7 +208,7 @@ $url = Flight::request()->getFullUrl(); ### 基础 URL -您可以使用 `getBaseUrl()` 方法访问基础 URL: +你可以使用 `getBaseUrl()` 方法访问基础 URL: ```php // http://example.com/path/to/something/cool?query=yes+thanks @@ -219,7 +219,7 @@ $url = Flight::request()->getBaseUrl(); ## 查询解析 -您可以将 URL 传递给 `parseQuery()` 方法,将查询字符串解析为关联数组: +你可以将 URL 传递给 `parseQuery()` 方法来解析查询字符串为关联数组: ```php $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); @@ -230,18 +230,18 @@ $query = Flight::request()->parseQuery('https://example.com/some/path?foo=bar'); _v3.17.2_ -您可以使用 `negotiateContentType()` 方法,根据客户端发送的 `Accept` 头部确定最佳响应内容类型。 +你可以使用 `negotiateContentType()` 方法根据客户端发送的 `Accept` 头部确定最佳响应内容类型。 ```php // 示例 Accept 头部:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 -// 下方定义您支持的内容。 +// 下面定义你支持的内容。 $availableTypes = ['application/json', 'application/xml']; $typeToServe = Flight::request()->negotiateContentType($availableTypes); if ($typeToServe === 'application/json') { - // 提供 JSON 响应 + // 服务 JSON 响应 } elseif ($typeToServe === 'application/xml') { - // 提供 XML 响应 + // 服务 XML 响应 } else { // 默认使用其他内容或抛出错误 } @@ -250,14 +250,14 @@ if ($typeToServe === 'application/json') { > **注意:** 如果在 `Accept` 头部中找不到任何可用类型,该方法将返回 `null`。如果没有定义 `Accept` 头部,该方法将返回 `$availableTypes` 数组中的第一个类型。 ## 另请参阅 -- [Routing](/learn/routing) - 了解如何将路由映射到控制器并渲染视图。 +- [Routing](/learn/routing) - 查看如何将路由映射到控制器并渲染视图。 - [Responses](/learn/responses) - 如何自定义 HTTP 响应。 - [Why a Framework?](/learn/why-frameworks) - 请求如何融入大局。 - [Collections](/learn/collections) - 处理数据集合。 - [Uploaded File Handler](/learn/uploaded-file) - 处理文件上传。 ## 故障排除 -- 如果您的 Web 服务器位于代理、负载均衡器等后面,`request()->ip` 和 `request()->proxy_ip` 可能不同。 +- 如果你的 Web 服务器位于代理、负载均衡器等后面,`request()->ip` 和 `request()->proxy_ip` 可能不同。 ## 更新日志 - v3.17.2 - 添加了 negotiateContentType() diff --git a/content/v3/zh/learn/routing.md b/content/v3/zh/learn/routing.md index a98efc9d..c0bbffbd 100644 --- a/content/v3/zh/learn/routing.md +++ b/content/v3/zh/learn/routing.md @@ -4,14 +4,14 @@ Flight PHP 中的路由将 URL 模式映射到回调函数或类方法,从而实现快速且简单的请求处理。它设计用于最小开销、适合初学者的使用方式,并且无需外部依赖即可扩展。 ## 理解 -路由是 Flight 中连接 HTTP 请求与应用程序逻辑的核心机制。通过定义路由,您可以指定不同 URL 如何触发特定代码,无论是通过函数、类方法还是控制器动作。Flight 的路由系统灵活,支持基本模式、命名参数、正则表达式,以及依赖注入和资源路由等高级功能。这种方法使您的代码保持组织性和易维护性,同时对初学者快速简单,对高级用户可扩展。 +路由是 Flight 中将 HTTP 请求连接到应用程序逻辑的核心机制。通过定义路由,您可以指定不同 URL 如何触发特定代码,无论是通过函数、类方法还是控制器操作。Flight 的路由系统灵活,支持基本模式、命名参数、正则表达式,以及依赖注入和资源路由等高级功能。这种方法使您的代码保持组织性和易维护性,同时对初学者快速简单,对高级用户可扩展。 -> **注意:** 想了解更多关于路由的信息?请查看 ["为什么使用框架?"](/learn/why-frameworks) 页面,以获取更深入的解释。 +> **注意:** 想了解更多关于路由的信息?请查看 ["为什么使用框架?"](/learn/why-frameworks) 页面以获取更深入的解释。 ## 基本用法 ### 定义简单路由 -Flight 中的基本路由通过将 URL 模式与回调函数或类和方法的数组匹配来实现。 +Flight 中的基本路由是通过将 URL 模式与回调函数或类和方法的数组匹配来完成的。 ```php Flight::route('/', function(){ @@ -19,7 +19,7 @@ Flight::route('/', function(){ }); ``` -> 路由按照定义顺序匹配。第一个匹配请求的路由将被调用。 +> 路由按照定义的顺序进行匹配。第一个匹配请求的路由将被调用。 ### 使用函数作为回调 回调可以是任何可调用的对象。因此,您可以使用普通函数: @@ -51,7 +51,7 @@ Flight::route('/', [ 'GreetingController::hello' ]); Flight::route('/', [ 'GreetingController->hello' ]); ``` -或者先创建对象,然后调用方法: +或者先创建一个对象,然后调用该方法: ```php use flight\Engine; @@ -114,21 +114,21 @@ Flight 为 `HEAD` 和 `OPTIONS` HTTP 请求提供内置处理: #### HEAD 请求 -- **HEAD 请求** 被视为与 `GET` 请求相同,但 Flight 在发送给客户端之前自动移除响应体。 -- 这意味着您可以为 `GET` 定义路由,HEAD 请求到同一 URL 将仅返回标头(无内容),符合 HTTP 标准。 +- **HEAD 请求** 被视为与 `GET` 请求相同,但 Flight 在发送到客户端之前自动移除响应主体。 +- 这意味着您可以为 `GET` 定义一个路由,HEAD 请求到同一 URL 将仅返回标头(无内容),符合 HTTP 标准。 ```php Flight::route('GET /info', function() { echo 'This is some info!'; }); -// HEAD 请求到 /info 将返回相同的标头,但无体。 +// HEAD 请求到 /info 将返回相同的标头,但无主体。 ``` #### OPTIONS 请求 `OPTIONS` 请求由 Flight 为任何定义的路由自动处理。 - 当收到 OPTIONS 请求时,Flight 以 `204 No Content` 状态响应,并包含 `Allow` 标头,列出该路由支持的所有 HTTP 方法。 -- 除非您想要自定义行为或修改响应,否则无需为 OPTIONS 定义单独路由。 +- 您无需为 OPTIONS 定义单独的路由。 ```php // 对于定义为: @@ -142,7 +142,7 @@ Flight::route('GET|POST /users', function() { /* ... */ }); ### 使用路由器对象 -此外,您可以获取路由器对象,它提供了一些辅助方法供您使用: +此外,您可以获取路由器对象,它有一些辅助方法供您使用: ```php @@ -175,7 +175,7 @@ Flight::route('/user/[0-9]+', function () { 虽然此方法可用,但推荐使用命名参数,或带有正则表达式的命名参数,因为它们更易读且易于维护。 ### 命名参数 -您可以在路由中指定命名参数,这些参数将传递给您的回调函数。**这主要是为了路由的可读性。请参阅下面关于重要注意事项的部分。** +您可以在路由中指定命名参数,这些参数将被传递到您的回调函数。**这主要是为了路由的可读性。请参阅下面的重要注意事项。** ```php Flight::route('/@name/@id', function (string $name, string $id) { @@ -183,7 +183,7 @@ Flight::route('/@name/@id', function (string $name, string $id) { }); ``` -您也可以使用 `:` 分隔符为命名参数包含正则表达式: +您也可以使用 `:` 分隔符在命名参数中包含正则表达式: ```php Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { @@ -196,7 +196,7 @@ Flight::route('/@name/@id:[0-9]{3}', function (string $name, string $id) { #### 重要注意事项 -在上面的示例中,`@name` 似乎直接绑定到变量 `$name`,但事实并非如此。回调函数中参数的顺序决定了传递给它的内容。如果您在回调函数中切换参数顺序,变量也会切换。下面是一个示例: +在上面的示例中,`@name` 似乎直接绑定到变量 `$name`,但实际上并非如此。回调函数中参数的顺序决定了传递给它的内容。如果您在回调函数中切换参数顺序,变量也会相应切换。以下是一个示例: ```php Flight::route('/@name/@id', function (string $id, string $name) { @@ -223,7 +223,7 @@ Flight::route( ); ``` -未匹配的任何可选参数将作为 `NULL` 传递。 +未匹配的任何可选参数将被传递为 `NULL`。 ### 通配符路由 匹配仅在单个 URL 段上进行。如果您想匹配多个段,可以使用 `*` 通配符。 @@ -238,13 +238,13 @@ Flight::route('/blog/*', function () { ```php Flight::route('*', function () { - // 执行某些操作 + // 做些什么 }); ``` ### 404 未找到处理程序 -默认情况下,如果找不到 URL,Flight 将发送非常简单且朴素的 `HTTP 404 Not Found` 响应。 +默认情况下,如果找不到 URL,Flight 将发送一个非常简单且朴素的 `HTTP 404 Not Found` 响应。 如果您想要更自定义的 404 响应,您可以 [映射](/learn/extending) 自己的 `notFound` 方法: ```php @@ -267,7 +267,7 @@ Flight::map('notFound', function() { ### 方法未找到处理程序 -默认情况下,如果找到 URL 但方法不允许,Flight 将发送非常简单且朴素的 `HTTP 405 Method Not Allowed` 响应(例如:Method Not Allowed. Allowed Methods are: GET, POST)。它还将包含 `Allow` 标头,带有该 URL 的允许方法。 +默认情况下,如果找到 URL 但方法不允许,Flight 将发送一个非常简单且朴素的 `HTTP 405 Method Not Allowed` 响应(例如:方法不允许。允许的方法是:GET, POST)。它还将包含一个 `Allow` 标头,带有该 URL 的允许方法。 如果您想要更自定义的 405 响应,您可以 [映射](/learn/extending) 自己的 `methodNotFound` 方法: @@ -297,9 +297,9 @@ Flight::map('methodNotFound', function(Route $route) { ## 高级用法 ### 路由中的依赖注入 -如果您想通过容器使用依赖注入(PSR-11、PHP-DI、Dice 等),唯一可用的路由类型是自己直接创建对象并使用容器创建对象,或者使用字符串定义类和要调用的方法。您可以前往 [依赖注入](/learn/dependency-injection-container) 页面获取更多信息。 +如果您想通过容器(PSR-11、PHP-DI、Dice 等)使用依赖注入,则唯一可用的路由类型是直接自己创建对象并使用容器创建您的对象,或者使用字符串定义要调用的类和方法。您可以转到 [依赖注入](/learn/dependency-injection-container) 页面获取更多信息。 -这是一个快速示例: +以下是一个快速示例: ```php @@ -314,7 +314,7 @@ class Greeting } public function hello(int $id) { - // 使用 $this->pdoWrapper 执行某些操作 + // 使用 $this->pdoWrapper 做些什么 $name = $this->pdoWrapper->fetchField("SELECT name FROM users WHERE id = ?", [ $id ]); echo "Hello, world! My name is {$name}!"; } @@ -322,7 +322,7 @@ class Greeting // index.php -// 使用您需要的任何参数设置容器 +// 使用所需的任何参数设置容器 // 请参阅依赖注入页面以获取有关 PSR-11 的更多信息 $dice = new \Dice\Dice(); @@ -351,9 +351,9 @@ Flight::route('/hello/@id', 'Greeting::hello'); Flight::start(); ``` -### 将执行传递给下一个路由 +### 将执行传递到下一个路由 已弃用 -您可以通过从回调函数返回 `true` 将执行传递给下一个匹配的路由。 +您可以通过从回调函数返回 `true` 将执行传递到下一个匹配的路由。 ```php Flight::route('/user/@name', function (string $name) { @@ -369,7 +369,7 @@ Flight::route('/user/*', function () { }); ``` -现在推荐使用 [中间件](/learn/middleware) 来处理此类复杂用例。 +现在推荐使用 [中间件](/learn/middleware) 来处理这种情况的复杂用例。 ### 路由别名 通过为路由分配别名,您可以在应用程序中动态调用该别名,以便稍后在代码中生成(例如:HTML 模板中的链接,或生成重定向 URL)。 @@ -393,8 +393,8 @@ class UserController { ``` -这在 URL 发生变化时特别有用。在上面的示例中,假设用户已移动到 `/admin/users/@id` 而不是 `/users/@id`。 -有了路由别名,您不再需要在代码中查找所有旧 URL 并更改它们,因为别名现在将返回 `/admin/users/5`,如上面的示例。 +这在 URL 发生变化时特别有用。在上面的示例中,假设用户已移动到 `/admin/users/@id`。 +使用别名设置路由后,您无需在代码中查找所有旧 URL 并更改它们,因为别名现在将返回 `/admin/users/5`,如上面的示例。 路由别名在组中仍然有效: @@ -410,13 +410,13 @@ Flight::group('/users', function() { 如果您想检查匹配的路由信息,有两种方式可以做到: 1. 您可以使用 `Flight::router()` 对象上的 `executedRoute` 属性。 -2. 您可以通过在路由方法中将第三个参数传递为 `true` 来请求将路由对象传递给您的回调。路由对象将始终作为传递给回调函数的最后一个参数。 +2. 您可以通过在路由方法中将第三个参数传递为 `true` 来请求将路由对象传递到您的回调。路由对象将始终作为传递到回调函数的最后一个参数。 #### `executedRoute` ```php Flight::route('/', function() { $route = Flight::router()->executedRoute; - // 使用 $route 执行某些操作 + // 使用 $route 做些什么 // 匹配的 HTTP 方法数组 $route->methods; @@ -432,7 +432,7 @@ Flight::route('/', function() { // 显示 URL 路径...如果您真的需要它 $route->pattern; - // 显示分配给此的中间件 + // 显示分配给此的中介软件 $route->middleware; // 显示分配给此路由的别名 @@ -440,7 +440,7 @@ Flight::route('/', function() { }); ``` -> **注意:** `executedRoute` 属性仅在路由执行后设置。如果您在路由执行前尝试访问它,它将是 `NULL`。您也可以在 [中间件](/learn/middleware) 中使用 executedRoute! +> **注意:** `executedRoute` 属性仅在路由执行后设置。如果您在路由执行前尝试访问它,将为 `NULL`。您也可以在 [中间件](/learn/middleware) 中使用 executedRoute! #### 在路由定义中传递 `true` ```php @@ -460,12 +460,12 @@ Flight::route('/', function(\flight\net\Route $route) { // 显示 URL 路径...如果您真的需要它 $route->pattern; - // 显示分配给此的中间件 + // 显示分配给此的中介软件 $route->middleware; // 显示分配给此路由的别名 $route->alias; -}, true);// <-- 这个 true 参数就是使它发生的原因 +}, true);// <-- 这个 true 参数就是让它发生的原因 ``` ### 路由分组和中间件 @@ -514,7 +514,7 @@ Flight::group('/api', function () { #### 使用对象上下文的分组 -您仍然可以使用以下方式与 `Engine` 对象进行路由分组: +您仍然可以使用以下方式与 `Engine` 对象一起使用路由分组: ```php $app = Flight::app(); @@ -543,13 +543,13 @@ Flight::group('/api/v1', function () { Flight::route('/users', function () { // 匹配 /api/v1/users }); -}, [ MyAuthMiddleware::class ]); // 或者 [ new MyAuthMiddleware() ] 如果您想使用实例 +}, [ MyAuthMiddleware::class ]); // 或 [ new MyAuthMiddleware() ] 如果您想使用实例 ``` -请参阅 [组中间件](/learn/middleware#grouping-middleware) 页面的更多详细信息。 +请参阅 [组中间件](/learn/middleware#grouping-middleware) 页面的更多细节。 ### 资源路由 -您可以使用 `resource` 方法为资源创建一组路由。这将为遵循 RESTful 约定的资源创建一组路由。 +您可以使用 `resource` 方法为资源创建一组路由。这将创建一个遵循 RESTful 约定的资源路由集。 要创建资源,请执行以下操作: @@ -557,7 +557,7 @@ Flight::group('/api/v1', function () { Flight::resource('/users', UsersController::class); ``` -后台将创建以下路由: +后台会发生什么,它将创建以下路由: ```php [ @@ -628,12 +628,12 @@ Flight::resource('/users', UsersController::class, [ 'aliasBase' => 'user' ]); 您也可以使用 `only` 和 `except` 选项指定要创建哪些路由。 ```php -// 只允许这些方法并黑名单其余 +// 只允许这些方法并阻止其余 Flight::resource('/users', UsersController::class, [ 'only' => [ 'index', 'show' ] ]); ``` ```php -// 只黑名单这些方法并白名单其余 +// 只阻止这些方法并允许其余 Flight::resource('/users', UsersController::class, [ 'except' => [ 'create', 'store', 'edit', 'update', 'destroy' ] ]); ``` @@ -653,20 +653,20 @@ Flight::resource('/users', UsersController::class, [ 'middleware' => [ MyAuthMid 这对于发送大文件、长时间运行的进程或生成大响应很有用。 流式传输路由的处理方式与常规路由略有不同。 -> **注意:** 仅当您将 [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) 设置为 `false` 时,才支持流式响应。 +> **注意:** 流式响应仅在您将 [`flight.v2.output_buffering`](/learn/migrating-to-v3#output_buffering) 设置为 `false` 时可用。 #### 手动标头的流式传输 您可以通过在路由上使用 `stream()` 方法向客户端流式传输响应。如果您 这样做,您必须在向客户端输出任何内容之前手动设置所有标头。 -这使用 `header()` PHP 函数或 `Flight::response()->setRealHeader()` 方法完成。 +这是使用 `header()` php 函数或 `Flight::response()->setRealHeader()` 方法完成的。 ```php Flight::route('/@filename', function($filename) { $response = Flight::response(); - // 显然,您会清理路径等。 + // 显然您会清理路径什么的。 $fileNameSafe = basename($filename); // 如果您在路由执行后有额外的标头要设置 @@ -688,7 +688,7 @@ Flight::route('/@filename', function($filename) { // 或 $response->setRealHeader('Content-Length: '.filesize($filePath)); - // 流式传输文件到客户端,因为它被读取 + // 以读取的方式将文件流式传输到客户端 readfile($filePath); // 这是这里的魔法行 @@ -705,7 +705,7 @@ Flight::route('/stream-users', function() { // 您可以在这里添加任何额外的标头 // 您只需使用 header() 或 Flight::response()->setRealHeader() - // 无论您如何拉取数据,只是一个示例... + // 无论您如何拉取数据,仅作为示例... $users_stmt = Flight::db()->query("SELECT id, first_name, last_name FROM users"); echo '{'; @@ -716,7 +716,7 @@ Flight::route('/stream-users', function() { echo ','; } - // 这对于将数据发送到客户端是必需的 + // 这是在将数据发送到客户端时必需的 ob_flush(); } echo '}'; @@ -735,18 +735,18 @@ Flight::route('/stream-users', function() { - [依赖注入](/learn/dependency-injection-container) - 简化路由中的对象创建和管理。 - [为什么使用框架?](/learn/why-frameworks) - 理解使用像 Flight 这样的框架的好处。 - [扩展](/learn/extending) - 如何使用自己的功能扩展 Flight,包括 `notFound` 方法。 -- [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - PHP 正则表达式匹配函数。 +- [php.net: preg_match](https://www.php.net/manual/en/function.preg-match.php) - PHP 用于正则表达式匹配的函数。 ## 故障排除 - 路由参数按顺序匹配,而不是按名称。确保回调参数顺序与路由定义匹配。 -- 使用 `Flight::get()` 不会定义路由;对于路由,请使用 `Flight::route('GET /...')` 或组中的路由器对象上下文(例如 `$router->get(...)`)。 -- executedRoute 属性仅在路由执行后设置;执行前为 NULL。 +- 使用 `Flight::get()` 不会定义路由;对于路由,请使用 `Flight::route('GET /...')` 或组中的 Router 对象上下文(例如 `$router->get(...)`)。 +- executedRoute 属性仅在路由执行后设置;在执行前为 NULL。 - 流式传输需要禁用遗留 Flight 输出缓冲功能(`flight.v2.output_buffering = false`)。 - 对于依赖注入,只有某些路由定义支持基于容器的实例化。 ### 404 未找到或意外路由行为 -如果您看到 404 未找到错误(但您发誓它确实存在,并且不是拼写错误),这实际上可能是因为您在路由端点中返回值而不是只是回显它。这种情况是有意的,但可能会偷偷影响一些开发者。 +如果您看到 404 未找到错误(但您发誓它确实存在,并且不是拼写错误),这实际上可能是因为您在路由端点中返回了一个值而不是简单地回显它。这是有意的,但可能会让一些开发者措手不及。 ```php Flight::route('/hello', function(){ @@ -760,9 +760,9 @@ Flight::route('/hello', function(){ }); ``` -原因是因为路由器中内置了一个特殊机制,将返回输出处理为“转到下一个路由”的信号。 -您可以在 [路由](/learn/routing#passing) 部分查看该行为的文档。 +这样做的原因是路由器中内置了一个特殊机制,将返回输出处理为“转到下一个路由”的信号。 +您可以在 [路由](/learn/routing#passing) 部分查看文档化的行为。 ## 更新日志 - v3:添加了资源路由、路由别名和流式传输支持、路由组和中间件支持。 -- v1:大多数基本功能可用。 \ No newline at end of file +- v1:绝大多数基本功能可用。 \ No newline at end of file From 92eb49e54ca6544204438e1f5d3ba9ec23f01148 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Tue, 7 Oct 2025 20:21:00 +0100 Subject: [PATCH 13/36] added Eventify example --- content/v3/en/examples.md | 1 + 1 file changed, 1 insertion(+) diff --git a/content/v3/en/examples.md b/content/v3/en/examples.md index 6374ae7d..f0bdf076 100644 --- a/content/v3/en/examples.md +++ b/content/v3/en/examples.md @@ -16,6 +16,7 @@ Community contributed examples: While these are not officially sponsored by the Flight Team, these could give you ideas on how to structure your own projects that are built with Flight! +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify is a single-page app connecting event organizers with attendees. Built with PHP (FlightPHP), JavaScript, and MySQL, it features JWT auth, event management, and RESTful API docs using OpenAPI. - [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental is a single-page, mobile-friendly car rental web application built with PHP (FlightPHP), JavaScript, and MySQL. It supports user registration, browsing, and booking cars, while admins can manage cars, users, and bookings. The app features a REST API, JWT authentication, and a responsive design for a modern rental experience. - [Decay](https://github.com/boxybird/decay) - Flight v3 with HTMX and SleekDB all about zombies! ([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 with Middleware, Controllers, Active Record, and Latte. From a64255bedbc6eadc3137f5e59891b539d1dd98e6 Mon Sep 17 00:00:00 2001 From: KnifeLemon Date: Sun, 19 Oct 2025 23:51:39 +0900 Subject: [PATCH 14/36] Add CommentTemplate documentation to awesome plugins --- .../v3/en/awesome-plugins/awesome_plugins.md | 1 + .../v3/en/awesome-plugins/comment_template.md | 257 ++++++++++++++++++ 2 files changed, 258 insertions(+) create mode 100644 content/v3/en/awesome-plugins/comment_template.md diff --git a/content/v3/en/awesome-plugins/awesome_plugins.md b/content/v3/en/awesome-plugins/awesome_plugins.md index 27c5578f..a2ec1211 100644 --- a/content/v3/en/awesome-plugins/awesome_plugins.md +++ b/content/v3/en/awesome-plugins/awesome_plugins.md @@ -84,6 +84,7 @@ Templating is core to any web application with a UI. There are a number of templ - deprecated [flightphp/core View](/learn#views) - This is a very basic templating engine that is part of the core. It's not recommended to be used if you have more than a couple pages in your project. - [latte/latte](/awesome-plugins/latte) - Latte is a full featured templating engine that is very easy to use and feels closer to a PHP syntax than Twig or Smarty. It's also very easy to extend and add your own filters and functions. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate is a powerful PHP template engine with asset compilation, template inheritance, and variable processing. Features automatic CSS/JS minification, caching, Base64 encoding, and optional Flight PHP framework integration. ## WordPress Integration diff --git a/content/v3/en/awesome-plugins/comment_template.md b/content/v3/en/awesome-plugins/comment_template.md new file mode 100644 index 00000000..c3e5fb66 --- /dev/null +++ b/content/v3/en/awesome-plugins/comment_template.md @@ -0,0 +1,257 @@ +# CommentTemplate + +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) is a powerful PHP template engine with asset compilation, template inheritance, and variable processing. It provides a simple yet flexible way to manage templates with built-in CSS/JS minification and caching. + +## Features + +- **Template Inheritance**: Use layouts and include other templates +- **Asset Compilation**: Automatic CSS/JS minification and caching +- **Variable Processing**: Template variables with filters and commands +- **Base64 Encoding**: Inline assets as data URIs +- **Flight Framework Integration**: Optional integration with Flight PHP framework + +## Installation + +Install with composer. + +```bash +composer require knifelemon/comment-template +``` + +## Basic Configuration + +There are some basic configuration options to get started. You can read more about them in the [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate). + +### Method 1: Using Callback Function + +```php +register('view', Engine::class, [], function (Engine $engine) use ($app) { + // Where your template files are stored + $engine->setTemplatesPath(__DIR__ . '/views'); + + // Where your public assets will be served from + $engine->setPublicPath(__DIR__ . '/public'); + + // Where compiled assets will be stored + $engine->setAssetPath('assets'); + + // Template file extension + $engine->setFileExtension('.php'); +}); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +### Method 2: Using Constructor Parameters + +```php +register('view', Engine::class, [ + __DIR__ . '/public', // publicPath - where assets will be served from + __DIR__ . '/views', // skinPath - where template files are stored + 'assets', // assetPath - where compiled assets will be stored + '.php' // fileExtension - template file extension +]); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +## Template Directives + +### Layout Inheritance + +Use layouts to create a common structure: + +**layout/global_layout.php**: +```html + + + + {$title} + + + + + +``` + +**view/page.php**: +```html + +

{$title}

+

{$content}

+``` + +### Asset Management + +#### CSS Files +```html + + +``` + +#### JavaScript Files +CommentTemplate supports different JavaScript loading strategies: + +```html + + + + + + + + + +``` + +#### Asset Directives in CSS/JS Files + +CommentTemplate also processes asset directives within CSS and JavaScript files during compilation: + +**CSS Example:** +```css +/* In your CSS files */ +@font-face { + font-family: 'CustomFont'; + src: url('') format('woff2'); +} + +.background-image { + background: url(''); +} + +.inline-icon { + background: url(''); +} +``` + +**JavaScript Example:** +```javascript +/* In your JS files */ +const fontUrl = ''; +const imageData = ''; +``` + +#### Base64 Encoding +```html + +``` +** Example: ** +```html + +Logo +
+ Small icon as background +
+``` + +#### Asset Copying +```html + + +``` +** Example: ** +```html + +Hero Banner +Download Brochure + + + + +``` + +### Template Includes +```html + +``` +** Example: ** +```html + + + +
+

Welcome to our website

+ + +
+

Main content here...

+
+
+ + +``` + +### Variable Processing + +#### Basic Variables +```html +

{$title}

+

{$description}

+``` + +#### Variable Filters +```html +{$title|upper} +{$content|lower} +{$html|striptag} +{$text|escape} +{$multiline|nl2br} +{$html|br2nl} +{$description|trim} +{$subject|title} +``` + +#### Variable Commands +```html +{$title|default=Default Title} +{$name|concat= (Admin)} +``` + +#### Variable Commands +```html +{$content|striptag|trim|escape} +``` + +## Example Project Structure + +``` +project/ +├── source/ +│ ├── layouts/ +│ │ └── default.php +│ ├── components/ +│ │ ├── header.php +│ │ └── footer.php +│ ├── css/ +│ │ ├── bootstrap.min.css +│ │ └── custom.css +│ ├── js/ +│ │ ├── app.js +│ │ └── bootstrap.min.js +│ └── homepage.php +├── public/ +│ └── assets/ # Generated assets +│ ├── css/ +│ └── js/ +└── vendor/ +``` \ No newline at end of file From 1706eb192299ac0ac06bba2dad746c1a31bde87c Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Mon, 20 Oct 2025 18:45:46 -0600 Subject: [PATCH 15/36] translation --- .../v3/de/awesome-plugins/awesome_plugins.md | 45 +-- .../v3/de/awesome-plugins/comment_template.md | 257 +++++++++++++++++ content/v3/de/examples.md | 19 +- .../v3/es/awesome-plugins/awesome_plugins.md | 29 +- .../v3/es/awesome-plugins/comment_template.md | 257 +++++++++++++++++ content/v3/es/examples.md | 15 +- .../v3/fr/awesome-plugins/awesome_plugins.md | 43 +-- .../v3/fr/awesome-plugins/comment_template.md | 257 +++++++++++++++++ content/v3/fr/examples.md | 17 +- .../v3/id/awesome-plugins/awesome_plugins.md | 33 +-- .../v3/id/awesome-plugins/comment_template.md | 257 +++++++++++++++++ content/v3/id/examples.md | 11 +- .../v3/ja/awesome-plugins/awesome_plugins.md | 73 ++--- .../v3/ja/awesome-plugins/comment_template.md | 258 ++++++++++++++++++ content/v3/ja/examples.md | 21 +- .../v3/ko/awesome-plugins/awesome_plugins.md | 55 ++-- .../v3/ko/awesome-plugins/comment_template.md | 257 +++++++++++++++++ content/v3/ko/examples.md | 27 +- .../v3/lv/awesome-plugins/awesome_plugins.md | 65 ++--- .../v3/lv/awesome-plugins/comment_template.md | 257 +++++++++++++++++ content/v3/lv/examples.md | 29 +- .../v3/pt/awesome-plugins/awesome_plugins.md | 39 +-- .../v3/pt/awesome-plugins/comment_template.md | 257 +++++++++++++++++ content/v3/pt/examples.md | 5 +- .../v3/ru/awesome-plugins/awesome_plugins.md | 50 ++-- .../v3/ru/awesome-plugins/comment_template.md | 257 +++++++++++++++++ content/v3/ru/examples.md | 17 +- .../v3/uk/awesome-plugins/awesome_plugins.md | 73 ++--- .../v3/uk/awesome-plugins/comment_template.md | 257 +++++++++++++++++ content/v3/uk/examples.md | 15 +- .../v3/zh/awesome-plugins/awesome_plugins.md | 41 +-- .../v3/zh/awesome-plugins/comment_template.md | 257 +++++++++++++++++ content/v3/zh/examples.md | 9 +- 33 files changed, 3205 insertions(+), 354 deletions(-) create mode 100644 content/v3/de/awesome-plugins/comment_template.md create mode 100644 content/v3/es/awesome-plugins/comment_template.md create mode 100644 content/v3/fr/awesome-plugins/comment_template.md create mode 100644 content/v3/id/awesome-plugins/comment_template.md create mode 100644 content/v3/ja/awesome-plugins/comment_template.md create mode 100644 content/v3/ko/awesome-plugins/comment_template.md create mode 100644 content/v3/lv/awesome-plugins/comment_template.md create mode 100644 content/v3/pt/awesome-plugins/comment_template.md create mode 100644 content/v3/ru/awesome-plugins/comment_template.md create mode 100644 content/v3/uk/awesome-plugins/comment_template.md create mode 100644 content/v3/zh/awesome-plugins/comment_template.md diff --git a/content/v3/de/awesome-plugins/awesome_plugins.md b/content/v3/de/awesome-plugins/awesome_plugins.md index e8e1cc1c..97f32378 100644 --- a/content/v3/de/awesome-plugins/awesome_plugins.md +++ b/content/v3/de/awesome-plugins/awesome_plugins.md @@ -1,28 +1,28 @@ # Tolle 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, und andere sind Micro/Lite-Bibliotheken, um Ihnen den Einstieg zu erleichtern. +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 und andere sind Micro/Lite-Bibliotheken, um Ihnen den Einstieg zu erleichtern. ## API-Dokumentation -API-Dokumentation ist entscheidend für jede API. Sie hilft Entwicklern zu verstehen, wie sie mit Ihrer API interagieren können und was sie als Rückgabe erwarten können. Es gibt einige Tools, die Ihnen helfen können, API-Dokumentation für Ihre Flight-Projekte zu generieren. +API-Dokumentation ist entscheidend für jede API. Sie hilft Entwicklern zu verstehen, wie sie mit Ihrer API interagieren können und was sie als Rückgabe erwarten können. Es gibt ein paar Tools, die Ihnen helfen können, API-Dokumentation für Ihre Flight-Projekte zu generieren. - [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Blog-Beitrag von Daniel Schreiber darüber, wie man die OpenAPI-Spezifikation mit FlightPHP verwendet, um Ihre API mit einem API-First-Ansatz aufzubauen. - [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ist ein großartiges Tool, um API-Dokumentation für Ihre Flight-Projekte zu generieren. Es ist sehr einfach zu verwenden und kann an Ihre Bedürfnisse angepasst werden. Dies ist die PHP-Bibliothek, die Ihnen hilft, die Swagger-Dokumentation zu generieren. -## Application Performance Monitoring (APM) +## Anwendungsleistungsüberwachung (APM) -Application Performance Monitoring (APM) ist entscheidend für jede Anwendung. Es hilft Ihnen zu verstehen, wie Ihre Anwendung performt und wo die Engpässe liegen. Es gibt eine Reihe von APM-Tools, die mit Flight verwendet werden können. -- offiziell [flightphp/apm](/awesome-plugins/apm) - Flight APM ist eine einfache APM-Bibliothek, die verwendet werden kann, um Ihre Flight-Anwendungen zu überwachen. Sie kann verwendet werden, um die Performance Ihrer Anwendung zu überwachen und Ihnen zu helfen, Engpässe zu identifizieren. +Anwendungsleistungsüberwachung (APM) ist entscheidend für jede Anwendung. Sie hilft Ihnen zu verstehen, wie Ihre Anwendung performt und wo die Engpässe liegen. Es gibt eine Reihe von APM-Tools, die mit Flight verwendet werden können. +- offiziell [flightphp/apm](/awesome-plugins/apm) - Flight APM ist eine einfache APM-Bibliothek, die verwendet werden kann, um Ihre Flight-Anwendungen zu überwachen. Sie kann verwendet werden, um die Leistung Ihrer Anwendung zu überwachen und Ihnen zu helfen, Engpässe zu identifizieren. -## Async +## Asynchron -Flight ist bereits ein schnelles Framework, aber es mit einem Turbo-Motor auszustatten macht alles noch spaßiger (und herausfordernder)! +Flight ist bereits ein schnelles Framework, aber wenn man es mit einem Turbo-Motor ausstattet, wird alles noch unterhaltsamer (und herausfordernder)! - [flightphp/async](/awesome-plugins/async) - Offizielle Flight Async-Bibliothek. Diese Bibliothek ist eine einfache Möglichkeit, asynchrone Verarbeitung zu Ihrer Anwendung hinzuzufügen. Sie verwendet Swoole/Openswoole im Hintergrund, um eine einfache und effektive Möglichkeit zu bieten, Aufgaben asynchron auszuführen. ## Autorisierung/Berechtigungen -Autorisierung und Berechtigungen sind entscheidend für jede Anwendung, die Steuerungen benötigt, um festzulegen, wer auf was zugreifen kann. +Autorisierung und Berechtigungen sind entscheidend für jede Anwendung, die Steuerelemente benötigt, um zu definieren, wer auf was zugreifen kann. - offiziell [flightphp/permissions](/awesome-plugins/permissions) - Offizielle Flight Permissions-Bibliothek. Diese Bibliothek ist eine einfache Möglichkeit, Benutzer- und Anwendungsebene-Berechtigungen zu Ihrer Anwendung hinzuzufügen. @@ -30,7 +30,7 @@ Autorisierung und Berechtigungen sind entscheidend für jede Anwendung, die Steu Caching ist eine großartige Möglichkeit, Ihre Anwendung zu beschleunigen. Es gibt eine Reihe von Caching-Bibliotheken, die mit Flight verwendet werden können. -- offiziell [flightphp/cache](/awesome-plugins/php-file-cache) - Leichte, einfache und eigenständige PHP-in-File-Caching-Klasse +- offiziell [flightphp/cache](/awesome-plugins/php-file-cache) - Leichte, einfache und eigenständige PHP In-File-Caching-Klasse ## CLI @@ -46,26 +46,26 @@ Cookies sind eine großartige Möglichkeit, kleine Datenmengen auf der Client-Se ## Debugging -Debugging ist entscheidend, wenn Sie in Ihrer lokalen Umgebung entwickeln. Es gibt einige Plugins, die Ihr Debugging-Erlebnis verbessern können. +Debugging ist entscheidend, wenn Sie in Ihrer lokalen Umgebung entwickeln. Es gibt ein paar Plugins, die Ihr Debugging-Erlebnis verbessern können. -- [tracy/tracy](/awesome-plugins/tracy) - Dies ist ein vollständiges Fehlerbehandlungstool, das mit Flight verwendet werden kann. Es hat eine Reihe von Panels, die Ihnen helfen können, Ihre Anwendung zu debuggen. Es ist auch sehr einfach zu erweitern und eigene Panels hinzuzufügen. -- offiziell [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - In Verbindung mit dem [Tracy](/awesome-plugins/tracy) Fehlerbehandlungstool fügt dieses Plugin einige zusätzliche Panels hinzu, um das Debugging speziell für Flight-Projekte zu erleichtern. +- [tracy/tracy](/awesome-plugins/tracy) - Dies ist ein vollständiges Fehlerbehandlungs-Tool, das mit Flight verwendet werden kann. Es hat eine Reihe von Panels, die Ihnen helfen können, Ihre Anwendung zu debuggen. Es ist auch sehr einfach zu erweitern und eigene Panels hinzuzufügen. +- offiziell [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - In Verbindung mit dem [Tracy](/awesome-plugins/tracy) Fehlerbehandlungs-Tool fügt dieses Plugin ein paar zusätzliche Panels hinzu, die speziell für das Debugging von Flight-Projekten helfen. ## Datenbanken -Datenbanken sind der Kern der meisten Anwendungen. So speichern und rufen Sie Daten ab. Einige Datenbankbibliotheken sind einfach Wrapper, um Abfragen zu schreiben, und einige sind vollwertige ORMs. +Datenbanken sind der Kern der meisten Anwendungen. So speichern und rufen Sie Daten ab. Einige Datenbank-Bibliotheken sind einfach Wrapper, um Abfragen zu schreiben, und einige sind vollwertige ORMs. -- offiziell [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Offizieller Flight PDO-Wrapper, der zum Kern gehört. Dies ist ein einfacher Wrapper, der den Prozess des Schreibens und Ausführens von Abfragen vereinfacht. Es handelt sich nicht um ein ORM. +- offiziell [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Offizieller Flight PDO Wrapper, der zum Kern gehört. Dies ist ein einfacher Wrapper, der den Prozess des Schreibens und Ausführens von Abfragen vereinfacht. Es handelt sich nicht um ein ORM. - offiziell [flightphp/active-record](/awesome-plugins/active-record) - Offizielles Flight ActiveRecord ORM/Mapper. Tolle kleine Bibliothek, um Daten einfach in Ihrer Datenbank abzurufen und zu speichern. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin, um alle Datenbankänderungen für Ihr Projekt zu verfolgen. ## Verschlüsselung -Verschlüsselung ist entscheidend für jede Anwendung, die sensible Daten speichert. Das Verschlüsseln und Entschlüsseln der Daten ist nicht besonders schwer, aber das ordnungsgemäße Speichern des Verschlüsselungsschlüssels [kann](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [sein](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [schwierig](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Das Wichtigste ist, Ihren Verschlüsselungsschlüssel niemals in einem öffentlichen Verzeichnis zu speichern oder ihn in Ihr Code-Repository zu committen. +Verschlüsselung ist entscheidend für jede Anwendung, die sensible Daten speichert. Das Verschlüsseln und Entschlüsseln von Daten ist nicht allzu schwer, aber das ordnungsgemäße Speichern des Verschlüsselungsschlüssels [kann](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [sein](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [schwierig](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Das Wichtigste ist, Ihren Verschlüsselungsschlüssel niemals in einem öffentlichen Verzeichnis zu speichern oder ihn in Ihr Code-Repository zu committen. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Dies ist eine Bibliothek, die verwendet werden kann, um Daten zu verschlüsseln und zu entschlüsseln. Der Einstieg ist ziemlich einfach, um mit dem Verschlüsseln und Entschlüsseln von Daten zu beginnen. -## Job Queue +## Job-Warteschlange Job-Warteschlangen sind wirklich hilfreich, um Aufgaben asynchron zu verarbeiten. Das kann das Versenden von E-Mails, die Verarbeitung von Bildern oder alles sein, was nicht in Echtzeit erledigt werden muss. @@ -73,21 +73,22 @@ Job-Warteschlangen sind wirklich hilfreich, um Aufgaben asynchron zu verarbeiten ## Session -Sessions sind für APIs nicht wirklich nützlich, aber beim Aufbau einer Web-Anwendung können Sessions entscheidend für die Aufrechterhaltung des Zustands und Login-Informationen sein. +Sitzungen sind für APIs nicht wirklich nützlich, aber beim Aufbau einer Web-Anwendung können Sitzungen entscheidend für die Aufrechterhaltung von Zuständen und Anmeldeinformationen sein. - offiziell [flightphp/session](/awesome-plugins/session) - Offizielle Flight Session-Bibliothek. Dies ist eine einfache Session-Bibliothek, die verwendet werden kann, um Session-Daten zu speichern und abzurufen. Sie verwendet die integrierte Session-Behandlung von PHP. - [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (nicht-blockierend, Flash, Segment, Session-Verschlüsselung). Verwendet PHP open_ssl für optionale Verschlüsselung/Entschlüsselung von Session-Daten. -## Templating +## Vorlagen -Templating ist der Kern jeder Web-Anwendung mit einer UI. Es gibt eine Reihe von Templating-Engines, die mit Flight verwendet werden können. +Vorlagen sind der Kern jeder Web-Anwendung mit einer Benutzeroberfläche. Es gibt eine Reihe von Vorlagen-Engines, die mit Flight verwendet werden können. -- veraltet [flightphp/core View](/learn#views) - Dies ist eine sehr grundlegende Templating-Engine, die zum Kern gehört. Es wird nicht empfohlen, sie zu verwenden, wenn Ihr Projekt mehr als ein paar Seiten hat. -- [latte/latte](/awesome-plugins/latte) - Latte ist eine vollständige Templating-Engine, die sehr einfach zu verwenden ist und sich näher an der PHP-Syntax anfühlt als Twig oder Smarty. Sie ist auch sehr einfach zu erweitern und eigene Filter und Funktionen hinzuzufügen. +- veraltet [flightphp/core View](/learn#views) - Dies ist ein sehr grundlegendes Vorlagen-Engine, das zum Kern gehört. Es wird nicht empfohlen, es zu verwenden, wenn Ihr Projekt mehr als ein paar Seiten hat. +- [latte/latte](/awesome-plugins/latte) - Latte ist eine vollständige Vorlagen-Engine, die sehr einfach zu verwenden ist und sich näher an der PHP-Syntax anfühlt als Twig oder Smarty. Sie ist auch sehr einfach zu erweitern und eigene Filter und Funktionen hinzuzufügen. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate ist eine leistungsstarke PHP-Vorlagen-Engine mit Asset-Kompilierung, Vorlagen-Vererbung und Variablenverarbeitung. Features automatische CSS/JS-Minifizierung, Caching, Base64-Kodierung und optionale Integration des Flight PHP-Frameworks. ## WordPress-Integration -Möchten Sie Flight in Ihrem WordPress-Projekt verwenden? Es gibt ein praktisches Plugin dafür! +Möchten Sie Flight in Ihrem WordPress-Projekt verwenden? Es gibt ein handliches Plugin dafür! - [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Dieses WordPress-Plugin ermöglicht es Ihnen, Flight direkt neben WordPress auszuführen. Es ist perfekt, um benutzerdefinierte APIs, Microservices oder sogar vollständige Apps zu Ihrer WordPress-Site mit dem Flight-Framework hinzuzufügen. Super nützlich, wenn Sie das Beste aus beiden Welten wollen! diff --git a/content/v3/de/awesome-plugins/comment_template.md b/content/v3/de/awesome-plugins/comment_template.md new file mode 100644 index 00000000..b5ee6482 --- /dev/null +++ b/content/v3/de/awesome-plugins/comment_template.md @@ -0,0 +1,257 @@ +# CommentTemplate + +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) ist ein leistungsstarkes PHP-Template-Engine mit Asset-Kompilierung, Template-Vererbung und Variablenverarbeitung. Es bietet eine einfache, aber flexible Möglichkeit, Templates zu verwalten, mit integrierter CSS/JS-Minifizierung und Caching. + +## Features + +- **Template-Vererbung**: Verwenden von Layouts und Einbinden anderer Templates +- **Asset-Kompilierung**: Automatische CSS/JS-Minifizierung und Caching +- **Variablenverarbeitung**: Template-Variablen mit Filtern und Befehlen +- **Base64-Kodierung**: Inline-Assets als Data-URIs +- **Flight-Framework-Integration**: Optionale Integration mit dem Flight-PHP-Framework + +## Installation + +Installieren Sie es mit Composer. + +```bash +composer require knifelemon/comment-template +``` + +## Grundlegende Konfiguration + +Es gibt einige grundlegende Konfigurationsoptionen, um zu starten. Sie können mehr darüber in der [CommentTemplate-Repo](https://github.com/KnifeLemon/CommentTemplate) lesen. + +### Methode 1: Verwendung einer Callback-Funktion + +```php +register('view', Engine::class, [], function (Engine $engine) use ($app) { + // Wo Ihre Template-Dateien gespeichert sind + $engine->setTemplatesPath(__DIR__ . '/views'); + + // Wo Ihre öffentlichen Assets serviert werden + $engine->setPublicPath(__DIR__ . '/public'); + + // Wo kompilierte Assets gespeichert werden + $engine->setAssetPath('assets'); + + // Template-Dateierweiterung + $engine->setFileExtension('.php'); +}); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +### Methode 2: Verwendung von Konstruktor-Parametern + +```php +register('view', Engine::class, [ + __DIR__ . '/public', // publicPath - wo Assets serviert werden + __DIR__ . '/views', // skinPath - wo Template-Dateien gespeichert sind + 'assets', // assetPath - wo kompilierte Assets gespeichert werden + '.php' // fileExtension - Template-Dateierweiterung +]); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +## Template-Direktiven + +### Layout-Vererbung + +Verwenden Sie Layouts, um eine gemeinsame Struktur zu erstellen: + +**layout/global_layout.php**: +```html + + + + {$title} + + + + + +``` + +**view/page.php**: +```html + +

{$title}

+

{$content}

+``` + +### Asset-Verwaltung + +#### CSS-Dateien +```html + + +``` + +#### JavaScript-Dateien +CommentTemplate unterstützt verschiedene JavaScript-Lade-Strategien: + +```html + + + + + + + + + +``` + +#### Asset-Direktiven in CSS/JS-Dateien + +CommentTemplate verarbeitet auch Asset-Direktiven innerhalb von CSS- und JavaScript-Dateien während der Kompilierung: + +**CSS-Beispiel:** +```css +/* In Ihren CSS-Dateien */ +@font-face { + font-family: 'CustomFont'; + src: url('') format('woff2'); +} + +.background-image { + background: url(''); +} + +.inline-icon { + background: url(''); +} +``` + +**JavaScript-Beispiel:** +```javascript +/* In Ihren JS-Dateien */ +const fontUrl = ''; +const imageData = ''; +``` + +#### Base64-Kodierung +```html + +``` +**Beispiel:** +```html + +Logo +
+ Kleines Icon als Hintergrund +
+``` + +#### Asset-Kopieren +```html + + +``` +**Beispiel:** +```html + +Hero Banner +Download Brochure + + + + +``` + +### Template-Einbindungen +```html + +``` +**Beispiel:** +```html + + + +
+

Willkommen auf unserer Website

+ + +
+

Hauptinhalt hier...

+
+
+ + +``` + +### Variablenverarbeitung + +#### Grundlegende Variablen +```html +

{$title}

+

{$description}

+``` + +#### Variablenfilter +```html +{$title|upper} +{$content|lower} +{$html|striptag} +{$text|escape} +{$multiline|nl2br} +{$html|br2nl} +{$description|trim} +{$subject|title} +``` + +#### Variablenbefehle +```html +{$title|default=Default Title} +{$name|concat= (Admin)} +``` + +#### Variablenbefehle +```html +{$content|striptag|trim|escape} +``` + +## Beispiel-Projektstruktur + +``` +project/ +├── source/ +│ ├── layouts/ +│ │ └── default.php +│ ├── components/ +│ │ ├── header.php +│ │ └── footer.php +│ ├── css/ +│ │ ├── bootstrap.min.css +│ │ └── custom.css +│ ├── js/ +│ │ ├── app.js +│ │ └── bootstrap.min.js +│ └── homepage.php +├── public/ +│ └── assets/ # Generierte Assets +│ ├── css/ +│ └── js/ +└── vendor/ +``` \ No newline at end of file diff --git a/content/v3/de/examples.md b/content/v3/de/examples.md index cd8918e9..00f1b014 100644 --- a/content/v3/de/examples.md +++ b/content/v3/de/examples.md @@ -1,25 +1,26 @@ -# Schneller Einstieg? +# Brauchen Sie einen schnellen Einstieg? -Sie haben zwei Optionen, um mit einem neuen Flight-Projekt zu starten: +Sie haben zwei Optionen, um mit einem neuen Flight-Projekt zu beginnen: - [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Ein umfassenderes Beispiel mit Controllern und Views. -- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Eine einzelne Datei, die alles enthält, was Sie benötigen, um Ihre App in einer einfachen einzigen Datei auszuführen. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Eine einzelne Datei, die alles enthält, was Sie benötigen, um Ihre App in einer einzigen einfachen Datei auszuführen. -Community-beigetragene Beispiele: +Von der Community beigetragene Beispiele: - [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP mit Laravel-Verzeichnissen, mit PHP-Tools + GH Actions - [fleact](https://github.com/flightphp/fleact) - Ein FlightPHP-Starter-Kit mit ReactJS-Integration. - [flastro](https://github.com/flightphp/flastro) - Ein FlightPHP-Starter-Kit mit Astro-Integration. - [velt](https://github.com/flightphp/velt) - Velt ist eine schnelle und einfache Svelte-Starter-Vorlage mit einem FlightPHP-Backend. -## Brauchen Sie Inspiration? +## Brauchen Sie etwas Inspiration? -Obwohl diese nicht offiziell von dem Flight-Team gesponsert werden, könnten sie Ihnen Ideen geben, wie Sie Ihre eigenen Projekte strukturieren, die mit Flight aufgebaut sind! +Obwohl diese nicht offiziell von dem Flight-Team gesponsert werden, könnten sie Ihnen Ideen geben, wie Sie Ihre eigenen mit Flight gebauten Projekte strukturieren! -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental ist eine einseitige, mobilfreundliche Autovermietungs-Web-Anwendung, die mit PHP (FlightPHP), JavaScript und MySQL aufgebaut wurde. Sie unterstützt Benutzerregistrierung, Durchsuchen und Buchen von Autos, während Admins Autos, Benutzer und Buchungen verwalten können. Die App verfügt über eine REST-API, JWT-Authentifizierung und ein responsives Design für ein modernes Vermietungserlebnis. +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify ist eine Single-Page-App, die Veranstaltungsorganisatoren mit Teilnehmern verbindet. Gebaut mit PHP (FlightPHP), JavaScript und MySQL, bietet es JWT-Authentifizierung, Veranstaltungsmanagement und RESTful-API-Dokumentation mit OpenAPI. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental ist eine Single-Page, mobilfreundliche Autovermietungs-Web-Anwendung, gebaut mit PHP (FlightPHP), JavaScript und MySQL. Es unterstützt Benutzerregistrierung, Durchsuchen und Buchen von Autos, während Admins Autos, Benutzer und Buchungen verwalten können. Die App verfügt über eine REST-API, JWT-Authentifizierung und ein responsives Design für ein modernes Vermietungserlebnis. - [Decay](https://github.com/boxybird/decay) - Flight v3 mit HTMX und SleekDB, alles über Zombies! ([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 mit Middleware, Controllern, Active Record und Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Einfaches CRUD-API-Projekt mit dem Flight-Framework, das eine grundlegende Struktur für neue Benutzer bietet, um schnell eine PHP-Anwendung mit CRUD-Operationen und Datenbankverbindung einzurichten. Das Projekt demonstriert, wie man Flight für die RESTful-API-Entwicklung verwendet, was es zu einem idealen Lernwerkzeug für Anfänger und einem nützlichen Starter-Kit für erfahrene Entwickler macht. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Ein einfaches CRUD-API-Projekt mit dem Flight-Framework, das eine grundlegende Struktur für neue Benutzer bietet, um schnell eine PHP-Anwendung mit CRUD-Operationen und Datenbankverbindung einzurichten. Das Projekt demonstriert, wie man Flight für die RESTful-API-Entwicklung verwendet, was es zu einem idealen Lernwerkzeug für Anfänger und einem nützlichen Starter-Kit für erfahrene Entwickler macht. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -30,7 +31,7 @@ Obwohl diese nicht offiziell von dem Flight-Team gesponsert werden, könnten sie - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Produktionsreifes Authentifizierungs-Framework, das Ihnen Wochen der Entwicklung erspart. Es bietet unternehmensklasse Sicherheit: 2FA/TOTP, LDAP-Integration, Azure SSO, intelligente Ratenbegrenzung, Sitzungs-Fingerprinting, Schutz vor Brute-Force-Angriffen, Sicherheits-Analytics-Dashboard, umfassende Audit-Protokollierung und granulare rollenbasierte Zugriffssteuerung. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Ein produktionsreifes Authentifizierungs-Framework, das Ihnen Wochen der Entwicklung erspart. Es bietet enterprise-grade Sicherheit: 2FA/TOTP, LDAP-Integration, Azure SSO, intelligente Rate-Limiting, Session-Fingerprinting, Brute-Force-Schutz, Security-Analytics-Dashboard, umfassende Audit-Logging und granulare rollenbasierte Zugriffssteuerung. ## Möchten Sie Ihr eigenes Beispiel teilen? diff --git a/content/v3/es/awesome-plugins/awesome_plugins.md b/content/v3/es/awesome-plugins/awesome_plugins.md index 7c190429..deb861c8 100644 --- a/content/v3/es/awesome-plugins/awesome_plugins.md +++ b/content/v3/es/awesome-plugins/awesome_plugins.md @@ -4,10 +4,10 @@ Flight es increíblemente extensible. Hay una serie de plugins que se pueden usa ## Documentación de API -La documentación de API es crucial para cualquier API. Ayuda a los desarrolladores a entender cómo interactuar con tu API y qué esperar a cambio. Hay un par de herramientas disponibles para ayudarte a generar documentación de API para tus Proyectos Flight. +La documentación de API es crucial para cualquier API. Ayuda a los desarrolladores a entender cómo interactuar con tu API y qué esperar a cambio. Hay un par de herramientas disponibles para ayudarte a generar documentación de API para tus Proyectos de Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Publicación de blog escrita por Daniel Schreiber sobre cómo usar la Especificación OpenAPI con FlightPHP para construir tu API utilizando un enfoque API first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI es una gran herramienta para ayudarte a generar documentación de API para tus proyectos Flight. Es muy fácil de usar y se puede personalizar para adaptarse a tus necesidades. Esta es la biblioteca PHP para ayudarte a generar la documentación Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Publicación de blog escrita por Daniel Schreiber sobre cómo usar la Especificación OpenAPI con FlightPHP para construir tu API utilizando un enfoque API primero. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI es una gran herramienta para ayudarte a generar documentación de API para tus proyectos de Flight. Es muy fácil de usar y se puede personalizar para adaptarse a tus necesidades. Esta es la biblioteca PHP para ayudarte a generar la documentación Swagger. ## Monitoreo de Rendimiento de Aplicaciones (APM) @@ -24,13 +24,13 @@ Flight ya es un framework rápido, pero agregarle un motor turbo lo hace todo m La autorización y los permisos son cruciales para cualquier aplicación que requiera controles en su lugar para quién puede acceder a qué. -- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca oficial de Permisos de Flight. Esta biblioteca es una forma simple de agregar permisos a nivel de usuario y aplicación a tu aplicación. +- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca oficial de Permisos de Flight. Esta biblioteca es una forma simple de agregar permisos a nivel de usuario y aplicación a tu aplicación. ## Caché El caché es una gran manera de acelerar tu aplicación. Hay una serie de bibliotecas de caché que se pueden usar con Flight. -- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Clase ligera, simple y autónoma de caché en archivo PHP +- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Clase ligera, simple y independiente de caché en archivo PHP ## CLI @@ -40,7 +40,7 @@ Las aplicaciones CLI son una gran manera de interactuar con tu aplicación. Pued ## Cookies -Las cookies son una gran manera de almacenar pequeños bits de datos en el lado del cliente. Se pueden usar para almacenar preferencias de usuario, configuraciones de aplicación y más. +Las cookies son una gran manera de almacenar pequeños fragmentos de datos en el lado del cliente. Se pueden usar para almacenar preferencias de usuario, configuraciones de aplicación y más. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie es una biblioteca PHP que proporciona una forma simple y efectiva de gestionar cookies. @@ -48,16 +48,16 @@ Las cookies son una gran manera de almacenar pequeños bits de datos en el lado La depuración es crucial cuando estás desarrollando en tu entorno local. Hay algunos plugins que pueden elevar tu experiencia de depuración. -- [tracy/tracy](/awesome-plugins/tracy) - Esta es una manejadora de errores completa que se puede usar con Flight. Tiene una serie de paneles que pueden ayudarte a depurar tu aplicación. También es muy fácil de extender y agregar tus propios paneles. -- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado con el manejador de errores [Tracy](/awesome-plugins/tracy), este plugin agrega algunos paneles extra para ayudar con la depuración específicamente para proyectos Flight. +- [tracy/tracy](/awesome-plugins/tracy) - Esta es un manejador de errores completo que se puede usar con Flight. Tiene una serie de paneles que pueden ayudarte a depurar tu aplicación. También es muy fácil de extender y agregar tus propios paneles. +- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado con el manejador de errores [Tracy](/awesome-plugins/tracy), este plugin agrega algunos paneles extra para ayudar con la depuración específicamente para proyectos de Flight. ## Bases de Datos -Las bases de datos son el núcleo de la mayoría de las aplicaciones. Así es como almacenas y recuperas datos. Algunas bibliotecas de bases de datos son simplemente envolturas para escribir consultas y otras son ORMs completos. +Las bases de datos son el núcleo de la mayoría de las aplicaciones. Así es como almacenas y recuperas datos. Algunas bibliotecas de bases de datos son simplemente envolturas para escribir consultas y algunas son ORMs completos. - oficial [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Envoltura oficial de PDO de Flight que forma parte del núcleo. Esta es una envoltura simple para ayudar a simplificar el proceso de escribir consultas y ejecutarlas. No es un ORM. -- oficial [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord oficial de Flight. Gran biblioteca pequeña para recuperar y almacenar datos fácilmente en tu base de datos. -- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para mantener un seguimiento de todos los cambios de base de datos para tu proyecto. +- oficial [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper oficial de ActiveRecord de Flight. Gran biblioteca pequeña para recuperar y almacenar datos fácilmente en tu base de datos. +- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para rastrear todos los cambios de base de datos para tu proyecto. ## Encriptación @@ -80,17 +80,18 @@ Las sesiones no son realmente útiles para las API, pero para construir una apli ## Plantillas -Las plantillas son el núcleo de cualquier aplicación web con una UI. Hay una serie de motores de plantillas que se pueden usar con Flight. +La plantillación es el núcleo de cualquier aplicación web con una UI. Hay una serie de motores de plantillas que se pueden usar con Flight. - deprecado [flightphp/core View](/learn#views) - Este es un motor de plantillas muy básico que forma parte del núcleo. No se recomienda usarlo si tienes más de un par de páginas en tu proyecto. - [latte/latte](/awesome-plugins/latte) - Latte es un motor de plantillas completo que es muy fácil de usar y se siente más cercano a la sintaxis de PHP que Twig o Smarty. También es muy fácil de extender y agregar tus propios filtros y funciones. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate es un potente motor de plantillas PHP con compilación de activos, herencia de plantillas y procesamiento de variables. Incluye minificación automática de CSS/JS, caché, codificación Base64 e integración opcional con el framework Flight PHP. ## Integración con WordPress ¿Quieres usar Flight en tu proyecto de WordPress? ¡Hay un plugin práctico para eso! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Este plugin de WordPress te permite ejecutar Flight justo al lado de WordPress. Es perfecto para agregar APIs personalizadas, microservicios o incluso aplicaciones completas a tu sitio de WordPress usando el framework Flight. Súper útil si quieres lo mejor de ambos mundos! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Este plugin de WordPress te permite ejecutar Flight junto con WordPress. Es perfecto para agregar APIs personalizadas, microservicios o incluso aplicaciones completas a tu sitio de WordPress usando el framework Flight. ¡Súper útil si quieres lo mejor de ambos mundos! -## Contribuir +## Contribuyendo ¿Tienes un plugin que te gustaría compartir? ¡Envía una solicitud de pull para agregarlo a la lista! \ No newline at end of file diff --git a/content/v3/es/awesome-plugins/comment_template.md b/content/v3/es/awesome-plugins/comment_template.md new file mode 100644 index 00000000..6bc1d53d --- /dev/null +++ b/content/v3/es/awesome-plugins/comment_template.md @@ -0,0 +1,257 @@ +# CommentTemplate + +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) es un potente motor de plantillas PHP con compilación de activos, herencia de plantillas y procesamiento de variables. Proporciona una manera simple pero flexible de gestionar plantillas con minificación y caché integrados de CSS/JS. + +## Características + +- **Herencia de Plantillas**: Usa diseños y incluye otras plantillas +- **Compilación de Activos**: Minificación y caché automáticos de CSS/JS +- **Procesamiento de Variables**: Variables de plantilla con filtros y comandos +- **Codificación Base64**: Activos en línea como URIs de datos +- **Integración con Flight Framework**: Integración opcional con el framework PHP Flight + +## Instalación + +Instala con composer. + +```bash +composer require knifelemon/comment-template +``` + +## Configuración Básica + +Hay algunas opciones de configuración básicas para comenzar. Puedes leer más sobre ellas en el [Repositorio de CommentTemplate](https://github.com/KnifeLemon/CommentTemplate). + +### Método 1: Usando Función de Retorno de Llamada + +```php +register('view', Engine::class, [], function (Engine $engine) use ($app) { + // Donde se almacenan tus archivos de plantilla + $engine->setTemplatesPath(__DIR__ . '/views'); + + // Donde se servirán tus activos públicos + $engine->setPublicPath(__DIR__ . '/public'); + + // Donde se almacenarán los activos compilados + $engine->setAssetPath('assets'); + + // Extensión de archivo de plantilla + $engine->setFileExtension('.php'); +}); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +### Método 2: Usando Parámetros del Constructor + +```php +register('view', Engine::class, [ + __DIR__ . '/public', // publicPath - donde se servirán los activos + __DIR__ . '/views', // skinPath - donde se almacenan los archivos de plantilla + 'assets', // assetPath - donde se almacenarán los activos compilados + '.php' // fileExtension - extensión de archivo de plantilla +]); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +## Directivas de Plantilla + +### Herencia de Diseño + +Usa diseños para crear una estructura común: + +**layout/global_layout.php**: +```html + + + + {$title} + + + + + +``` + +**view/page.php**: +```html + +

{$title}

+

{$content}

+``` + +### Gestión de Activos + +#### Archivos CSS +```html + + +``` + +#### Archivos JavaScript +CommentTemplate soporta diferentes estrategias de carga de JavaScript: + +```html + + + + + + + + + +``` + +#### Directivas de Activos en Archivos CSS/JS + +CommentTemplate también procesa directivas de activos dentro de archivos CSS y JavaScript durante la compilación: + +**Ejemplo de CSS:** +```css +/* En tus archivos CSS */ +@font-face { + font-family: 'CustomFont'; + src: url('') format('woff2'); +} + +.background-image { + background: url(''); +} + +.inline-icon { + background: url(''); +} +``` + +**Ejemplo de JavaScript:** +```javascript +/* En tus archivos JS */ +const fontUrl = ''; +const imageData = ''; +``` + +#### Codificación Base64 +```html + +``` +** Ejemplo: ** +```html + +Logo +
+ Icono pequeño como fondo +
+``` + +#### Copia de Activos +```html + + +``` +** Ejemplo: ** +```html + +Hero Banner +Descargar Folleto + + + + +``` + +### Inclusiones de Plantilla +```html + +``` +** Ejemplo: ** +```html + + + +
+

Bienvenido a nuestro sitio web

+ + +
+

Contenido principal aquí...

+
+
+ + +``` + +### Procesamiento de Variables + +#### Variables Básicas +```html +

{$title}

+

{$description}

+``` + +#### Filtros de Variables +```html +{$title|upper} +{$content|lower} +{$html|striptag} +{$text|escape} +{$multiline|nl2br} +{$html|br2nl} +{$description|trim} +{$subject|title} +``` + +#### Comandos de Variables +```html +{$title|default=Default Title} +{$name|concat= (Admin)} +``` + +#### Comandos de Variables +```html +{$content|striptag|trim|escape} +``` + +## Estructura de Proyecto de Ejemplo + +``` +project/ +├── source/ +│ ├── layouts/ +│ │ └── default.php +│ ├── components/ +│ │ ├── header.php +│ │ └── footer.php +│ ├── css/ +│ │ ├── bootstrap.min.css +│ │ └── custom.css +│ ├── js/ +│ │ ├── app.js +│ │ └── bootstrap.min.js +│ └── homepage.php +├── public/ +│ └── assets/ # Activos generados +│ ├── css/ +│ └── js/ +└── vendor/ +``` \ No newline at end of file diff --git a/content/v3/es/examples.md b/content/v3/es/examples.md index 9fdf6c70..3dcf8760 100644 --- a/content/v3/es/examples.md +++ b/content/v3/es/examples.md @@ -5,21 +5,22 @@ Tienes dos opciones para comenzar con un nuevo proyecto de Flight: - [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Un ejemplo más completo con controladores y vistas. - [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Un solo archivo que incluye todo lo que necesitas para ejecutar tu aplicación en un archivo simple. -Ejemplos aportados por la comunidad: +Ejemplos contribuidos por la comunidad: - [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP con directorios de Laravel, con herramientas de PHP + GH Actions - [fleact](https://github.com/flightphp/fleact) - Un kit de inicio de FlightPHP con integración de ReactJS. - [flastro](https://github.com/flightphp/flastro) - Un kit de inicio de FlightPHP con integración de Astro. -- [velt](https://github.com/flightphp/velt) - Velt es una plantilla de inicio rápida y fácil para Svelte con un backend de FlightPHP. +- [velt](https://github.com/flightphp/velt) - Velt es una plantilla de inicio rápida y fácil de Svelte con un backend de FlightPHP. ## ¿Necesitas algo de inspiración? Aunque estos no están patrocinados oficialmente por el equipo de Flight, podrían darte ideas sobre cómo estructurar tus propios proyectos construidos con Flight! -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental es una aplicación web de alquiler de autos de una sola página, amigable con dispositivos móviles, construida con PHP (FlightPHP), JavaScript y MySQL. Soporta registro de usuarios, navegación y reserva de autos, mientras que los administradores pueden gestionar autos, usuarios y reservas. La aplicación cuenta con una API REST, autenticación JWT y un diseño responsivo para una experiencia de alquiler moderna. -- [Decay](https://github.com/boxybird/decay) - Flight v3 con HTMX y SleekDB, todo sobre zombis! ([Demo](https://decay.andrewrhyand.com)) +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify es una aplicación de una sola página que conecta a organizadores de eventos con asistentes. Construida con PHP (FlightPHP), JavaScript y MySQL, cuenta con autenticación JWT, gestión de eventos y documentación de API RESTful usando OpenAPI. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental es una aplicación web de alquiler de autos de una sola página, amigable con móviles, construida con PHP (FlightPHP), JavaScript y MySQL. Soporta registro de usuarios, navegación y reserva de autos, mientras que los administradores pueden gestionar autos, usuarios y reservas. La aplicación cuenta con una API REST, autenticación JWT y un diseño responsivo para una experiencia de alquiler moderna. +- [Decay](https://github.com/boxybird/decay) - Flight v3 con HTMX y SleekDB todo sobre zombis! ([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 con Middleware, Controladores, Active Record y Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Proyecto de API CRUD simple utilizando el framework Flight, que proporciona una estructura básica para que los nuevos usuarios configuren rápidamente una aplicación PHP con operaciones CRUD y conectividad a la base de datos. El proyecto demuestra cómo usar Flight para el desarrollo de API RESTful, lo que lo convierte en una herramienta de aprendizaje ideal para principiantes y un kit de inicio útil para desarrolladores más experimentados. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Proyecto simple de API CRUD usando el framework Flight, que proporciona una estructura básica para que los nuevos usuarios configuren rápidamente una aplicación PHP con operaciones CRUD y conectividad a la base de datos. El proyecto demuestra cómo usar Flight para el desarrollo de API RESTful, convirtiéndolo en una herramienta de aprendizaje ideal para principiantes y un kit de inicio útil para desarrolladores más experimentados. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -30,8 +31,8 @@ Aunque estos no están patrocinados oficialmente por el equipo de Flight, podrí - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework de autenticación listo para producción que te ahorra semanas de desarrollo. Características de seguridad de grado empresarial: 2FA/TOTP, integración LDAP, SSO de Azure, limitación de velocidad inteligente, huella dactilar de sesión, protección contra fuerza bruta, panel de análisis de seguridad, registro de auditoría completo y control de acceso basado en roles granular. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework de autenticación listo para producción que te ahorra semanas de desarrollo. Cuenta con seguridad de grado empresarial: 2FA/TOTP, integración LDAP, Azure SSO, limitación de tasa inteligente, huella dactilar de sesión, protección contra fuerza bruta, panel de análisis de seguridad, registro de auditoría integral y control de acceso basado en roles granular. ## ¿Quieres compartir tu propio ejemplo? -Si tienes un proyecto que quieres compartir, ¡por favor envía una solicitud de pull para agregarlo a esta lista! \ No newline at end of file +Si tienes un proyecto que quieres compartir, por favor envía una solicitud de pull para agregarlo a esta lista! \ No newline at end of file diff --git a/content/v3/fr/awesome-plugins/awesome_plugins.md b/content/v3/fr/awesome-plugins/awesome_plugins.md index 797523c3..2bf4f82e 100644 --- a/content/v3/fr/awesome-plugins/awesome_plugins.md +++ b/content/v3/fr/awesome-plugins/awesome_plugins.md @@ -1,46 +1,46 @@ -# Plugins Géniaux +# Plugins Formidables -Flight est incroyablement extensible. Il existe un certain nombre de plugins qui peuvent être utilisés pour ajouter des fonctionnalités à votre application Flight. Certains sont officiellement supportés par l'équipe Flight et d'autres sont des bibliothèques micro/lite pour vous aider à démarrer. +Flight est incroyablement extensible. Il existe un certain nombre de plugins qui peuvent être utilisés pour ajouter des fonctionnalités à votre application Flight. Certains sont officiellement pris en charge par l'équipe Flight et d'autres sont des bibliothèques micro/lite pour vous aider à démarrer. ## Documentation API La documentation API est cruciale pour toute API. Elle aide les développeurs à comprendre comment interagir avec votre API et ce qu'ils peuvent attendre en retour. Il existe quelques outils disponibles pour vous aider à générer la documentation API pour vos projets Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Article de blog écrit par Daniel Schreiber sur la façon d'utiliser la spécification OpenAPI avec FlightPHP pour construire votre API en adoptant une approche API first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI est un excellent outil pour vous aider à générer la documentation API pour vos projets Flight. Il est très facile à utiliser et peut être personnalisé selon vos besoins. C'est la bibliothèque PHP pour vous aider à générer la documentation Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Article de blog écrit par Daniel Schreiber sur la façon d'utiliser la spécification OpenAPI avec FlightPHP pour construire votre API en adoptant une approche API-first. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI est un excellent outil pour vous aider à générer la documentation API pour vos projets Flight. Il est très facile à utiliser et peut être personnalisé selon vos besoins. Il s'agit de la bibliothèque PHP pour vous aider à générer la documentation Swagger. ## Surveillance des Performances des Applications (APM) -La surveillance des performances des applications (APM) est cruciale pour toute application. Elle vous aide à comprendre comment votre application performe et où se trouvent les goulots d'étranglement. Il existe un certain nombre d'outils APM qui peuvent être utilisés avec Flight. +La surveillance des performances des applications (APM) est cruciale pour toute application. Elle vous aide à comprendre comment votre application se comporte et où se trouvent les goulots d'étranglement. Il existe un certain nombre d'outils APM qui peuvent être utilisés avec Flight. - officiel [flightphp/apm](/awesome-plugins/apm) - Flight APM est une bibliothèque APM simple qui peut être utilisée pour surveiller vos applications Flight. Elle peut être utilisée pour surveiller les performances de votre application et vous aider à identifier les goulots d'étranglement. ## Asynchrone -Flight est déjà un framework rapide, mais lui ajouter un turbo le rend encore plus amusant (et challenging) ! +Flight est déjà un framework rapide, mais lui ajouter un moteur turbo rend tout plus amusant (et plus stimulant) ! - [flightphp/async](/awesome-plugins/async) - Bibliothèque officielle Flight Async. Cette bibliothèque est une façon simple d'ajouter un traitement asynchrone à votre application. Elle utilise Swoole/Openswoole en arrière-plan pour fournir une façon simple et efficace d'exécuter des tâches de manière asynchrone. ## Autorisation/Permissions -L'autorisation et les permissions sont cruciales pour toute application qui nécessite des contrôles sur qui peut accéder à quoi. +L'autorisation et les permissions sont cruciales pour toute application qui nécessite des contrôles pour déterminer qui peut accéder à quoi. - officiel [flightphp/permissions](/awesome-plugins/permissions) - Bibliothèque officielle Flight Permissions. Cette bibliothèque est une façon simple d'ajouter des permissions au niveau utilisateur et application à votre application. ## Mise en Cache -La mise en cache est une excellente façon d'accélérer votre application. Il existe un certain nombre de bibliothèques de mise en cache qui peuvent être utilisées avec Flight. +La mise en cache est un excellent moyen d'accélérer votre application. Il existe un certain nombre de bibliothèques de mise en cache qui peuvent être utilisées avec Flight. -- officiel [flightphp/cache](/awesome-plugins/php-file-cache) - Classe PHP légère, simple et autonome pour la mise en cache en fichier +- officiel [flightphp/cache](/awesome-plugins/php-file-cache) - Classe de mise en cache PHP légère, simple et autonome en fichier ## CLI -Les applications CLI sont une excellente façon d'interagir avec votre application. Vous pouvez les utiliser pour générer des contrôleurs, afficher toutes les routes, et plus encore. +Les applications CLI sont un excellent moyen d'interagir avec votre application. Vous pouvez les utiliser pour générer des contrôleurs, afficher toutes les routes, et plus encore. - officiel [flightphp/runway](/awesome-plugins/runway) - Runway est une application CLI qui vous aide à gérer vos applications Flight. ## Cookies -Les cookies sont une excellente façon de stocker de petites quantités de données côté client. Ils peuvent être utilisés pour stocker les préférences utilisateur, les paramètres d'application, et plus encore. +Les cookies sont un excellent moyen de stocker de petites quantités de données côté client. Ils peuvent être utilisés pour stocker les préférences utilisateur, les paramètres d'application, et plus encore. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie est une bibliothèque PHP qui fournit une façon simple et efficace de gérer les cookies. @@ -48,42 +48,43 @@ Les cookies sont une excellente façon de stocker de petites quantités de donn Le débogage est crucial lorsque vous développez dans votre environnement local. Il existe quelques plugins qui peuvent améliorer votre expérience de débogage. -- [tracy/tracy](/awesome-plugins/tracy) - C'est un gestionnaire d'erreurs complet qui peut être utilisé avec Flight. Il dispose d'un certain nombre de panneaux qui peuvent vous aider à déboguer votre application. Il est également très facile à étendre et à ajouter vos propres panneaux. +- [tracy/tracy](/awesome-plugins/tracy) - Il s'agit d'un gestionnaire d'erreurs complet qui peut être utilisé avec Flight. Il dispose d'un certain nombre de panneaux qui peuvent vous aider à déboguer votre application. Il est également très facile à étendre et à ajouter vos propres panneaux. - officiel [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Utilisé avec le gestionnaire d'erreurs [Tracy](/awesome-plugins/tracy), ce plugin ajoute quelques panneaux supplémentaires pour aider au débogage spécifiquement pour les projets Flight. ## Bases de Données Les bases de données sont au cœur de la plupart des applications. C'est ainsi que vous stockez et récupérez les données. Certaines bibliothèques de bases de données sont simplement des wrappers pour écrire des requêtes et d'autres sont des ORMs complets. -- officiel [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO officiel Flight qui fait partie du cœur. C'est un wrapper simple pour aider à simplifier le processus d'écriture et d'exécution des requêtes. Ce n'est pas un ORM. -- officiel [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord officiel Flight. Excellente petite bibliothèque pour récupérer et stocker facilement des données dans votre base de données. +- officiel [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO officiel Flight qui fait partie du cœur. Il s'agit d'un wrapper simple pour aider à simplifier le processus d'écriture et d'exécution des requêtes. Ce n'est pas un ORM. +- officiel [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord officiel Flight. Excellente petite bibliothèque pour récupérer et stocker facilement les données dans votre base de données. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin pour suivre toutes les modifications de base de données pour votre projet. ## Chiffrement Le chiffrement est crucial pour toute application qui stocke des données sensibles. Chiffrer et déchiffrer les données n'est pas terriblement difficile, mais stocker correctement la clé de chiffrement [peut](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [être](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difficile](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). La chose la plus importante est de ne jamais stocker votre clé de chiffrement dans un répertoire public ou de l'engager dans votre dépôt de code. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - C'est une bibliothèque qui peut être utilisée pour chiffrer et déchiffrer des données. Se mettre en route est assez simple pour commencer à chiffrer et déchiffrer des données. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - Il s'agit d'une bibliothèque qui peut être utilisée pour chiffrer et déchiffrer les données. Se mettre en route est assez simple pour commencer à chiffrer et déchiffrer les données. ## File d'Attente de Tâches Les files d'attente de tâches sont vraiment utiles pour traiter les tâches de manière asynchrone. Cela peut être l'envoi d'emails, le traitement d'images, ou tout ce qui n'a pas besoin d'être fait en temps réel. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue est une bibliothèque qui peut être utilisée pour traiter les tâches de manière asynchrone. Elle peut être utilisée avec beanstalkd, MySQL/MariaDB, SQLite, et PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue est une bibliothèque qui peut être utilisée pour traiter les tâches de manière asynchrone. Elle peut être utilisée avec beanstalkd, MySQL/MariaDB, SQLite et PostgreSQL. ## Session Les sessions ne sont pas vraiment utiles pour les API, mais pour construire une application web, les sessions peuvent être cruciales pour maintenir l'état et les informations de connexion. -- officiel [flightphp/session](/awesome-plugins/session) - Bibliothèque officielle Flight Session. C'est une bibliothèque de session simple qui peut être utilisée pour stocker et récupérer les données de session. Elle utilise la gestion de session intégrée de PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - Gestionnaire de Session PHP (non-bloquant, flash, segment, chiffrement de session). Utilise PHP open_ssl pour le chiffrement/déchiffrement optionnel des données de session. +- officiel [flightphp/session](/awesome-plugins/session) - Bibliothèque officielle Flight Session. Il s'agit d'une bibliothèque de session simple qui peut être utilisée pour stocker et récupérer les données de session. Elle utilise la gestion de session intégrée de PHP. +- [Ghostff/Session](/awesome-plugins/ghost-session) - Gestionnaire de sessions PHP (non-bloquant, flash, segment, chiffrement de session). Utilise PHP open_ssl pour le chiffrement/déchiffrement optionnel des données de session. ## Modélisation La modélisation est au cœur de toute application web avec une interface utilisateur. Il existe un certain nombre de moteurs de modélisation qui peuvent être utilisés avec Flight. -- déprécié [flightphp/core View](/learn#views) - C'est un moteur de modélisation très basique qui fait partie du cœur. Il n'est pas recommandé de l'utiliser si vous avez plus de quelques pages dans votre projet. -- [latte/latte](/awesome-plugins/latte) - Latte est un moteur de modélisation complet qui est très facile à utiliser et se rapproche plus de la syntaxe PHP que Twig ou Smarty. Il est également très facile à étendre et à ajouter vos propres filtres et fonctions. +- déprécié [flightphp/core View](/learn#views) - Il s'agit d'un moteur de modélisation très basique qui fait partie du cœur. Il n'est pas recommandé de l'utiliser si vous avez plus de quelques pages dans votre projet. +- [latte/latte](/awesome-plugins/latte) - Latte est un moteur de modélisation complet qui est très facile à utiliser et qui ressemble plus à une syntaxe PHP que Twig ou Smarty. Il est également très facile à étendre et à ajouter vos propres filtres et fonctions. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate est un puissant moteur de templates PHP avec compilation d'actifs, héritage de templates et traitement de variables. Fonctionnalités : minification automatique CSS/JS, mise en cache, encodage Base64 et intégration optionnelle avec le framework PHP Flight. ## Intégration WordPress @@ -93,4 +94,4 @@ Vous voulez utiliser Flight dans votre projet WordPress ? Il y a un plugin prati ## Contribution -Vous avez un plugin que vous aimeriez partager ? Soumettez une pull request pour l'ajouter à la liste ! \ No newline at end of file +Vous avez un plugin que vous aimeriez partager ? Soumettez une demande de tirage pour l'ajouter à la liste ! \ No newline at end of file diff --git a/content/v3/fr/awesome-plugins/comment_template.md b/content/v3/fr/awesome-plugins/comment_template.md new file mode 100644 index 00000000..d23634ae --- /dev/null +++ b/content/v3/fr/awesome-plugins/comment_template.md @@ -0,0 +1,257 @@ +# CommentTemplate + +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) est un puissant moteur de templates PHP avec compilation d'actifs, héritage de templates et traitement des variables. Il fournit une façon simple mais flexible de gérer les templates avec une minification CSS/JS intégrée et un cache. + +## Fonctionnalités + +- **Héritage de Templates** : Utilisez des layouts et incluez d'autres templates +- **Compilation d'Actifs** : Minification et cache automatique CSS/JS +- **Traitement des Variables** : Variables de template avec filtres et commandes +- **Encodage Base64** : Actifs en ligne sous forme d'URI de données +- **Intégration avec le Framework Flight** : Intégration optionnelle avec le framework PHP Flight + +## Installation + +Installez avec composer. + +```bash +composer require knifelemon/comment-template +``` + +## Configuration de Base + +Il existe quelques options de configuration de base pour commencer. Vous pouvez en lire plus à leur sujet dans le [Repo CommentTemplate](https://github.com/KnifeLemon/CommentTemplate). + +### Méthode 1 : Utilisation d'une Fonction de Callback + +```php +register('view', Engine::class, [], function (Engine $engine) use ($app) { + // Où vos fichiers de templates sont stockés + $engine->setTemplatesPath(__DIR__ . '/views'); + + // D'où vos actifs publics seront servis + $engine->setPublicPath(__DIR__ . '/public'); + + // Où les actifs compilés seront stockés + $engine->setAssetPath('assets'); + + // Extension des fichiers de template + $engine->setFileExtension('.php'); +}); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +### Méthode 2 : Utilisation des Paramètres du Constructeur + +```php +register('view', Engine::class, [ + __DIR__ . '/public', // publicPath - d'où les actifs seront servis + __DIR__ . '/views', // skinPath - où les fichiers de templates sont stockés + 'assets', // assetPath - où les actifs compilés seront stockés + '.php' // fileExtension - extension des fichiers de template +]); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +## Directives de Template + +### Héritage de Layout + +Utilisez des layouts pour créer une structure commune : + +**layout/global_layout.php** : +```html + + + + {$title} + + + + + +``` + +**view/page.php** : +```html + +

{$title}

+

{$content}

+``` + +### Gestion des Actifs + +#### Fichiers CSS +```html + + +``` + +#### Fichiers JavaScript +CommentTemplate prend en charge différentes stratégies de chargement JavaScript : + +```html + + + + + + + + + +``` + +#### Directives d'Actifs dans les Fichiers CSS/JS + +CommentTemplate traite également les directives d'actifs au sein des fichiers CSS et JavaScript lors de la compilation : + +**Exemple CSS :** +```css +/* Dans vos fichiers CSS */ +@font-face { + font-family: 'CustomFont'; + src: url('') format('woff2'); +} + +.background-image { + background: url(''); +} + +.inline-icon { + background: url(''); +} +``` + +**Exemple JavaScript :** +```javascript +/* Dans vos fichiers JS */ +const fontUrl = ''; +const imageData = ''; +``` + +#### Encodage Base64 +```html + +``` +** Exemple : ** +```html + +Logo +
+ Petite icône en arrière-plan +
+``` + +#### Copie d'Actifs +```html + + +``` +** Exemple : ** +```html + +Bannière Héroïque +Télécharger la Brochure + + + + +``` + +### Inclutions de Templates +```html + +``` +** Exemple : ** +```html + + + +
+

Bienvenue sur notre site web

+ + +
+

Contenu principal ici...

+
+
+ + +``` + +### Traitement des Variables + +#### Variables de Base +```html +

{$title}

+

{$description}

+``` + +#### Filtres de Variables +```html +{$title|upper} +{$content|lower} +{$html|striptag} +{$text|escape} +{$multiline|nl2br} +{$html|br2nl} +{$description|trim} +{$subject|title} +``` + +#### Commandes de Variables +```html +{$title|default=Default Title} +{$name|concat= (Admin)} +``` + +#### Commandes de Variables +```html +{$content|striptag|trim|escape} +``` + +## Structure de Projet Exemple + +``` +project/ +├── source/ +│ ├── layouts/ +│ │ └── default.php +│ ├── components/ +│ │ ├── header.php +│ │ └── footer.php +│ ├── css/ +│ │ ├── bootstrap.min.css +│ │ └── custom.css +│ ├── js/ +│ │ ├── app.js +│ │ └── bootstrap.min.js +│ └── homepage.php +├── public/ +│ └── assets/ # Actifs générés +│ ├── css/ +│ └── js/ +└── vendor/ +``` \ No newline at end of file diff --git a/content/v3/fr/examples.md b/content/v3/fr/examples.md index f8de6a4c..21e4a63a 100644 --- a/content/v3/fr/examples.md +++ b/content/v3/fr/examples.md @@ -10,27 +10,28 @@ Exemples contributés par la communauté : - [flightravel](https://github.com/fadrian06-templates/flighravel) : FlightPHP avec des répertoires Laravel, avec des outils PHP + GH Actions - [fleact](https://github.com/flightphp/fleact) - Un kit de démarrage FlightPHP avec intégration ReactJS. - [flastro](https://github.com/flightphp/flastro) - Un kit de démarrage FlightPHP avec intégration Astro. -- [velt](https://github.com/flightphp/velt) - Velt est un modèle de démarrage Svelte rapide et facile avec un backend FlightPHP. +- [velt](https://github.com/flightphp/velt) - Velt est un modèle de démarrage rapide et facile pour Svelte avec un backend FlightPHP. ## Besoin d'inspiration ? Bien que ces exemples ne soient pas officiellement sponsorisés par l'équipe Flight, ils pourraient vous donner des idées sur la façon de structurer vos propres projets construits avec Flight ! -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental est une application web de location de voitures monopage, adaptée aux mobiles, construite avec PHP (FlightPHP), JavaScript et MySQL. Elle prend en charge l'inscription des utilisateurs, la navigation et la réservation de voitures, tandis que les administrateurs peuvent gérer les voitures, les utilisateurs et les réservations. L'application propose une API REST, une authentification JWT et un design responsive pour une expérience de location moderne. -- [Decay](https://github.com/boxybird/decay) - Flight v3 avec HTMX et SleekDB, tout sur les zombies ! ([Démo](https://decay.andrewrhyand.com)) -- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 avec Middleware, Controllers, Active Record et Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Projet d'API CRUD simple utilisant le framework Flight, qui fournit une structure de base pour que les nouveaux utilisateurs configurent rapidement une application PHP avec des opérations CRUD et une connectivité à la base de données. Le projet démontre comment utiliser Flight pour le développement d'API RESTful, ce qui en fait un outil d'apprentissage idéal pour les débutants et un kit de démarrage utile pour les développeurs plus expérimentés. +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify est une application monopage connectant les organisateurs d'événements avec les participants. Construite avec PHP (FlightPHP), JavaScript et MySQL, elle inclut une authentification JWT, la gestion d'événements et des docs API RESTful utilisant OpenAPI. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental est une application web monopage, adaptée aux mobiles, pour la location de voitures construite avec PHP (FlightPHP), JavaScript et MySQL. Elle supporte l'inscription des utilisateurs, la navigation et la réservation de voitures, tandis que les admins peuvent gérer les voitures, les utilisateurs et les réservations. L'application inclut une API REST, une authentification JWT et un design responsive pour une expérience de location moderne. +- [Decay](https://github.com/boxybird/decay) - Flight v3 avec HTMX et SleekDB tout sur les zombies ! ([Démo](https://decay.andrewrhyand.com)) +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 avec Middleware, Contrôleurs, Active Record et Latte. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Projet API CRUD simple utilisant le framework Flight, qui fournit une structure de base pour que les nouveaux utilisateurs configurent rapidement une application PHP avec des opérations CRUD et une connectivité à la base de données. Le projet démontre comment utiliser Flight pour le développement d'API RESTful, en en faisant un outil d'apprentissage idéal pour les débutants et un kit de démarrage utile pour les développeurs plus expérimentés. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) - [Example Wiki](https://github.com/Skayo/FlightWiki) - [The IT-Innovator PHP Framework Application](https://github.com/itinnovator/myphp-app) -- [LittleEducationalCMS (Espagnol)](https://github.com/casgin/LittleEducationalCMS) +- [LittleEducationalCMS (Spanish)](https://github.com/casgin/LittleEducationalCMS) - [Italian Yellow Pages API](https://github.com/chiccomagnus/PGAPI) -- [Generic Content Management System (avec....très peu de documentation)](https://github.com/recepuncu/cms) +- [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework d'authentification prêt pour la production qui vous fait économiser des semaines de développement. Fonctionnalités de sécurité de niveau entreprise : 2FA/TOTP, intégration LDAP, SSO Azure, limitation de taux intelligente, empreinte de session, protection contre les attaques par force brute, tableau de bord d'analyse de sécurité, journalisation d'audit complète et contrôle d'accès basé sur les rôles granulaire. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework d'authentification prêt pour la production qui vous fait économiser des semaines de développement. Fonctionnalités de sécurité de niveau entreprise : 2FA/TOTP, intégration LDAP, SSO Azure, limitation de taux intelligente, empreinte de session, protection contre les attaques par force brute, tableau de bord d'analyse de sécurité, journalisation d'audit complète et contrôle d'accès granulaire basé sur les rôles. ## Voulez-vous partager votre propre exemple ? diff --git a/content/v3/id/awesome-plugins/awesome_plugins.md b/content/v3/id/awesome-plugins/awesome_plugins.md index bcd880f4..4535c3f0 100644 --- a/content/v3/id/awesome-plugins/awesome_plugins.md +++ b/content/v3/id/awesome-plugins/awesome_plugins.md @@ -1,6 +1,6 @@ # Plugin Hebat -Flight sangat dapat diperluas. Ada sejumlah plugin yang dapat digunakan untuk menambahkan fungsionalitas ke aplikasi Flight Anda. Beberapa didukung secara resmi oleh Tim Flight dan yang lainnya adalah pustaka mikro/lite untuk membantu Anda memulai. +Flight sangat dapat dikembangkan. Ada sejumlah plugin yang dapat digunakan untuk menambahkan fungsionalitas ke aplikasi Flight Anda. Beberapa didukung secara resmi oleh Tim Flight dan yang lainnya adalah pustaka mikro/lite untuk membantu Anda memulai. ## Dokumentasi API @@ -11,26 +11,26 @@ Dokumentasi API sangat penting untuk API apa pun. Ini membantu pengembang memaha ## Pemantauan Kinerja Aplikasi (APM) -Pemantauan Kinerja Aplikasi (APM) sangat penting untuk aplikasi apa pun. Ini membantu Anda memahami bagaimana aplikasi Anda berkinerja dan di mana titik penyumbatannya. Ada sejumlah alat APM yang dapat digunakan dengan Flight. -- resmi [flightphp/apm](/awesome-plugins/apm) - Flight APM adalah pustaka APM sederhana yang dapat digunakan untuk memantau aplikasi Flight Anda. Ini dapat digunakan untuk memantau kinerja aplikasi Anda dan membantu Anda mengidentifikasi titik penyumbatan. +Pemantauan Kinerja Aplikasi (APM) sangat penting untuk aplikasi apa pun. Ini membantu Anda memahami bagaimana aplikasi Anda berkinerja dan di mana kemacetan terjadi. Ada sejumlah alat APM yang dapat digunakan dengan Flight. +- resmi [flightphp/apm](/awesome-plugins/apm) - Flight APM adalah pustaka APM sederhana yang dapat digunakan untuk memantau aplikasi Flight Anda. Ini dapat digunakan untuk memantau kinerja aplikasi Anda dan membantu Anda mengidentifikasi kemacetan. -## Async +## Asinkron -Flight sudah merupakan framework yang cepat, tetapi menambahkan mesin turbo padanya membuat semuanya lebih menyenangkan (dan menantang)! +Flight sudah merupakan kerangka kerja yang cepat, tetapi menambahkan mesin turbo padanya membuat semuanya lebih menyenangkan (dan menantang)! - [flightphp/async](/awesome-plugins/async) - Pustaka Async Flight resmi. Pustaka ini adalah cara sederhana untuk menambahkan pemrosesan asinkron ke aplikasi Anda. Ini menggunakan Swoole/Openswoole di balik layar untuk menyediakan cara sederhana dan efektif untuk menjalankan tugas secara asinkron. ## Otorisasi/Izin -Otorisasi dan Izin sangat penting untuk aplikasi apa pun yang memerlukan kontrol untuk siapa yang dapat mengakses apa. +Otorisasi dan Izin sangat penting untuk aplikasi apa pun yang memerlukan kontrol atas siapa yang dapat mengakses apa. -- resmi [flightphp/permissions](/awesome-plugins/permissions) - Pustaka Permissions Flight resmi. Pustaka ini adalah cara sederhana untuk menambahkan izin tingkat pengguna dan aplikasi ke aplikasi Anda. +- resmi [flightphp/permissions](/awesome-plugins/permissions) - Pustaka Permissions Flight resmi. Pustaka ini adalah cara sederhana untuk menambahkan izin tingkat pengguna dan aplikasi ke aplikasi Anda. ## Penyimpanan Cache Penyimpanan cache adalah cara hebat untuk mempercepat aplikasi Anda. Ada sejumlah pustaka caching yang dapat digunakan dengan Flight. -- resmi [flightphp/cache](/awesome-plugins/php-file-cache) - Kelas caching in-file PHP yang ringan, sederhana, dan standalone +- resmi [flightphp/cache](/awesome-plugins/php-file-cache) - Kelas caching dalam file PHP yang ringan, sederhana, dan mandiri ## CLI @@ -46,28 +46,28 @@ Cookies adalah cara hebat untuk menyimpan bit data kecil di sisi klien. Mereka d ## Debugging -Debugging sangat penting ketika Anda mengembangkan di lingkungan lokal Anda. Ada beberapa plugin yang dapat meningkatkan pengalaman debugging Anda. +Debugging sangat penting saat Anda mengembangkan di lingkungan lokal Anda. Ada beberapa plugin yang dapat meningkatkan pengalaman debugging Anda. -- [tracy/tracy](/awesome-plugins/tracy) - Ini adalah penanganan kesalahan lengkap yang dapat digunakan dengan Flight. Ini memiliki sejumlah panel yang dapat membantu Anda mendebug aplikasi Anda. Ini juga sangat mudah untuk diperluas dan menambahkan panel Anda sendiri. -- resmi [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Digunakan dengan penanganan kesalahan [Tracy](/awesome-plugins/tracy), plugin ini menambahkan beberapa panel ekstra untuk membantu debugging khusus untuk proyek Flight. +- [tracy/tracy](/awesome-plugins/tracy) - Ini adalah penanganan kesalahan lengkap yang dapat digunakan dengan Flight. Ini memiliki sejumlah panel yang dapat membantu Anda mendiagnosis aplikasi Anda. Ini juga sangat mudah untuk diperluas dan menambahkan panel Anda sendiri. +- resmi [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Digunakan dengan penanganan kesalahan [Tracy](/awesome-plugins/tracy), plugin ini menambahkan beberapa panel tambahan untuk membantu debugging khusus untuk proyek Flight. ## Database -Database adalah inti dari sebagian besar aplikasi. Ini adalah cara Anda menyimpan dan mengambil data. Beberapa pustaka database hanyalah wrapper untuk menulis query dan beberapa adalah ORM lengkap. +Database adalah inti dari sebagian besar aplikasi. Inilah cara Anda menyimpan dan mengambil data. Beberapa pustaka database hanyalah pembungkus untuk menulis kueri dan beberapa adalah ORM lengkap. -- resmi [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO Flight resmi yang merupakan bagian dari inti. Ini adalah wrapper sederhana untuk membantu menyederhanakan proses penulisan query dan mengeksekusinya. Ini bukan ORM. +- resmi [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Pembungkus PDO Flight resmi yang merupakan bagian dari inti. Ini adalah pembungkus sederhana untuk membantu menyederhanakan proses penulisan kueri dan mengeksekusinya. Ini bukan ORM. - resmi [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord Flight resmi. Pustaka kecil yang hebat untuk dengan mudah mengambil dan menyimpan data di database Anda. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin untuk melacak semua perubahan database untuk proyek Anda. ## Enkripsi -Enkripsi sangat penting untuk aplikasi apa pun yang menyimpan data sensitif. Mengenkripsi dan mendekripsi data tidak terlalu sulit, tetapi menyimpan kunci enkripsi dengan benar [bisa](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [menjadi](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [sulit](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Hal yang paling penting adalah jangan pernah menyimpan kunci enkripsi Anda di direktori publik atau mengommitnya ke repositori kode Anda. +Enkripsi sangat penting untuk aplikasi apa pun yang menyimpan data sensitif. Mengenkripsi dan mendekripsi data tidak terlalu sulit, tetapi menyimpan kunci enkripsi dengan benar [bisa](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [jadi](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [sulit](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Hal yang paling penting adalah jangan pernah menyimpan kunci enkripsi Anda di direktori publik atau mengkomitnya ke repositori kode Anda. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Ini adalah pustaka yang dapat digunakan untuk mengenkripsi dan mendekripsi data. Memulai dan menjalankannya cukup sederhana untuk mulai mengenkripsi dan mendekripsi data. ## Antrian Pekerjaan -Antrian pekerjaan sangat membantu untuk memproses tugas secara asinkron. Ini bisa mengirim email, memproses gambar, atau apa pun yang tidak perlu dilakukan secara real-time. +Antrian pekerjaan sangat membantu untuk memproses tugas secara asinkron. Ini bisa berupa mengirim email, memproses gambar, atau apa pun yang tidak perlu dilakukan secara real-time. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue adalah pustaka yang dapat digunakan untuk memproses pekerjaan secara asinkron. Ini dapat digunakan dengan beanstalkd, MySQL/MariaDB, SQLite, dan PostgreSQL. @@ -84,12 +84,13 @@ Templating adalah inti dari aplikasi web apa pun dengan UI. Ada sejumlah mesin t - deprecated [flightphp/core View](/learn#views) - Ini adalah mesin templating dasar yang merupakan bagian dari inti. Tidak disarankan untuk digunakan jika Anda memiliki lebih dari beberapa halaman di proyek Anda. - [latte/latte](/awesome-plugins/latte) - Latte adalah mesin templating lengkap yang sangat mudah digunakan dan terasa lebih dekat dengan sintaks PHP daripada Twig atau Smarty. Ini juga sangat mudah untuk diperluas dan menambahkan filter dan fungsi Anda sendiri. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate adalah mesin template PHP yang kuat dengan kompilasi aset, pewarisan template, dan pemrosesan variabel. Fitur minifikasi CSS/JS otomatis, caching, pengkodean Base64, dan integrasi kerangka kerja Flight PHP opsional. ## Integrasi WordPress Ingin menggunakan Flight di proyek WordPress Anda? Ada plugin yang berguna untuk itu! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Plugin WordPress ini memungkinkan Anda menjalankan Flight tepat di samping WordPress. Ini sempurna untuk menambahkan API khusus, microservices, atau bahkan aplikasi lengkap ke situs WordPress Anda menggunakan framework Flight. Sangat berguna jika Anda ingin yang terbaik dari kedua dunia! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Plugin WordPress ini memungkinkan Anda menjalankan Flight tepat di samping WordPress. Ini sempurna untuk menambahkan API khusus, mikroservis, atau bahkan aplikasi lengkap ke situs WordPress Anda menggunakan kerangka kerja Flight. Sangat berguna jika Anda ingin yang terbaik dari kedua dunia! ## Kontribusi diff --git a/content/v3/id/awesome-plugins/comment_template.md b/content/v3/id/awesome-plugins/comment_template.md new file mode 100644 index 00000000..0d27b752 --- /dev/null +++ b/content/v3/id/awesome-plugins/comment_template.md @@ -0,0 +1,257 @@ +# CommentTemplate + +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) adalah mesin template PHP yang kuat dengan kompilasi aset, pewarisan template, dan pemrosesan variabel. Ini menyediakan cara sederhana namun fleksibel untuk mengelola template dengan minifikasi CSS/JS bawaan dan caching. + +## Fitur + +- **Pewarisan Template**: Gunakan layout dan sertakan template lain +- **Kompilasi Aset**: Minifikasi CSS/JS otomatis dan caching +- **Pemrosesan Variabel**: Variabel template dengan filter dan perintah +- **Encoding Base64**: Aset inline sebagai data URI +- **Integrasi Framework Flight**: Integrasi opsional dengan framework PHP Flight + +## Instalasi + +Instal dengan composer. + +```bash +composer require knifelemon/comment-template +``` + +## Konfigurasi Dasar + +Ada beberapa opsi konfigurasi dasar untuk memulai. Anda dapat membaca lebih lanjut tentangnya di [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate). + +### Metode 1: Menggunakan Fungsi Callback + +```php +register('view', Engine::class, [], function (Engine $engine) use ($app) { + // Tempat file template disimpan + $engine->setTemplatesPath(__DIR__ . '/views'); + + // Tempat aset publik akan disajikan + $engine->setPublicPath(__DIR__ . '/public'); + + // Tempat aset yang dikompilasi akan disimpan + $engine->setAssetPath('assets'); + + // Ekstensi file template + $engine->setFileExtension('.php'); +}); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +### Metode 2: Menggunakan Parameter Konstruktor + +```php +register('view', Engine::class, [ + __DIR__ . '/public', // publicPath - tempat aset akan disajikan + __DIR__ . '/views', // skinPath - tempat file template disimpan + 'assets', // assetPath - tempat aset yang dikompilasi akan disimpan + '.php' // fileExtension - ekstensi file template +]); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +## Direktif Template + +### Pewarisan Layout + +Gunakan layout untuk membuat struktur umum: + +**layout/global_layout.php**: +```html + + + + {$title} + + + + + +``` + +**view/page.php**: +```html + +

{$title}

+

{$content}

+``` + +### Pengelolaan Aset + +#### File CSS +```html + + +``` + +#### File JavaScript +CommentTemplate mendukung strategi pemuatan JavaScript yang berbeda: + +```html + + + + + + + + + +``` + +#### Direktif Aset dalam File CSS/JS + +CommentTemplate juga memproses direktif aset dalam file CSS dan JavaScript selama kompilasi: + +**Contoh CSS:** +```css +/* Di file CSS Anda */ +@font-face { + font-family: 'CustomFont'; + src: url('') format('woff2'); +} + +.background-image { + background: url(''); +} + +.inline-icon { + background: url(''); +} +``` + +**Contoh JavaScript:** +```javascript +/* Di file JS Anda */ +const fontUrl = ''; +const imageData = ''; +``` + +#### Encoding Base64 +```html + +``` +** Contoh: ** +```html + +Logo +
+ Ikon kecil sebagai latar belakang +
+``` + +#### Penyalinan Aset +```html + + +``` +** Contoh: ** +```html + +Hero Banner +Unduh Brosur + + + + +``` + +### Penyertaan Template +```html + +``` +** Contoh: ** +```html + + + +
+

Selamat datang di situs web kami

+ + +
+

Konten utama di sini...

+
+
+ + +``` + +### Pemrosesan Variabel + +#### Variabel Dasar +```html +

{$title}

+

{$description}

+``` + +#### Filter Variabel +```html +{$title|upper} +{$content|lower} +{$html|striptag} +{$text|escape} +{$multiline|nl2br} +{$html|br2nl} +{$description|trim} +{$subject|title} +``` + +#### Perintah Variabel +```html +{$title|default=Default Title} +{$name|concat= (Admin)} +``` + +#### Perintah Variabel +```html +{$content|striptag|trim|escape} +``` + +## Struktur Proyek Contoh + +``` +project/ +├── source/ +│ ├── layouts/ +│ │ └── default.php +│ ├── components/ +│ │ ├── header.php +│ │ └── footer.php +│ ├── css/ +│ │ ├── bootstrap.min.css +│ │ └── custom.css +│ ├── js/ +│ │ ├── app.js +│ │ └── bootstrap.min.js +│ └── homepage.php +├── public/ +│ └── assets/ # Aset yang dihasilkan +│ ├── css/ +│ └── js/ +└── vendor/ +``` \ No newline at end of file diff --git a/content/v3/id/examples.md b/content/v3/id/examples.md index f5ccc3e4..500af2a7 100644 --- a/content/v3/id/examples.md +++ b/content/v3/id/examples.md @@ -1,4 +1,4 @@ -# Butuh mulai cepat? +# Perlu Mulai Cepat? Anda memiliki dua opsi untuk memulai proyek Flight baru: @@ -7,7 +7,7 @@ Anda memiliki dua opsi untuk memulai proyek Flight baru: Contoh yang disumbangkan oleh komunitas: -- [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP dengan direktori Laravel, dengan alat PHP + GH Actions +- [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP dengan direktori Laravel, dengan tooling PHP + GH Actions - [fleact](https://github.com/flightphp/fleact) - Kit starter FlightPHP dengan integrasi ReactJS. - [flastro](https://github.com/flightphp/flastro) - Kit starter FlightPHP dengan integrasi Astro. - [velt](https://github.com/flightphp/velt) - Velt adalah template starter Svelte yang cepat dan mudah dengan backend FlightPHP. @@ -16,10 +16,11 @@ Contoh yang disumbangkan oleh komunitas: Meskipun ini tidak secara resmi disponsori oleh Tim Flight, ini bisa memberi Anda ide tentang cara menyusun proyek Anda sendiri yang dibangun dengan Flight! -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental adalah aplikasi web penyewaan mobil satu halaman yang ramah seluler, dibangun dengan PHP (FlightPHP), JavaScript, dan MySQL. Ini mendukung pendaftaran pengguna, penelusuran, dan pemesanan mobil, sementara admin dapat mengelola mobil, pengguna, dan pemesanan. Aplikasi ini memiliki REST API, autentikasi JWT, dan desain responsif untuk pengalaman penyewaan modern. +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify adalah aplikasi satu halaman yang menghubungkan penyelenggara acara dengan peserta. Dibangun dengan PHP (FlightPHP), JavaScript, dan MySQL, fitur autentikasi JWT, manajemen acara, dan dokumentasi API RESTful menggunakan OpenAPI. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental adalah aplikasi web penyewaan mobil satu halaman yang ramah seluler, dibangun dengan PHP (FlightPHP), JavaScript, dan MySQL. Mendukung pendaftaran pengguna, penelusuran, dan pemesanan mobil, sementara admin dapat mengelola mobil, pengguna, dan pemesanan. Aplikasi ini memiliki API REST, autentikasi JWT, dan desain responsif untuk pengalaman penyewaan modern. - [Decay](https://github.com/boxybird/decay) - Flight v3 dengan HTMX dan SleekDB semuanya tentang zombie! ([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 dengan Middleware, Controllers, Active Record, dan Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Proyek API CRUD sederhana menggunakan framework Flight, yang menyediakan struktur dasar bagi pengguna baru untuk dengan cepat menyiapkan aplikasi PHP dengan operasi CRUD dan konektivitas database. Proyek ini mendemonstrasikan cara menggunakan Flight untuk pengembangan RESTful API, menjadikannya alat pembelajaran ideal bagi pemula dan kit starter yang berguna bagi pengembang yang lebih berpengalaman. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Proyek API CRUD sederhana menggunakan framework Flight, yang menyediakan struktur dasar bagi pengguna baru untuk dengan cepat menyiapkan aplikasi PHP dengan operasi CRUD dan konektivitas database. Proyek ini mendemonstrasikan cara menggunakan Flight untuk pengembangan API RESTful, menjadikannya alat pembelajaran ideal bagi pemula dan kit starter yang berguna bagi pengembang yang lebih berpengalaman. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -30,7 +31,7 @@ Meskipun ini tidak secara resmi disponsori oleh Tim Flight, ini bisa memberi And - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework autentikasi siap produksi yang menghemat minggu pengembangan Anda. Fitur keamanan tingkat enterprise: 2FA/TOTP, integrasi LDAP, Azure SSO, pembatasan tingkat cerdas, fingerprinting sesi, perlindungan brute-force, dasbor analitik keamanan, logging audit komprehensif, dan kontrol akses berbasis peran granular. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework autentikasi siap produksi yang menghemat waktu pengembangan berminggu-minggu. Fitur keamanan tingkat enterprise: 2FA/TOTP, integrasi LDAP, Azure SSO, pembatasan laju cerdas, sidik jari sesi, perlindungan brute-force, dasbor analitik keamanan, logging audit komprehensif, dan kontrol akses berbasis peran yang granular. ## Ingin Berbagi Contoh Anda Sendiri? diff --git a/content/v3/ja/awesome-plugins/awesome_plugins.md b/content/v3/ja/awesome-plugins/awesome_plugins.md index 7f5e73f4..ad13cc13 100644 --- a/content/v3/ja/awesome-plugins/awesome_plugins.md +++ b/content/v3/ja/awesome-plugins/awesome_plugins.md @@ -1,28 +1,28 @@ # 素晴らしいプラグイン -Flight は驚くほど拡張性が高いです。Flight アプリケーションに機能を追加するために使用できる多くのプラグインがあります。一部は Flight チームによって公式にサポートされており、他のものはスタートするためのマイクロ/ライトライブラリです。 +Flight は非常に拡張性が高いです。Flight アプリケーションに機能を追加するために使用できるプラグインがいくつかあります。一部は Flight チームによって公式にサポートされており、他のものは開始するためのマイクロ/ライトライブラリです。 ## API ドキュメント -API ドキュメントはどんな API にとっても重要です。開発者が API とどのようにやり取りするかを理解し、何を期待するかを知るのに役立ちます。Flight プロジェクトの API ドキュメントを生成するのに役立ついくつかのツールがあります。 +API ドキュメントは、あらゆる API にとって重要です。開発者が API とどのようにやり取りするかを理解し、返されるものを期待することを助けます。Flight プロジェクトの API ドキュメントを生成するのに役立つツールがいくつかあります。 -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber によるブログ記事で、OpenAPI Spec を FlightPHP と使用して API ファーストアプローチで API を構築する方法について説明しています。 -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI は、Flight プロジェクトの API ドキュメントを生成するのに役立つ優れたツールです。非常に使いやすく、ニーズに合わせてカスタマイズ可能です。これは Swagger ドキュメントを生成するための PHP ライブラリです。 +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber によるブログ投稿で、OpenAPI Spec を FlightPHP と使用して API ファーストのアプローチで API を構築する方法について説明しています。 +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI は、Flight プロジェクトの API ドキュメントを生成するのに役立つ優れたツールです。非常に使いやすく、ニーズに合わせてカスタマイズできます。これは Swagger ドキュメントを生成するための PHP ライブラリです。 -## アプリケーション パフォーマンス モニタリング (APM) +## アプリケーション パフォーマンス監視 (APM) -アプリケーション パフォーマンス モニタリング (APM) はどんなアプリケーションにとっても重要です。アプリケーションのパフォーマンスを理解し、ボトルネックの場所を特定するのに役立ちます。Flight で使用できる APM ツールがいくつかあります。 -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM は、Flight アプリケーションを監視するためのシンプルな APM ライブラリです。アプリケーションのパフォーマンスを監視し、ボトルネックを特定するのに使用できます。 +アプリケーション パフォーマンス監視 (APM) は、あらゆるアプリケーションにとって重要です。アプリケーションのパフォーマンスを理解し、ボトルネックがどこにあるかを特定するのに役立ちます。Flight で使用できる APM ツールがいくつかあります。 +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM は、Flight アプリケーションを監視するために使用できるシンプルな APM ライブラリです。アプリケーションのパフォーマンスを監視し、ボトルネックを特定するのに役立ちます。 ## 非同期 -Flight はすでに高速なフレームワークですが、それにターボエンジンを追加するとすべてがより楽しく(そして挑戦的)になります! +Flight はすでに高速なフレームワークですが、ターボエンジンを追加するとすべてがより楽しく(そして挑戦的)になります! -- [flightphp/async](/awesome-plugins/async) - 公式の Flight Async ライブラリです。このライブラリは、アプリケーションに非同期処理を追加するシンプルな方法です。Swoole/Openswoole を内部で使用して、タスクを非同期で実行するシンプルで効果的な方法を提供します。 +- [flightphp/async](/awesome-plugins/async) - 公式の Flight Async ライブラリです。このライブラリは、アプリケーションに非同期処理を追加するシンプルな方法です。Swoole/Openswoole を基盤として使用し、タスクを非同期で実行するシンプルで効果的な方法を提供します。 -## 認可/権限 +## 認証/権限 -認可と権限は、誰が何にアクセスできるかを制御する必要があるどんなアプリケーションにとっても重要です。 +認証と権限は、誰が何にアクセスできるかを制御する必要があるあらゆるアプリケーションにとって重要です。 - official [flightphp/permissions](/awesome-plugins/permissions) - 公式の Flight Permissions ライブラリです。このライブラリは、アプリケーションにユーザーおよびアプリケーション レベルの権限を追加するシンプルな方法です。 @@ -30,67 +30,68 @@ Flight はすでに高速なフレームワークですが、それにターボ キャッシュはアプリケーションを高速化する優れた方法です。Flight で使用できるキャッシュ ライブラリがいくつかあります。 -- official [flightphp/cache](/awesome-plugins/php-file-cache) - 軽量でシンプルなスタンドアローンファイル内キャッシュ PHP クラス +- official [flightphp/cache](/awesome-plugins/php-file-cache) - 軽量でシンプルなスタンドアロン PHP イン-File キャッシュ クラス ## CLI -CLI アプリケーションはアプリケーションとやり取りする優れた方法です。コントローラーの生成、すべてのルートの表示などを使用できます。 +CLI アプリケーションは、アプリケーションとやり取りする優れた方法です。コントローラーを生成したり、すべてのルートを表示したり、その他さまざまなことを行うことができます。 -- official [flightphp/runway](/awesome-plugins/runway) - Runway は Flight アプリケーションを管理するのに役立つ CLI アプリケーションです。 +- official [flightphp/runway](/awesome-plugins/runway) - Runway は、Flight アプリケーションを管理するのに役立つ CLI アプリケーションです。 ## クッキー -クッキーはクライアント側に少量のデータを保存する優れた方法です。ユーザーの好み、アプリケーション設定などを保存するために使用できます。 +クッキーは、クライアント側に少量のデータを保存する優れた方法です。ユーザー設定、アプリケーション設定などを保存するために使用できます。 -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie は、クッキーを管理するシンプルで効果的な PHP ライブラリです。 +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie は、クッキーを管理するためのシンプルで効果的な PHP ライブラリです。 ## デバッグ -デバッグはローカル環境で開発する際に重要です。デバッグ体験を向上させるいくつかのプラグインがあります。 +ローカル環境で開発する際のデバッグは重要です。デバッグ体験を向上させるプラグインがいくつかあります。 -- [tracy/tracy](/awesome-plugins/tracy) - これは Flight で使用できる完全機能のエラーハンドラーです。アプリケーションをデバッグするのに役立ついくつかのパネルがあります。また、拡張して独自のパネルを追加するのが非常に簡単です。 -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) エラーハンドラーと使用され、このプラグインは Flight プロジェクト専用のデバッグを支援するための追加パネルをいくつか追加します。 +- [tracy/tracy](/awesome-plugins/tracy) - Flight で使用できる完全機能のエラー ハンドラーです。アプリケーションのデバッグに役立つパネルがいくつかあります。また、拡張して独自のパネルを追加することも非常に簡単です。 +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) エラー ハンドラーと使用され、Flight プロジェクト専用のデバッグに役立つ追加のパネルをいくつか追加します。 ## データベース -データベースはほとんどのアプリケーションのコアです。これでデータを保存および取得します。一部のデータベース ライブラリはクエリを書くための単なるラッパーであり、一部はフル機能の ORM です。 +データベースはほとんどのアプリケーションのコアです。これによりデータを保存および取得します。一部のデータベース ライブラリはクエリを書くためのラッパーであり、他のものは完全な ORM です。 -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - コアの一部である公式の Flight PDO Wrapper です。これはクエリの記述と実行を簡素化するためのシンプルなラッパーです。ORM ではありません。 -- official [flightphp/active-record](/awesome-plugins/active-record) - 公式の Flight ActiveRecord ORM/Mapper です。データベースからデータを簡単に取得および保存するための優れた小さなライブラリです。 +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - コアの一部である公式の Flight PDO Wrapper です。クエリを書いて実行するプロセスを簡素化するためのシンプルなラッパーです。ORM ではありません。 +- official [flightphp/active-record](/awesome-plugins/active-record) - 公式の Flight ActiveRecord ORM/マッパーです。データベースからデータを簡単に取得および保存するための優れたライブラリです。 - [byjg/php-migration](/awesome-plugins/migrations) - プロジェクトのすべてのデータベース変更を追跡するためのプラグインです。 ## 暗号化 -暗号化は機密データを保存するどんなアプリケーションにとっても重要です。データの暗号化と復号化はそれほど難しくありませんが、暗号化キーの適切な保存 [は](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [です](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [難しい](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)。最も重要なのは、暗号化キーをパブリックディレクトリに保存したり、コードリポジトリにコミットしたりしないことです。 +暗号化は、機密データを保存するあらゆるアプリケーションにとって重要です。データを暗号化および復号化するのはそれほど難しくありませんが、暗号化キーを適切に保存することは [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [です](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [が](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)、難しい場合があります。最も重要なのは、暗号化キーを公開ディレクトリに保存したり、コード リポジトリにコミットしたりしないことです。 -- [defuse/php-encryption](/awesome-plugins/php-encryption) - これはデータを暗号化および復号化するためのライブラリです。データの暗号化と復号化を開始するのがかなりシンプルです。 +- [defuse/php-encryption](/awesome-plugins/php-encryption) - データを暗号化および復号化するために使用できるライブラリです。データを暗号化および復号化するのを開始するのはかなりシンプルです。 -## ジョブキュー +## ジョブ キュー -ジョブキューはタスクを非同期で処理するのに非常に役立ちます。これはメールの送信、画像の処理、またはリアルタイムで必要ない何でもです。 +ジョブ キューは、タスクを非同期で処理するのに非常に役立ちます。これはメールの送信、画像の処理、またはリアルタイムで実行する必要のないあらゆるものです。 -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue は、ジョブを非同期で処理するためのライブラリです。beanstalkd、MySQL/MariaDB、SQLite、PostgreSQL で使用できます。 +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue は、ジョブを非同期で処理するために使用できるライブラリです。beanstalkd、MySQL/MariaDB、SQLite、PostgreSQL と使用できます。 ## セッション -セッションは API にはあまり役立ちませんが、Web アプリケーションを構築する際には、状態とログイン情報を維持するために重要です。 +セッションは API にはあまり有用ではありませんが、Web アプリケーションを構築する際には、状態とログイン情報を維持するために重要です。 -- official [flightphp/session](/awesome-plugins/session) - 公式の Flight Session ライブラリです。これはセッションデータを保存および取得するためのシンプルなセッション ライブラリです。PHP の組み込みセッション処理を使用します。 -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (非ブロッキング、フラッシュ、セグメント、セッション暗号化)。セッションデータのオプションの暗号化/復号化に PHP open_ssl を使用します。 +- official [flightphp/session](/awesome-plugins/session) - 公式の Flight Session ライブラリです。セッションデータを保存および取得するために使用できるシンプルなセッション ライブラリです。PHP のビルトイン セッション ハンドリングを使用します。 +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP セッション マネージャー(非ブロッキング、フラッシュ、セグメント、セッション暗号化)。セッションデータのオプションの暗号化/復号化に PHP open_ssl を使用します。 ## テンプレート -テンプレートは UI を持つどんな Web アプリケーションにとってもコアです。Flight で使用できるテンプレートエンジンがいくつかあります。 +テンプレートは UI を備えたあらゆる Web アプリケーションのコアです。Flight で使用できるテンプレート エンジンがいくつかあります。 -- deprecated [flightphp/core View](/learn#views) - コアの一部である非常に基本的なテンプレートエンジンです。プロジェクトに数ページ以上ある場合は使用を推奨しません。 -- [latte/latte](/awesome-plugins/latte) - Latte は、Twig や Smarty よりも PHP 構文に近い、非常に使いやすいフル機能のテンプレートエンジンです。また、拡張して独自のフィルターと関数を追加するのが非常に簡単です。 +- deprecated [flightphp/core View](/learn#views) - コアの一部である非常に基本的なテンプレート エンジンです。プロジェクトに数ページ以上ある場合は使用を推奨しません。 +- [latte/latte](/awesome-plugins/latte) - Latte は、Twig や Smarty よりも PHP 構文に近い、非常に使いやすい完全機能のテンプレート エンジンです。また、拡張して独自のフィルターや関数を追加することも非常に簡単です。 +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate は、アセット コンパイル、テンプレート継承、変数処理を備えた強力な PHP テンプレート エンジンです。自動 CSS/JS 最小化、キャッシュ、Base64 エンコーディング、およびオプションの Flight PHP フレームワーク統合を特徴とします。 ## WordPress 統合 -WordPress プロジェクトで Flight を使用したいですか?そのための便利なプラグインがあります! +WordPress プロジェクトで Flight を使用したいですか? そのための便利なプラグインがあります! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - この WordPress プラグインにより、WordPress と並行して Flight を実行できます。カスタム API、マイクロサービス、または WordPress サイトに Flight フレームワークを使用してフルアプリを追加するのに最適です。両方の世界の最高を望む場合に超便利です! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - この WordPress プラグインにより、WordPress と並行して Flight を実行できます。Flight フレームワークを使用して WordPress サイトにカスタム API、マイクロサービス、または完全なアプリを追加するのに最適です。両方の世界の最高のものを手に入れたい場合に超便利です! ## 貢献 -共有したいプラグインがありますか?リストに追加するためのプルリクエストを送信してください! \ No newline at end of file +共有したいプラグインがありますか? リストに追加するためのプルリクエストを送信してください! \ No newline at end of file diff --git a/content/v3/ja/awesome-plugins/comment_template.md b/content/v3/ja/awesome-plugins/comment_template.md new file mode 100644 index 00000000..710e6808 --- /dev/null +++ b/content/v3/ja/awesome-plugins/comment_template.md @@ -0,0 +1,258 @@ +# CommentTemplate + +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) は、強力な PHP テンプレートエンジンで、アセットのコンパイル、テンプレートの継承、変数の処理を備えています。組み込みの CSS/JS 最小化とキャッシュにより、シンプルで柔軟なテンプレート管理を提供します。 + +## 機能 + +- **テンプレートの継承**: レイアウトを使用し、他のテンプレートを含める +- **アセットのコンパイル**: CSS/JS の自動最小化とキャッシュ +- **変数の処理**: フィルターとコマンド付きのテンプレート変数 +- **Base64 エンコーディング**: アセットをデータ URI としてインライン化 +- **Flight Framework 統合**: Flight PHP フレームワークとのオプションの統合 + +## インストール + +Composer を使用してインストールします。 + +```bash +composer require knifelemon/comment-template +``` + +## 基本設定 + +開始するための基本的な設定オプションがあります。これらについての詳細は [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate) を参照してください。 + +### 方法 1: コールバック関数を使用 + +```php +register('view', Engine::class, [], function (Engine $engine) use ($app) { + // テンプレートファイルが保存される場所 + $engine->setTemplatesPath(__DIR__ . '/views'); + + // パブリックアセットが提供される場所 + $engine->setPublicPath(__DIR__ . '/public'); + + // コンパイルされたアセットが保存される場所 + $engine->setAssetPath('assets'); + + // テンプレートファイルの拡張子 + $engine->setFileExtension('.php'); +}); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +### 方法 2: コンストラクタパラメータを使用 + +```php +register('view', Engine::class, [ + __DIR__ . '/public', // publicPath - アセットが提供される場所 + __DIR__ . '/views', // skinPath - テンプレートファイルが保存される場所 + 'assets', // assetPath - コンパイルされたアセットが保存される場所 + '.php' // fileExtension - テンプレートファイルの拡張子 +]); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +## テンプレートディレクティブ + +### レイアウトの継承 + +共通の構造を作成するためにレイアウトを使用します: + +**layout/global_layout.php**: +```html + + + + {$title} + + + + + +``` + +**view/page.php**: +```html + +

{$title}

+

{$content}

+``` + +### アセット管理 + +#### CSS ファイル +```html + + +``` + +#### JavaScript ファイル +CommentTemplate は異なる JavaScript 読み込み戦略をサポートします: + +```html + + + + + + + + + +``` + +#### CSS/JS ファイル内のアセットディレクティブ + +CommentTemplate はコンパイル中に CSS と JavaScript ファイル内のアセットディレクティブも処理します: + +**CSS の例:** +```css +/* CSS ファイル内 */ +/* フォントファイル */ +@font-face { + font-family: 'CustomFont'; + src: url('') format('woff2'); +} + +.background-image { + background: url(''); +} + +.inline-icon { + background: url(''); +} +``` + +**JavaScript の例:** +```javascript +/* JS ファイル内 */ +const fontUrl = ''; +const imageData = ''; +``` + +#### Base64 エンコーディング +```html + +``` +**例:** +```html + +Logo +
+ 背景としての小さなアイコン +
+``` + +#### アセットのコピー +```html + + +``` +**例:** +```html + +Hero Banner +パンフレットダウンロード + + + + +``` + +### テンプレートのインクルード +```html + +``` +**例:** +```html + + + +
+

ウェブサイトへようこそ

+ + +
+

メインコンテンツはここ...

+
+
+ + +``` + +### 変数の処理 + +#### 基本変数 +```html +

{$title}

+

{$description}

+``` + +#### 変数フィルター +```html +{$title|upper} +{$content|lower} +{$html|striptag} +{$text|escape} +{$multiline|nl2br} +{$html|br2nl} +{$description|trim} +{$subject|title} +``` + +#### 変数コマンド +```html +{$title|default=Default Title} +{$name|concat= (Admin)} +``` + +#### 変数コマンド +```html +{$content|striptag|trim|escape} +``` + +## 例のプロジェクト構造 + +``` +project/ +├── source/ +│ ├── layouts/ +│ │ └── default.php +│ ├── components/ +│ │ ├── header.php +│ │ └── footer.php +│ ├── css/ +│ │ ├── bootstrap.min.css +│ │ └── custom.css +│ ├── js/ +│ │ ├── app.js +│ │ └── bootstrap.min.js +│ └── homepage.php +├── public/ +│ └── assets/ # 生成されたアセット +│ ├── css/ +│ └── js/ +└── vendor/ +``` \ No newline at end of file diff --git a/content/v3/ja/examples.md b/content/v3/ja/examples.md index ab24d88c..881ab74e 100644 --- a/content/v3/ja/examples.md +++ b/content/v3/ja/examples.md @@ -2,24 +2,25 @@ 新しい Flight プロジェクトを始めるために、2つのオプションがあります: -- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): コントローラーとビューを含む、より完全な例。 -- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): アプリを単一のシンプルなファイルで実行するために必要なすべてを含む単一のファイル。 +- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): コントローラーとビューを含む、より充実した例。 +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): アプリを単一のシンプルなファイルで実行するために必要なすべてを含む単一ファイル。 コミュニティ提供の例: - [flightravel](https://github.com/fadrian06-templates/flighravel): Laravel ディレクトリ付きの FlightPHP、PHP ツール + GH Actions -- [fleact](https://github.com/flightphp/fleact) - ReactJS 統合付きの FlightPHP スターターキット。 -- [flastro](https://github.com/flightphp/flastro) - Astro 統合付きの FlightPHP スターターキット。 -- [velt](https://github.com/flightphp/velt) - Velt は、FlightPHP バックエンド付きのクイックで簡単な Svelte スターターテンプレートです。 +- [fleact](https://github.com/flightphp/fleact) - ReactJS 統合の FlightPHP スターターキット。 +- [flastro](https://github.com/flightphp/flastro) - Astro 統合の FlightPHP スターターキット。 +- [velt](https://github.com/flightphp/velt) - Velt は FlightPHP バックエンド付きの Svelte スターターテンプレートで、クイックで簡単です。 ## インスピレーションが必要ですか? -これらは Flight チームの公式スポンサーではありませんが、Flight で構築した独自のプロジェクトの構造についてのアイデアを提供する可能性があります! +これらは Flight チームの公式スポンサーではありませんが、Flight で構築した自分のプロジェクトの構造についてのアイデアを提供する可能性があります! -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental は、PHP (FlightPHP)、JavaScript、MySQL で構築されたシングルページのモバイルフレンドリーなカーレンタルウェブアプリケーションです。ユーザー登録、閲覧、車の予約をサポートし、管理者は車、ユーザー、予約を管理できます。アプリには REST API、JWT 認証、モダンなレンタル体験のためのレスポンシブデザインが備わっています。 -- [Decay](https://github.com/boxybird/decay) - ゾンビについての HTMX と SleekDB 付きの Flight v3! ([Demo](https://decay.andrewrhyand.com)) +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify はイベント主催者と参加者を結ぶシングルページアプリです。PHP (FlightPHP)、JavaScript、MySQL で構築され、JWT 認証、イベント管理、OpenAPI を使用した RESTful API ドキュメントを備えています。 +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental は PHP (FlightPHP)、JavaScript、MySQL で構築されたシングルページのモバイルフレンドリーなカーレンタルウェブアプリケーションです。ユーザー登録、閲覧、車の予約をサポートし、管理者は車、ユーザー、予約を管理できます。アプリには REST API、JWT 認証、モダンなレンタル体験のためのレスポンシブデザインが備わっています。 +- [Decay](https://github.com/boxybird/decay) - ゾンビに関する HTMX と SleekDB 付きの Flight v3!([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - ミドルウェア、コントローラー、Active Record、Latte 付きの Flight v3。 -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Flight フレームワークを使用したシンプルな CRUD API プロジェクトで、新しいユーザーが CRUD 操作とデータベース接続付きの PHP アプリケーションを迅速にセットアップするための基本構造を提供します。このプロジェクトは、RESTful API 開発のための Flight の使用方法を示し、初心者向けの学習ツールおよび経験豊富な開発者向けの便利なスターターキットとして理想的です。 +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Flight フレームワークを使用したシンプルな CRUD API プロジェクトで、新しいユーザーが CRUD 操作とデータベース接続付きの PHP アプリケーションを迅速にセットアップするための基本構造を提供します。このプロジェクトは RESTful API 開発のための Flight の使用方法を示し、初心者向けの学習ツールおよびより経験豊富な開発者向けの便利なスターターキットとして理想的です。 - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -30,7 +31,7 @@ - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 開発を数週間短縮する本番環境対応の認証フレームワーク。エンタープライズグレードのセキュリティ機能:2FA/TOTP、LDAP 統合、Azure SSO、インテリジェントなレート制限、セッションフィンガープリンティング、ブルートフォース保護、セキュリティ分析ダッシュボード、包括的な監査ログ、グラニュラーなロールベースアクセス制御。 +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 数週間の開発時間を節約する本番環境対応の認証フレームワーク。エンタープライズグレードのセキュリティ機能:2FA/TOTP、LDAP 統合、Azure SSO、インテリジェントなレート制限、セッション指紋認証、ブルートフォース保護、セキュリティ分析ダッシュボード、包括的な監査ログ、グラニュラーなロールベースアクセス制御。 ## 自分の例を共有したいですか? diff --git a/content/v3/ko/awesome-plugins/awesome_plugins.md b/content/v3/ko/awesome-plugins/awesome_plugins.md index 0eddf635..9505da10 100644 --- a/content/v3/ko/awesome-plugins/awesome_plugins.md +++ b/content/v3/ko/awesome-plugins/awesome_plugins.md @@ -1,42 +1,42 @@ # 멋진 플러그인 -Flight는 놀라울 정도로 확장 가능합니다. Flight 애플리케이션에 기능을 추가하는 데 사용할 수 있는 여러 플러그인이 있습니다. 일부는 Flight 팀에서 공식적으로 지원하며, 다른 일부는 시작하는 데 도움을 주기 위한 마이크로/라이트 라이브러리입니다. +Flight는 놀라울 정도로 확장 가능합니다. Flight 애플리케이션에 기능을 추가하는 데 사용할 수 있는 여러 플러그인이 있습니다. 일부는 Flight 팀에서 공식적으로 지원하며, 다른 일부는 시작하는 데 도움이 되는 마이크로/라이트 라이브러리입니다. ## API 문서화 -API 문서화는 모든 API에 필수적입니다. 개발자들이 API와 상호 작용하는 방법을 이해하고 반환되는 것을 예상할 수 있도록 도와줍니다. Flight 프로젝트를 위한 API 문서화를 생성하는 데 도움을 주는 몇 가지 도구가 있습니다. +API 문서화는 모든 API에 필수적입니다. 개발자들이 API와 상호 작용하는 방법을 이해하고 반환되는 것을 기대할 수 있도록 도와줍니다. Flight 프로젝트를 위한 API 문서화를 생성하는 데 도움이 되는 몇 가지 도구가 있습니다. - [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber가 작성한 블로그 포스트로, OpenAPI 사양을 FlightPHP와 함께 사용하여 API 우선 접근 방식을 통해 API를 구축하는 방법에 대해 설명합니다. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI는 Flight 프로젝트를 위한 API 문서화를 생성하는 데 도움이 되는 훌륭한 도구입니다. 사용하기 매우 쉽고 필요에 맞게 사용자 지정할 수 있습니다. 이는 Swagger 문서화를 생성하는 데 도움을 주는 PHP 라이브러리입니다. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI는 Flight 프로젝트를 위한 API 문서화를 생성하는 데 훌륭한 도구입니다. 사용하기 매우 쉽고 필요에 맞게 사용자 지정할 수 있습니다. 이는 Swagger 문서화를 생성하는 데 도움이 되는 PHP 라이브러리입니다. ## 애플리케이션 성능 모니터링 (APM) -애플리케이션 성능 모니터링 (APM)은 모든 애플리케이션에 필수적입니다. 애플리케이션이 어떻게 작동하는지 이해하고 병목 현상이 어디에 있는지 파악하는 데 도움을 줍니다. Flight와 함께 사용할 수 있는 여러 APM 도구가 있습니다. -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM은 Flight 애플리케이션을 모니터링하는 데 사용할 수 있는 간단한 APM 라이브러리입니다. 애플리케이션의 성능을 모니터링하고 병목 현상을 식별하는 데 도움을 줄 수 있습니다. +애플리케이션 성능 모니터링 (APM)은 모든 애플리케이션에 필수적입니다. 애플리케이션이 어떻게 작동하는지 이해하고 병목 현상이 어디에 있는지 파악하는 데 도움이 됩니다. Flight와 함께 사용할 수 있는 여러 APM 도구가 있습니다. +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM은 Flight 애플리케이션을 모니터링하는 데 사용할 수 있는 간단한 APM 라이브러리입니다. 애플리케이션의 성능을 모니터링하고 병목 현상을 식별하는 데 도움이 됩니다. -## Async +## 비동기 -Flight는 이미 빠른 프레임워크이지만, 터보 엔진을 장착하면 모든 것이 더 재미있고 (도전적) 됩니다! +Flight는 이미 빠른 프레임워크이지만, 터보 엔진을 장착하면 모든 것이 더 재미있고 (그리고 도전적) 됩니다! -- [flightphp/async](/awesome-plugins/async) - 공식 Flight Async 라이브러리입니다. 이 라이브러리는 애플리케이션에 비동기 처리를 추가하는 간단한 방법입니다. Swoole/Openswoole을 내부적으로 사용하여 작업을 비동기적으로 실행하는 간단하고 효과적인 방법을 제공합니다. +- [flightphp/async](/awesome-plugins/async) - 공식 Flight Async 라이브러리. 이 라이브러리는 애플리케이션에 비동기 처리를 추가하는 간단한 방법입니다. Swoole/Openswoole을 내부적으로 사용하여 작업을 비동기적으로 실행하는 간단하고 효과적인 방법을 제공합니다. ## 권한 부여/권한 권한 부여와 권한은 누가 무엇에 접근할 수 있는지에 대한 제어가 필요한 모든 애플리케이션에 필수적입니다. -- official [flightphp/permissions](/awesome-plugins/permissions) - 공식 Flight Permissions 라이브러리입니다. 이 라이브러리는 애플리케이션에 사용자 및 애플리케이션 수준의 권한을 추가하는 간단한 방법입니다. +- official [flightphp/permissions](/awesome-plugins/permissions) - 공식 Flight Permissions 라이브러리. 이 라이브러리는 애플리케이션에 사용자 및 애플리케이션 수준의 권한을 추가하는 간단한 방법입니다. ## 캐싱 캐싱은 애플리케이션을 가속화하는 훌륭한 방법입니다. Flight와 함께 사용할 수 있는 여러 캐싱 라이브러리가 있습니다. -- official [flightphp/cache](/awesome-plugins/php-file-cache) - 가볍고 간단하며 독립적인 PHP 인파일 캐싱 클래스 +- official [flightphp/cache](/awesome-plugins/php-file-cache) - 가볍고 간단하며 독립적인 PHP 파일 내 캐싱 클래스 ## CLI CLI 애플리케이션은 애플리케이션과 상호 작용하는 훌륭한 방법입니다. 컨트롤러 생성, 모든 경로 표시 등에 사용할 수 있습니다. -- official [flightphp/runway](/awesome-plugins/runway) - Runway는 Flight 애플리케이션을 관리하는 데 도움을 주는 CLI 애플리케이션입니다. +- official [flightphp/runway](/awesome-plugins/runway) - Runway는 Flight 애플리케이션을 관리하는 데 도움이 되는 CLI 애플리케이션입니다. ## 쿠키 @@ -48,48 +48,49 @@ CLI 애플리케이션은 애플리케이션과 상호 작용하는 훌륭한 로컬 환경에서 개발할 때 디버깅은 필수적입니다. 디버깅 경험을 향상시킬 수 있는 몇 가지 플러그인이 있습니다. -- [tracy/tracy](/awesome-plugins/tracy) - Flight와 함께 사용할 수 있는 완전한 기능을 갖춘 오류 처리기입니다. 애플리케이션을 디버깅하는 데 도움을 주는 여러 패널을 가지고 있습니다. 확장하기도 매우 쉽고 자체 패널을 추가할 수도 있습니다. -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) 오류 처리기와 함께 사용되며, Flight 프로젝트를 위한 디버깅을 도와주는 몇 가지 추가 패널을 추가하는 플러그인입니다. +- [tracy/tracy](/awesome-plugins/tracy) - Flight와 함께 사용할 수 있는 완전한 기능을 갖춘 오류 핸들러입니다. 애플리케이션을 디버깅하는 데 도움이 되는 여러 패널을 가지고 있습니다. 확장하고 자체 패널을 추가하기도 매우 쉽습니다. +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) 오류 핸들러와 함께 사용되며, 이 플러그인은 Flight 프로젝트를 위한 디버깅을 돕기 위해 몇 가지 추가 패널을 추가합니다. ## 데이터베이스 -데이터베이스는 대부분의 애플리케이션의 핵심입니다. 데이터를 저장하고 검색하는 방법입니다. 일부 데이터베이스 라이브러리는 쿼리를 작성하는 단순한 래퍼이고, 일부는 완전한 ORM입니다. +데이터베이스는 대부분의 애플리케이션의 핵심입니다. 데이터를 저장하고 검색하는 방법입니다. 일부 데이터베이스 라이브러리는 쿼리를 작성하는 단순한 래퍼이고, 일부는 완전한 ORMs입니다. -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 코어의 일부인 공식 Flight PDO Wrapper입니다. 쿼리를 작성하고 실행하는 과정을 단순화하는 데 도움을 주는 간단한 래퍼입니다. ORM이 아닙니다. -- official [flightphp/active-record](/awesome-plugins/active-record) - 공식 Flight ActiveRecord ORM/Mapper입니다. 데이터베이스에서 데이터를 쉽게 검색하고 저장하는 훌륭한 작은 라이브러리입니다. -- [byjg/php-migration](/awesome-plugins/migrations) - 프로젝트의 모든 데이터베이스 변경 사항을 추적하는 플러그인입니다. +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 핵심의 일부인 공식 Flight PDO Wrapper. 쿼리를 작성하고 실행하는 과정을 단순화하는 데 도움이 되는 간단한 래퍼입니다. ORM이 아닙니다. +- official [flightphp/active-record](/awesome-plugins/active-record) - 공식 Flight ActiveRecord ORM/Mapper. 데이터베이스에서 데이터를 쉽게 검색하고 저장하는 훌륭한 작은 라이브러리입니다. +- [byjg/php-migration](/awesome-plugins/migrations) - 프로젝트의 모든 데이터베이스 변경 사항을 추적하는 플러그인. ## 암호화 -암호화는 민감한 데이터를 저장하는 모든 애플리케이션에 필수적입니다. 데이터를 암호화하고 복호화하는 것은 그리 어렵지 않지만, 암호화 키를 적절히 저장하는 것은 [어렵습니다](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [수](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [있습니다](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). 가장 중요한 것은 암호화 키를 공개 디렉토리에 저장하지 않거나 코드 저장소에 커밋하지 않는 것입니다. +암호화는 민감한 데이터를 저장하는 모든 애플리케이션에 필수적입니다. 데이터를 암호화하고 복호화하는 것은 그리 어렵지 않지만, 암호화 키를 적절히 저장하는 [것](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [은](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [어렵습니다](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). 가장 중요한 것은 암호화 키를 공개 디렉토리에 저장하지 않거나 코드 저장소에 커밋하지 않는 것입니다. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - 데이터를 암호화하고 복호화하는 데 사용할 수 있는 라이브러리입니다. 데이터를 암호화하고 복호화하기 시작하는 것은 상당히 간단합니다. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - 데이터를 암호화하고 복호화하는 데 사용할 수 있는 라이브러리입니다. 데이터를 암호화하고 복호화하는 데 시작하기 위해 설정하는 것은 상당히 간단합니다. ## 작업 큐 -작업 큐는 작업을 비동기적으로 처리하는 데 매우 도움이 됩니다. 이메일 보내기, 이미지 처리 또는 실시간으로 수행할 필요가 없는 모든 작업에 사용할 수 있습니다. +작업 큐는 작업을 비동기적으로 처리하는 데 매우 유용합니다. 이메일 보내기, 이미지 처리 또는 실시간으로 수행할 필요가 없는 모든 작업에 사용할 수 있습니다. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue는 작업을 비동기적으로 처리하는 데 사용할 수 있는 라이브러리입니다. beanstalkd, MySQL/MariaDB, SQLite, PostgreSQL과 함께 사용할 수 있습니다. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue는 작업을 비동기적으로 처리하는 데 사용할 수 있는 라이브러리입니다. beanstalkd, MySQL/MariaDB, SQLite 및 PostgreSQL과 함께 사용할 수 있습니다. ## 세션 -세션은 API에는 정말 유용하지 않지만, 웹 애플리케이션을 구축할 때 상태와 로그인 정보를 유지하는 데 필수적일 수 있습니다. +세션은 API에는 정말 유용하지 않지만, 웹 애플리케이션을 구축할 때 상태와 로그인 정보를 유지하는 데 세션이 필수적일 수 있습니다. -- official [flightphp/session](/awesome-plugins/session) - 공식 Flight Session 라이브러리입니다. 세션 데이터를 저장하고 검색하는 데 사용할 수 있는 간단한 세션 라이브러리입니다. PHP의 내장 세션 처리를 사용합니다. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (비동기식, 플래시, 세그먼트, 세션 암호화). 세션 데이터의 선택적 암호화/복호화를 위해 PHP open_ssl을 사용합니다. +- official [flightphp/session](/awesome-plugins/session) - 공식 Flight Session 라이브러리. 세션 데이터를 저장하고 검색하는 데 사용할 수 있는 간단한 세션 라이브러리입니다. PHP의 내장 세션 처리를 사용합니다. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 세션 관리자 (비차단, 플래시, 세그먼트, 세션 암호화). 세션 데이터의 선택적 암호화/복호화를 위해 PHP open_ssl을 사용합니다. ## 템플릿 템플릿은 UI가 있는 모든 웹 애플리케이션의 핵심입니다. Flight와 함께 사용할 수 있는 여러 템플릿 엔진이 있습니다. -- deprecated [flightphp/core View](/learn#views) - 코어의 일부인 매우 기본적인 템플릿 엔진입니다. 프로젝트에 몇 페이지 이상이 있다면 사용하지 않는 것이 좋습니다. -- [latte/latte](/awesome-plugins/latte) - Latte는 사용하기 매우 쉽고 Twig나 Smarty보다 PHP 구문에 더 가까운 느낌의 완전한 기능을 갖춘 템플릿 엔진입니다. 확장하기도 매우 쉽고 자체 필터와 함수를 추가할 수도 있습니다. +- deprecated [flightphp/core View](/learn#views) - 핵심의 일부인 매우 기본적인 템플릿 엔진입니다. 프로젝트에 몇 페이지 이상이 있다면 사용하지 않는 것이 좋습니다. +- [latte/latte](/awesome-plugins/latte) - Latte는 사용하기 매우 쉽고 Twig나 Smarty보다 PHP 구문에 더 가까운 느낌의 완전한 기능을 갖춘 템플릿 엔진입니다. 확장하고 자체 필터와 함수를 추가하기도 매우 쉽습니다. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate는 자산 컴파일, 템플릿 상속 및 변수 처리를 갖춘 강력한 PHP 템플릿 엔진입니다. 자동 CSS/JS 최소화, 캐싱, Base64 인코딩 및 선택적 Flight PHP 프레임워크 통합 기능을 제공합니다. ## WordPress 통합 WordPress 프로젝트에서 Flight를 사용하고 싶으신가요? 이를 위한 편리한 플러그인이 있습니다! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 이 WordPress 플러그인은 Flight를 WordPress와 함께 실행할 수 있게 합니다. WordPress 사이트에 사용자 지정 API, 마이크로서비스 또는 전체 앱을 Flight 프레임워크를 사용하여 추가하는 데 완벽합니다. 두 세계의 장점을 모두 누리고 싶다면 매우 유용합니다! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 이 WordPress 플러그인은 WordPress와 함께 Flight를 실행할 수 있게 합니다. WordPress 사이트에 Flight 프레임워크를 사용하여 사용자 지정 API, 마이크로서비스 또는 전체 앱을 추가하는 데 완벽합니다. 두 세계의 장점을 모두 누리고 싶다면 매우 유용합니다! ## 기여 diff --git a/content/v3/ko/awesome-plugins/comment_template.md b/content/v3/ko/awesome-plugins/comment_template.md new file mode 100644 index 00000000..7a555178 --- /dev/null +++ b/content/v3/ko/awesome-plugins/comment_template.md @@ -0,0 +1,257 @@ +# CommentTemplate + +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate)은 자산 컴파일, 템플릿 상속, 변수 처리 기능을 갖춘 강력한 PHP 템플릿 엔진입니다. 내장된 CSS/JS 압축 및 캐싱으로 템플릿을 간단하면서도 유연하게 관리할 수 있습니다. + +## 기능 + +- **템플릿 상속**: 레이아웃 사용 및 다른 템플릿 포함 +- **자산 컴파일**: 자동 CSS/JS 압축 및 캐싱 +- **변수 처리**: 필터와 명령어를 사용한 템플릿 변수 +- **Base64 인코딩**: 데이터 URI로 인라인 자산 +- **Flight 프레임워크 통합**: Flight PHP 프레임워크와의 선택적 통합 + +## 설치 + +Composer를 사용하여 설치하세요. + +```bash +composer require knifelemon/comment-template +``` + +## 기본 구성 + +시작하기 위한 기본 구성 옵션이 있습니다. 이에 대해 자세한 내용은 [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate)를 참조하세요. + +### 방법 1: 콜백 함수 사용 + +```php +register('view', Engine::class, [], function (Engine $engine) use ($app) { + // 템플릿 파일이 저장된 위치 + $engine->setTemplatesPath(__DIR__ . '/views'); + + // 공용 자산이 제공되는 위치 + $engine->setPublicPath(__DIR__ . '/public'); + + // 컴파일된 자산이 저장되는 위치 + $engine->setAssetPath('assets'); + + // 템플릿 파일 확장자 + $engine->setFileExtension('.php'); +}); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +### 방법 2: 생성자 매개변수 사용 + +```php +register('view', Engine::class, [ + __DIR__ . '/public', // publicPath - 자산이 제공되는 위치 + __DIR__ . '/views', // skinPath - 템플릿 파일이 저장된 위치 + 'assets', // assetPath - 컴파일된 자산이 저장되는 위치 + '.php' // fileExtension - 템플릿 파일 확장자 +]); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +## 템플릿 지시어 + +### 레이아웃 상속 + +공통 구조를 생성하기 위해 레이아웃을 사용하세요: + +**layout/global_layout.php**: +```html + + + + {$title} + + + + + +``` + +**view/page.php**: +```html + +

{$title}

+

{$content}

+``` + +### 자산 관리 + +#### CSS 파일 +```html + + +``` + +#### JavaScript 파일 +CommentTemplate은 다양한 JavaScript 로딩 전략을 지원합니다: + +```html + + + + + + + + + +``` + +#### CSS/JS 파일 내 자산 지시어 + +CommentTemplate은 컴파일 중 CSS 및 JavaScript 파일 내 자산 지시어를 처리합니다: + +**CSS 예시:** +```css +/* CSS 파일 내 */ +/* @font-face { + font-family: 'CustomFont'; + src: url('') format('woff2'); +} + +.background-image { + background: url(''); +} + +.inline-icon { + background: url(''); +} +``` + +**JavaScript 예시:** +```javascript +/* JS 파일 내 */ +const fontUrl = ''; +const imageData = ''; +``` + +#### Base64 인코딩 +```html + +``` +** 예시: ** +```html + +Logo +
+ 배경으로 작은 아이콘 +
+``` + +#### 자산 복사 +```html + + +``` +** 예시: ** +```html + +Hero Banner +브로슈어 다운로드 + + + + +``` + +### 템플릿 포함 +```html + +``` +** 예시: ** +```html + + + +
+

웹사이트에 오신 것을 환영합니다

+ + +
+

메인 콘텐츠가 여기에...

+
+
+ + +``` + +### 변수 처리 + +#### 기본 변수 +```html +

{$title}

+

{$description}

+``` + +#### 변수 필터 +```html +{$title|upper} +{$content|lower} +{$html|striptag} +{$text|escape} +{$multiline|nl2br} +{$html|br2nl} +{$description|trim} +{$subject|title} +``` + +#### 변수 명령어 +```html +{$title|default=Default Title} +{$name|concat= (Admin)} +``` + +#### 변수 명령어 +```html +{$content|striptag|trim|escape} +``` + +## 예시 프로젝트 구조 + +``` +project/ +├── source/ +│ ├── layouts/ +│ │ └── default.php +│ ├── components/ +│ │ ├── header.php +│ │ └── footer.php +│ ├── css/ +│ │ ├── bootstrap.min.css +│ │ └── custom.css +│ ├── js/ +│ │ ├── app.js +│ │ └── bootstrap.min.js +│ └── homepage.php +├── public/ +│ └── assets/ # 생성된 자산 +│ ├── css/ +│ └── js/ +└── vendor/ +``` \ No newline at end of file diff --git a/content/v3/ko/examples.md b/content/v3/ko/examples.md index ae078101..861b6eb1 100644 --- a/content/v3/ko/examples.md +++ b/content/v3/ko/examples.md @@ -3,23 +3,24 @@ 새로운 Flight 프로젝트를 시작하는 데 두 가지 옵션이 있습니다: - [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): 컨트롤러와 뷰가 포함된 더 완전한 예제입니다. -- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): 앱을 단일 간단한 파일에서 실행하는 데 필요한 모든 것을 포함한 단일 파일입니다. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): 앱을 단일 간단한 파일로 실행하는 데 필요한 모든 것을 포함한 단일 파일입니다. -커뮤니티 기여 예제: +커뮤니티가 기여한 예제: -- [flightravel](https://github.com/fadrian06-templates/flighravel): Laravel 디렉토리와 PHP 도구 + GH Actions를 사용한 FlightPHP -- [fleact](https://github.com/flightphp/fleact) - ReactJS 통합을 포함한 FlightPHP 스타터 키트. -- [flastro](https://github.com/flightphp/flastro) - Astro 통합을 포함한 FlightPHP 스타터 키트. -- [velt](https://github.com/flightphp/velt) - FlightPHP 백엔드를 사용한 빠르고 쉬운 Svelte 스타터 템플릿인 Velt입니다. +- [flightravel](https://github.com/fadrian06-templates/flighravel): Laravel 디렉토리와 PHP 도구 + GH Actions를 사용한 FlightPHP입니다. +- [fleact](https://github.com/flightphp/fleact) - ReactJS 통합을 포함한 FlightPHP 스타터 키트입니다. +- [flastro](https://github.com/flightphp/flastro) - Astro 통합을 포함한 FlightPHP 스타터 키트입니다. +- [velt](https://github.com/flightphp/velt) - Velt는 FlightPHP 백엔드를 사용하는 빠르고 쉬운 Svelte 스타터 템플릿입니다. ## 영감을 얻고 싶으신가요? -이것들은 Flight 팀의 공식 후원이 아니지만, Flight로 구축된 자신의 프로젝트를 구조화하는 데 아이디어를 줄 수 있습니다! +이것들은 Flight 팀에서 공식적으로 후원하지 않지만, Flight로 구축된 자신의 프로젝트를 구조화하는 데 아이디어를 줄 수 있습니다! -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental은 PHP (FlightPHP), JavaScript, MySQL로 구축된 단일 페이지, 모바일 친화적인 자동차 대여 웹 애플리케이션입니다. 사용자 등록, 차량 검색 및 예약을 지원하며, 관리자는 차량, 사용자 및 예약을 관리할 수 있습니다. 앱에는 REST API, JWT 인증 및 현대적인 대여 경험을 위한 반응형 디자인이 포함되어 있습니다. -- [Decay](https://github.com/boxybird/decay) - 좀비에 관한 HTMX와 SleekDB를 사용한 Flight v3! ([Demo](https://decay.andrewrhyand.com)) -- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - 미들웨어, 컨트롤러, Active Record 및 Latte를 사용한 Flight v3. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Flight 프레임워크를 사용한 간단한 CRUD API 프로젝트로, CRUD 작업과 데이터베이스 연결이 포함된 PHP 애플리케이션을 신속하게 설정할 수 있는 기본 구조를 제공합니다. 이 프로젝트는 RESTful API 개발을 위한 Flight 사용 방법을 보여주며, 초보자에게 이상적인 학습 도구이자 경험이 풍부한 개발자에게 유용한 스타터 키트입니다. +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify는 이벤트 주최자와 참석자를 연결하는 단일 페이지 앱입니다. PHP (FlightPHP), JavaScript, MySQL로 구축되었으며, JWT 인증, 이벤트 관리, OpenAPI를 사용한 RESTful API 문서를 특징으로 합니다. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental은 PHP (FlightPHP), JavaScript, MySQL로 구축된 단일 페이지, 모바일 친화적인 자동차 대여 웹 애플리케이션입니다. 사용자 등록, 차량 검색, 예약을 지원하며, 관리자는 차량, 사용자, 예약을 관리할 수 있습니다. 앱은 REST API, JWT 인증, 현대적인 대여 경험을 위한 반응형 디자인을 특징으로 합니다. +- [Decay](https://github.com/boxybird/decay) - 좀비에 관한 Flight v3, HTMX 및 SleekDB! ([Demo](https://decay.andrewrhyand.com)) +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - 미들웨어, 컨트롤러, Active Record, Latte를 사용한 Flight v3. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Flight 프레임워크를 사용한 간단한 CRUD API 프로젝트로, 새로운 사용자가 CRUD 작업과 데이터베이스 연결을 포함한 PHP 애플리케이션을 빠르게 설정할 수 있는 기본 구조를 제공합니다. 프로젝트는 RESTful API 개발을 위한 Flight 사용 방법을 보여주며, 초보자에게 이상적인 학습 도구이자 경험이 많은 개발자에게 유용한 스타터 키트입니다. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -30,8 +31,8 @@ - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 개발 주를 절약해주는 프로덕션 준비 인증 프레임워크. 기업급 보안 기능: 2FA/TOTP, LDAP 통합, Azure SSO, 지능형 속도 제한, 세션 지문 인식, 무차별 대입 공격 보호, 보안 분석 대시보드, 포괄적인 감사 로깅 및 세밀한 역할 기반 액세스 제어. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 개발 주를 절약해주는 프로덕션 준비 인증 프레임워크입니다. 엔터프라이즈급 보안 기능: 2FA/TOTP, LDAP 통합, Azure SSO, 지능형 속도 제한, 세션 지문 인식, 무차별 대입 공격 보호, 보안 분석 대시보드, 포괄적인 감사 로깅, 세분화된 역할 기반 액세스 제어. ## 자신의 예제를 공유하고 싶으신가요? -공유하고 싶은 프로젝트가 있다면, 이 목록에 추가하기 위해 풀 리퀘스트를 제출해주세요! \ No newline at end of file +공유하고 싶은 프로젝트가 있으시면, 이 목록에 추가하기 위해 풀 리퀘스트를 제출해 주세요! \ No newline at end of file diff --git a/content/v3/lv/awesome-plugins/awesome_plugins.md b/content/v3/lv/awesome-plugins/awesome_plugins.md index 2ad5d078..3eddbbd7 100644 --- a/content/v3/lv/awesome-plugins/awesome_plugins.md +++ b/content/v3/lv/awesome-plugins/awesome_plugins.md @@ -1,59 +1,59 @@ # Lieliski spraudņi -Flight ir neticami paplašināms. Ir vairāki spraudņi, ko var izmantot, lai pievienotu funkcionalitāti jūsu Flight aplikācijai. Daži no tiem oficiāli atbalsta Flight komanda, bet citi ir mikro/lite bibliotēkas, lai palīdzētu jums sākt. +Flight ir neticami paplašināms. Ir vairāki spraudņi, ko var izmantot, lai pievienotu funkcionalitāti jūsu Flight lietojumprogrammai. Daži no tiem oficiāli atbalsta Flight Team, bet citi ir mikro/lite bibliotēkas, lai palīdzētu jums sākt. ## API dokumentācija -API dokumentācija ir izšķiroša jebkurai API. Tā palīdz izstrādātājiem saprast, kā mijiedarboties ar jūsu API un ko sagaidīt pretī. Ir pieejami vairāki rīki, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. +API dokumentācija ir izšķiroša jebkuram API. Tā palīdz izstrādātājiem saprast, kā mijiedarboties ar jūsu API un ko sagaidīt pretī. Ir pieejami vairāki rīki, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. - [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Bloga ieraksts, ko uzrakstījis Daniels Šreibers, par to, kā izmantot OpenAPI specifikāciju ar FlightPHP, lai izveidotu jūsu API, izmantojot API pirmo pieeju. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ir lielisks rīks, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. To ir ļoti viegli izmantot un to var pielāgot jūsu vajadzībām. Šī ir PHP bibliotēka, lai palīdzētu ģenerēt Swagger dokumentāciju. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ir lielisks rīks, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. To ir ļoti viegli izmantot, un to var pielāgot jūsu vajadzībām. Šī ir PHP bibliotēka, lai palīdzētu ģenerēt Swagger dokumentāciju. -## Aplikācijas veiktspējas uzraudzība (APM) +## Lietojumprogrammas veiktspējas uzraudzība (APM) -Aplikācijas veiktspējas uzraudzība (APM) ir izšķiroša jebkurai aplikācijai. Tā palīdz saprast, kā jūsu aplikācija darbojas un kur ir pudeles kakli. Ir vairāki APM rīki, ko var izmantot ar Flight. -- oficiāls [flightphp/apm](/awesome-plugins/apm) - Flight APM ir vienkārša APM bibliotēka, ko var izmantot, lai uzraudzītu jūsu Flight aplikācijas. To var izmantot, lai uzraudzītu jūsu aplikācijas veiktspēju un palīdzētu identificēt pudeles kaklus. +Lietojumprogrammas veiktspējas uzraudzība (APM) ir izšķiroša jebkurai lietojumprogrammai. Tā palīdz jums saprast, kā darbojas jūsu lietojumprogramma un kur ir pudeles kakli. Ir vairāki APM rīki, ko var izmantot ar Flight. +- oficiāls [flightphp/apm](/awesome-plugins/apm) - Flight APM ir vienkārša APM bibliotēka, ko var izmantot, lai uzraudzītu jūsu Flight lietojumprogrammas. To var izmantot, lai uzraudzītu jūsu lietojumprogrammas veiktspēju un palīdzētu identificēt pudeles kaklus. ## Async -Flight jau ir ātrs ietvars, bet pievienojot tam turbo dzinēju, viss kļūst jautrāks (un izaicinošāks)! +Flight jau ir ātrs ietvars, bet, pievienojot tam turbīnas dzinēju, viss kļūst jautrāks (un izaicinošāks)! -- [flightphp/async](/awesome-plugins/async) - Oficiālā Flight Async bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot asinhrono apstrādi jūsu aplikācijai. Tā izmanto Swoole/Openswoole zem kapota, lai nodrošinātu vienkāršu un efektīvu veidu, kā palaist uzdevumus asinhroni. +- [flightphp/async](/awesome-plugins/async) - Oficiālā Flight Async bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot asinhrono apstrādi jūsu lietojumprogrammai. Tā izmanto Swoole/Openswoole zem kapota, lai nodrošinātu vienkāršu un efektīvu veidu, kā palaist uzdevumus asinhroni. -## Autorizācija/Atļaujas +## Autorizācija/Atslēgas -Autorizācija un atļaujas ir izšķirošas jebkurai aplikācijai, kas prasa kontroli par to, kam ir piekļuve kam. +Autorizācija un atļaujas ir izšķirošas jebkurai lietojumprogrammai, kas prasa kontroles, lai noteiktu, kas var piekļūt kam. -- oficiāls [flightphp/permissions](/awesome-plugins/permissions) - Oficiālā Flight Permissions bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot lietotāja un aplikācijas līmeņa atļaujas jūsu aplikācijai. +- oficiāls [flightphp/permissions](/awesome-plugins/permissions) - Oficiālā Flight Permissions bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot lietotāja un lietojumprogrammas līmeņa atļaujas jūsu lietojumprogrammai. ## Kešošana -Kešošana ir lielisks veids, kā paātrināt jūsu aplikāciju. Ir vairāki kešošanas bibliotēkas, ko var izmantot ar Flight. +Kešošana ir lielisks veids, kā paātrināt jūsu lietojumprogrammu. Ir vairākas kešošanas bibliotēkas, ko var izmantot ar Flight. - oficiāls [flightphp/cache](/awesome-plugins/php-file-cache) - Gaisīga, vienkārša un neatkarīga PHP failā kešošanas klase ## CLI -CLI aplikācijas ir lielisks veids, kā mijiedarboties ar jūsu aplikāciju. Jūs varat izmantot tās, lai ģenerētu kontrolierus, parādītu visas maršrutus un vairāk. +CLI lietojumprogrammas ir lielisks veids, kā mijiedarboties ar jūsu lietojumprogrammu. Jūs varat izmantot tās, lai ģenerētu kontrolierus, parādītu visas maršrutus un vairāk. -- oficiāls [flightphp/runway](/awesome-plugins/runway) - Runway ir CLI aplikācija, kas palīdz jums pārvaldīt jūsu Flight aplikācijas. +- oficiāls [flightphp/runway](/awesome-plugins/runway) - Runway ir CLI lietojumprogramma, kas palīdz jums pārvaldīt jūsu Flight lietojumprogrammas. ## Sīkfaili -Sīkfaili ir lielisks veids, kā uzglabāt mazus datu gabalus klientu pusē. Tos var izmantot, lai uzglabātu lietotāja preferences, aplikācijas iestatījumus un vairāk. +Sīkfaili ir lielisks veids, kā uzglabāt mazus datu gabaliņus klienta pusē. Tos var izmantot, lai uzglabātu lietotāja preferences, lietojumprogrammas iestatījumus un vairāk. -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie ir PHP bibliotēka, kas nodrošina vienkāršu un efektīvu veidu, kā pārvaldīt sīkfailus. +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie ir PHP bibliotēka, kas nodrošina vienkāršu un efektīvu veidu, kā pārvaldīt sīkfaiļus. -## Kļūdu labošana +## Kļūdu meklēšana -Kļūdu labošana ir izšķiroša, kad jūs attīstāt savā lokālajā vidē. Ir daži spraudņi, kas var uzlabot jūsu kļūdu labošanas pieredzi. +Kļūdu meklēšana ir izšķiroša, kad jūs izstrādājat savā lokālajā vidē. Ir dažas spraudņi, kas var uzlabot jūsu kļūdu meklēšanas pieredzi. -- [tracy/tracy](/awesome-plugins/tracy) - Šis ir pilnībā aprīkots kļūdu apstrādātājs, ko var izmantot ar Flight. Tam ir vairāki paneļi, kas var palīdzēt jums labot kļūdas jūsu aplikācijā. To ir arī ļoti viegli paplašināt un pievienot savus paneļus. -- oficiāls [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Izmantojot ar [Tracy](/awesome-plugins/tracy) kļūdu apstrādātāju, šis spraudnis pievieno dažus papildu paneļus, lai palīdzētu ar kļūdu labošanu specifiski Flight projektiem. +- [tracy/tracy](/awesome-plugins/tracy) - Šis ir pilnvērtīgs kļūdu apstrādātājs, ko var izmantot ar Flight. Tam ir vairāki paneļi, kas var palīdzēt jums kļūdu meklēšanā jūsu lietojumprogrammā. To ir arī ļoti viegli paplašināt un pievienot savus paneļus. +- oficiāls [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Izmantojot ar [Tracy](/awesome-plugins/tracy) kļūdu apstrādātāju, šis spraudnis pievieno dažus papildu paneļus, lai palīdzētu ar kļūdu meklēšanu tieši Flight projektiem. ## Datubāzes -Datubāzes ir kodols lielākajai daļai aplikāciju. Tā ir veids, kā uzglabāt un izgūt datus. Dažas datubāzu bibliotēkas ir vienkārši apvalki vaicājumu rakstīšanai, bet dažas ir pilnvērtīgas ORM. +Datubāzes ir kodols lielākajai daļai lietojumprogrammu. Tā ir veids, kā uzglabāt un izgūt datus. Dažas datubāzes bibliotēkas ir vienkārši apvalki vaicājumu rakstīšanai, bet dažas ir pilnvērtīgas ORM. - oficiāls [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Oficiālais Flight PDO apvalks, kas ir daļa no kodola. Šis ir vienkāršs apvalks, lai palīdzētu vienkāršot vaicājumu rakstīšanas un izpildes procesu. Tas nav ORM. - oficiāls [flightphp/active-record](/awesome-plugins/active-record) - Oficiālā Flight ActiveRecord ORM/Mapper. Lieliska maza bibliotēka, lai viegli izgūtu un uzglabātu datus jūsu datubāzē. @@ -61,36 +61,37 @@ Datubāzes ir kodols lielākajai daļai aplikāciju. Tā ir veids, kā uzglabāt ## Šifrēšana -Šifrēšana ir izšķiroša jebkurai aplikācijai, kas uzglabā sensitīvus datus. Datu šifrēšana un dešifrēšana nav pārāk grūti, bet pareiza šifrēšanas atslēgas uzglabāšana [var](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [būt](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [grūti](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Visnozīmīgākais ir nekad neuzglabāt jūsu šifrēšanas atslēgu publiskā direktorijā vai neiekļaut to jūsu koda repozitorijā. +Šifrēšana ir izšķiroša jebkurai lietojumprogrammai, kas uzglabā sensitīvus datus. Datu šifrēšana un dešifrēšana nav pārāk grūti, bet pareiza šifrēšanas atslēgas uzglabāšana [var](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [būt](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [grūti](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Visnozīmīgākais ir nekad neuzglabāt jūsu šifrēšanas atslēgu publiskā direktorijā vai apņemt to jūsu koda repozitorijā. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Šī ir bibliotēka, ko var izmantot, lai šifrētu un dešifrētu datus. Sākšana un palaišana ir diezgan vienkārša, lai sāktu šifrēt un dešifrēt datus. ## Darbu rinda -Darbu rindas ir patiešām noderīgas, lai asinhroni apstrādātu uzdevumus. Tas var būt e-pastu sūtīšana, attēlu apstrāde vai jebkas, kam nav jābūt reāllaika. +Darbu rindas ir patiešām noderīgas, lai asinhroni apstrādātu uzdevumus. Tas var būt e-pasta sūtīšana, attēlu apstrāde vai jebkas, kam nav jāveic reāllaikā. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue ir bibliotēka, ko var izmantot, lai apstrādātu darbus asinhroni. To var izmantot ar beanstalkd, MySQL/MariaDB, SQLite un PostgreSQL. -## Sesijas +## Sesija -Sesijas nav īsti noderīgas API, bet veidojot tīmekļa aplikāciju, sesijas var būt izšķirošas, lai uzturētu stāvokli un pieteikšanās informāciju. +Sesijas nav īsti noderīgas API, bet, veidojot tīmekļa lietojumprogrammu, sesijas var būt izšķirošas, lai uzturētu stāvokli un pieteikšanās informāciju. - oficiāls [flightphp/session](/awesome-plugins/session) - Oficiālā Flight Session bibliotēka. Šī ir vienkārša sesijas bibliotēka, ko var izmantot, lai uzglabātu un izgūtu sesijas datus. Tā izmanto PHP iebūvēto sesijas apstrādi. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session pārvaldnieks (nebloķējošs, zibspuldze, segments, sesijas šifrēšana). Izmanto PHP open_ssl opcionālai sesijas datu šifrēšanai/dešifrēšanai. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (nebloķējošs, zibspuldze, segments, sesijas šifrēšana). Izmanto PHP open_ssl izvēles šifrēšanai/dešifrēšanai sesijas datiem. ## Veidnes -Veidnes ir kodols jebkurai tīmekļa aplikācijai ar UI. Ir vairāki veidņu dzinēji, ko var izmantot ar Flight. +Veidnes ir kodols jebkurai tīmekļa lietojumprogrammai ar lietotāja interfeisu. Ir vairāki veidņu dzinēji, ko var izmantot ar Flight. -- novecojis [flightphp/core View](/learn#views) - Šis ir ļoti pamata veidņu dzinējs, kas ir daļa no kodola. Nav ieteicams izmantot, ja jūsu projektā ir vairāk nekā pāris lapas. -- [latte/latte](/awesome-plugins/latte) - Latte ir pilnībā aprīkots veidņu dzinējs, kas ir ļoti viegli lietojams un jūtas tuvāk PHP sintaksei nekā Twig vai Smarty. To ir arī ļoti viegli paplašināt un pievienot savus filtrus un funkcijas. +- novecojis [flightphp/core View](/learn#views) - Šis ir ļoti pamata veidņu dzinējs, kas ir daļa no kodola. Nav ieteicams izmantot, ja jums ir vairāk nekā pāris lapas jūsu projektā. +- [latte/latte](/awesome-plugins/latte) - Latte ir pilnvērtīgs veidņu dzinējs, ko ir ļoti viegli izmantot un kas jūtas tuvāk PHP sintaksei nekā Twig vai Smarty. To ir arī ļoti viegli paplašināt un pievienot savus filtrus un funkcijas. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate ir spēcīgs PHP veidņu dzinējs ar resursu kompilāciju, veidnes mantošanu un mainīgo apstrādi. Funkcijas ietver automātisku CSS/JS minimizāciju, kešošanu, Base64 kodēšanu un izvēles Flight PHP ietvara integrāciju. ## WordPress integrācija -Vai vēlaties izmantot Flight jūsu WordPress projektā? Ir ērts spraudnis tam! +Vai vēlaties izmantot Flight savā WordPress projektā? Ir ērts spraudnis tam! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Šis WordPress spraudnis ļauj palaist Flight tieši blakus WordPress. Tas ir ideāls, lai pievienotu pielāgotas API, mikroservisus vai pat pilnas aplikācijas jūsu WordPress vietnē, izmantojot Flight ietvaru. Ļoti noderīgi, ja vēlaties labāko no abām pasaulēm! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Šis WordPress spraudnis ļauj palaist Flight tieši blakus WordPress. Tas ir ideāli, lai pievienotu pielāgotus API, mikroservisu vai pat pilnas lietojumprogrammas jūsu WordPress vietnē, izmantojot Flight ietvaru. Ļoti noderīgi, ja vēlaties labāko no abām pasaulēm! ## Iesaiste -Vai jums ir spraudnis, ko vēlaties dalīties? Iesniedziet pull request, lai pievienotu to sarakstam! \ No newline at end of file +Vai jums ir spraudnis, ko vēlaties dalīties? Iesniedziet pieprasījumu, lai pievienotu to sarakstam! \ No newline at end of file diff --git a/content/v3/lv/awesome-plugins/comment_template.md b/content/v3/lv/awesome-plugins/comment_template.md new file mode 100644 index 00000000..ad8a0d6e --- /dev/null +++ b/content/v3/lv/awesome-plugins/comment_template.md @@ -0,0 +1,257 @@ +# CommentTemplate + +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) ir jaudīgs PHP veidņu dz motor ar resursu kompilāciju, veidņu mantojumu un mainīgo apstrādi. Tas nodrošina vienkāršu, bet elastīgu veidu, kā pārvaldīt veidnes ar iebūvētu CSS/JS minimizāciju un kešošanu. + +## Funkcijas + +- **Veidņu mantojums**: Izmantojiet izkārtojumus un iekļaujiet citas veidnes +- **Resursu kompilācija**: Automātiska CSS/JS minimizācija un kešošana +- **Mainīgo apstrāde**: Veidņu mainīgie ar filtrēšanu un komandām +- **Base64 kodēšana**: Iekšējie resursi kā datu URI +- **Flight Framework integrācija**: Neobligātā integrācija ar Flight PHP framework + +## Instalācija + +Instalējiet ar composer. + +```bash +composer require knifelemon/comment-template +``` + +## Pamata konfigurācija + +Ir daži pamata konfigurācijas varianti, lai sāktu darbu. Jūs varat lasīt vairāk par tiem [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate). + +### 1. metode: Izmantojot atgriezeniskās saites funkciju + +```php +register('view', Engine::class, [], function (Engine $engine) use ($app) { + // Kur tiek glabāti jūsu veidņu faili + $engine->setTemplatesPath(__DIR__ . '/views'); + + // Kur tiks apkalpoti jūsu publiskie resursi + $engine->setPublicPath(__DIR__ . '/public'); + + // Kur tiks glabāti kompilētie resursi + $engine->setAssetPath('assets'); + + // Veidnes faila paplašinājums + $engine->setFileExtension('.php'); +}); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +### 2. metode: Izmantojot konstruktoras parametrus + +```php +register('view', Engine::class, [ + __DIR__ . '/public', // publicPath - kur tiks apkalpoti resursi + __DIR__ . '/views', // skinPath - kur tiek glabāti veidņu faili + 'assets', // assetPath - kur tiks glabāti kompilētie resursi + '.php' // fileExtension - veidnes faila paplašinājums +]); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +## Veidnes direktīvas + +### Izkārtojuma mantojums + +Izmantojiet izkārtojumus, lai izveidotu kopīgu struktūru: + +**layout/global_layout.php**: +```html + + + + {$title} + + + + + +``` + +**view/page.php**: +```html + +

{$title}

+

{$content}

+``` + +### Resursu pārvaldība + +#### CSS faili +```html + + +``` + +#### JavaScript faili +CommentTemplate atbalsta dažādas JavaScript ielādes stratēģijas: + +```html + + + + + + + + + +``` + +#### Resursu direktīvas CSS/JS failos + +CommentTemplate apstrādā arī resursu direktīvas CSS un JavaScript failos kompilācijas laikā: + +**CSS piemērs:** +```css +/* Jūsu CSS failos */ +/* @font-face { + font-family: 'CustomFont'; + src: url('') format('woff2'); +} + +.background-image { + background: url(''); +} + +.inline-icon { + background: url(''); +} +``` + +**JavaScript piemērs:** +```javascript +/* Jūsu JS failos */ +const fontUrl = ''; +const imageData = ''; +``` + +#### Base64 kodēšana +```html + +``` +** Piemērs: ** +```html + +Logo +
+ Mazs ikona kā fons +
+``` + +#### Resursu kopēšana +```html + + +``` +** Piemērs: ** +```html + +Hero Banner +Lejupielādēt Brošūru + + + + +``` + +### Veidnes iekļaušana +```html + +``` +** Piemērs: ** +```html + + + +
+

Sveiki mūsu vietnē

+ + +
+

Galvenais saturs šeit...

+
+
+ + +``` + +### Mainīgo apstrāde + +#### Pamata mainīgie +```html +

{$title}

+

{$description}

+``` + +#### Mainīgo filtri +```html +{$title|upper} +{$content|lower} +{$html|striptag} +{$text|escape} +{$multiline|nl2br} +{$html|br2nl} +{$description|trim} +{$subject|title} +``` + +#### Mainīgo komandas +```html +{$title|default=Default Title} +{$name|concat= (Admin)} +``` + +#### Mainīgo komandas +```html +{$content|striptag|trim|escape} +``` + +## Piemēra projekta struktūra + +``` +project/ +├── source/ +│ ├── layouts/ +│ │ └── default.php +│ ├── components/ +│ │ ├── header.php +│ │ └── footer.php +│ ├── css/ +│ │ ├── bootstrap.min.css +│ │ └── custom.css +│ ├── js/ +│ │ ├── app.js +│ │ └── bootstrap.min.js +│ └── homepage.php +├── public/ +│ └── assets/ # Ģenerētie resursi +│ ├── css/ +│ └── js/ +└── vendor/ +``` \ No newline at end of file diff --git a/content/v3/lv/examples.md b/content/v3/lv/examples.md index d7b1605e..d1bbd8be 100644 --- a/content/v3/lv/examples.md +++ b/content/v3/lv/examples.md @@ -1,25 +1,26 @@ -# Vai ātri sākt? +# Vai tev vajadzīga ātra uzsākšana? -Jums ir divas opcijas, lai sāktu jaunu Flight projektu: +Tev ir divas iespējas sākt darbu ar jaunu Flight projektu: -- [Pilna skeletu sagatave](https://github.com/flightphp/skeleton): Pilnīgāks piemērs ar kontrolieriem un skatiem. -- [Vienkārša faila skeletu sagatave](https://github.com/flightphp/skeleton-simple): Viens fails, kas ietver visu nepieciešamo, lai palaistu jūsu lietotni vienā vienkāršā failā. +- [Pilna Skeleton Boilerplate](https://github.com/flightphp/skeleton): Pilnīgāks piemērs ar kontrolieriem un skatiem. +- [Vienfaila Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Viena faila, kas ietver visu, kas tev vajadzīgs, lai palaistu savu lietotni vienā vienkāršā failā. -Kopienas sniegti piemēri: +Kopienas sniegtie piemēri: - [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP ar Laravel direktorijām, ar PHP rīkiem + GH Actions - [fleact](https://github.com/flightphp/fleact) - FlightPHP starter komplekts ar ReactJS integrāciju. - [flastro](https://github.com/flightphp/flastro) - FlightPHP starter komplekts ar Astro integrāciju. -- [velt](https://github.com/flightphp/velt) - Velt ir ātrs un viegls Svelte starter veidne ar FlightPHP aizmuguri. +- [velt](https://github.com/flightphp/velt) - Velt ir ātrs un viegls Svelte starter veidne ar FlightPHP backend. -## Vai vajag iedvesmu? +## Vai tev vajadzīga kāda iedvesma? -Lai gan šie nav oficiāli atbalstīti no Flight komandas puses, tie var sniegt idejas, kā strukturēt savus paša projektus, kas izveidoti ar Flight! +Lai gan šie nav oficiāli atbalstīti no Flight komandas puses, tie var dot tev idejas, kā strukturēt savus paša projektus, kas būvēti ar Flight! -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental ir vienlapa, mobilajām ierīcēm draudzīga auto nomas tīmekļa lietotne, kas izveidota ar PHP (FlightPHP), JavaScript un MySQL. Tā atbalsta lietotāju reģistrāciju, pārlūkošanu un auto rezervēšanu, savukārt administratori var pārvaldīt auto, lietotājus un rezervācijas. Lietotnē ir REST API, JWT autentifikācija un responsīvs dizains modernai nomas pieredzei. +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify ir vienas lapas lietotne, kas savieno pasākumu organizatorus ar dalībniekiem. Būvēta ar PHP (FlightPHP), JavaScript un MySQL, tā ietver JWT autentifikāciju, pasākumu pārvaldību un RESTful API dokumentāciju, izmantojot OpenAPI. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental ir vienas lapas, mobilajām ierīcēm draudzīga automašīnu nomas tīmekļa lietotne, būvēta ar PHP (FlightPHP), JavaScript un MySQL. Tā atbalsta lietotāju reģistrāciju, pārlūkošanu un automašīnu rezervēšanu, kamēr administratori var pārvaldīt automašīnas, lietotājus un rezervācijas. Lietotnē ir REST API, JWT autentifikācija un responsīvs dizains modernai nomas pieredzei. - [Decay](https://github.com/boxybird/decay) - Flight v3 ar HTMX un SleekDB, viss par zombijiem! ([Demo](https://decay.andrewrhyand.com)) -- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 ar starprogrammatūru, kontrolieriem, Active Record un Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Vienkāršs CRUD API projekts, izmantojot Flight ietvaru, kas nodrošina pamata struktūru jauniem lietotājiem, lai ātri izveidotu PHP lietotni ar CRUD operācijām un datubāzes savienojumu. Projekts demonstrē, kā izmantot Flight RESTful API izstrādei, padarot to par ideālu mācību rīku iesācējiem un noderīgu starter komplektu pieredzējušākiem izstrādātājiem. +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 ar Middleware, kontrolieriem, Active Record un Latte. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Vienkāršs CRUD API projekts, izmantojot Flight framework, kas nodrošina pamata struktūru jauniem lietotājiem, lai ātri izveidotu PHP lietotni ar CRUD operācijām un datubāzes savienojumu. Projekts demonstrē, kā izmantot Flight RESTful API izstrādei, padarot to par ideālu mācību rīku iesācējiem un noderīgu starter komplektu pieredzējušākiem izstrādātājiem. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -30,8 +31,8 @@ Lai gan šie nav oficiāli atbalstīti no Flight komandas puses, tie var sniegt - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Ražošanai gatavs autentifikācijas ietvars, kas ietaupa nedēļām ilgu izstrādi. Funkcijas ietver uzņēmuma līmeņa drošību: 2FA/TOTP, LDAP integrācija, Azure SSO, inteliģenta ātruma ierobežošana, sesijas pirkstu nospieduma atpazīšana, aizsardzība pret brutālu spēku, drošības analītikas panelis, visaptveroša audita žurnālošana un granulāra lomām balstīta piekļuves kontrole. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Ražošanai gatavs autentifikācijas framework, kas ietaupa nedēļas izstrādes laika. Ietver uzņēmuma līmeņa drošību: 2FA/TOTP, LDAP integrāciju, Azure SSO, inteliģentu ātruma ierobežošanu, sesijas pirkstu nospiedumu, aizsardzību pret brutālu spēku, drošības analītikas paneli, visaptverošu audita žurnālošanu un granulētu lomu balstītu piekļuves kontroli. -## Vai vēlaties dalīties ar savu paša piemēru? +## Vai vēlies dalīties ar savu paša piemēru? -Ja jums ir projekts, kuru vēlaties dalīt, lūdzu, iesniedziet pull request, lai to pievienotu šim sarakstam! \ No newline at end of file +Ja tev ir projekts, ko vēlies dalīt, lūdzu, iesniedz pull request, lai to pievienotu šim sarakstam! \ No newline at end of file diff --git a/content/v3/pt/awesome-plugins/awesome_plugins.md b/content/v3/pt/awesome-plugins/awesome_plugins.md index 13d2305d..5df510e3 100644 --- a/content/v3/pt/awesome-plugins/awesome_plugins.md +++ b/content/v3/pt/awesome-plugins/awesome_plugins.md @@ -12,44 +12,44 @@ A documentação de API é crucial para qualquer API. Ela ajuda os desenvolvedor ## Monitoramento de Desempenho de Aplicação (APM) O Monitoramento de Desempenho de Aplicação (APM) é crucial para qualquer aplicação. Ele ajuda você a entender como sua aplicação está se saindo e onde estão os gargalos. Existem vários ferramentas APM que podem ser usadas com Flight. -- oficial [flightphp/apm](/awesome-plugins/apm) - Flight APM é uma biblioteca APM simples que pode ser usada para monitorar suas aplicações Flight. Ela pode ser usada para monitorar o desempenho da sua aplicação e ajudá-lo a identificar gargalos. +- oficial [flightphp/apm](/awesome-plugins/apm) - Flight APM é uma biblioteca APM simples que pode ser usada para monitorar suas aplicações Flight. Pode ser usada para monitorar o desempenho da sua aplicação e ajudá-lo a identificar gargalos. -## Async +## Assíncrono -Flight já é um framework rápido, mas adicionar um motor turbo nele torna tudo mais divertido (e desafiador)! +Flight já é um framework rápido, mas adicionar um motor turbo a ele torna tudo mais divertido (e desafiador)! -- [flightphp/async](/awesome-plugins/async) - Biblioteca Async oficial do Flight. Esta biblioteca é uma forma simples de adicionar processamento assíncrono à sua aplicação. Ela usa Swoole/Openswoole sob o capô para fornecer uma forma simples e eficaz de executar tarefas de forma assíncrona. +- [flightphp/async](/awesome-plugins/async) - Biblioteca Async oficial do Flight. Esta biblioteca é uma forma simples de adicionar processamento assíncrono à sua aplicação. Ela usa Swoole/Openswoole sob o capô para fornecer uma maneira simples e eficaz de executar tarefas de forma assíncrona. ## Autorização/Permissões -Autorização e Permissões são cruciais para qualquer aplicação que requer controles para quem pode acessar o quê. +Autorização e Permissões são cruciais para qualquer aplicação que exija controles para quem pode acessar o quê. - oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca de Permissões oficial do Flight. Esta biblioteca é uma forma simples de adicionar permissões em nível de usuário e aplicação à sua aplicação. ## Cache -Cache é uma ótima forma de acelerar sua aplicação. Existem várias bibliotecas de cache que podem ser usadas com Flight. +Cache é uma ótima maneira de acelerar sua aplicação. Existem várias bibliotecas de cache que podem ser usadas com Flight. -- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Classe leve, simples e independente de cache em arquivo PHP +- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Classe de cache em arquivo PHP leve, simples e independente ## CLI -Aplicações CLI são uma ótima forma de interagir com sua aplicação. Você pode usá-las para gerar controladores, exibir todas as rotas e mais. +Aplicações CLI são uma ótima maneira de interagir com sua aplicação. Você pode usá-las para gerar controladores, exibir todas as rotas e mais. - oficial [flightphp/runway](/awesome-plugins/runway) - Runway é uma aplicação CLI que ajuda você a gerenciar suas aplicações Flight. ## Cookies -Cookies são uma ótima forma de armazenar pequenos pedaços de dados no lado do cliente. Eles podem ser usados para armazenar preferências de usuário, configurações de aplicação e mais. +Cookies são uma ótima maneira de armazenar pequenos pedaços de dados no lado do cliente. Eles podem ser usados para armazenar preferências do usuário, configurações da aplicação e mais. -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie é uma biblioteca PHP que fornece uma forma simples e eficaz de gerenciar cookies. +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie é uma biblioteca PHP que fornece uma maneira simples e eficaz de gerenciar cookies. ## Depuração Depuração é crucial quando você está desenvolvendo em seu ambiente local. Existem alguns plugins que podem elevar sua experiência de depuração. -- [tracy/tracy](/awesome-plugins/tracy) - Esta é um manipulador de erros completo que pode ser usado com Flight. Ele tem vários painéis que podem ajudá-lo a depurar sua aplicação. Também é muito fácil de estender e adicionar seus próprios painéis. -- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado com o manipulador de erros [Tracy](/awesome-plugins/tracy), este plugin adiciona alguns painéis extras para ajudar com depuração especificamente para projetos Flight. +- [tracy/tracy](/awesome-plugins/tracy) - Este é um manipulador de erros completo que pode ser usado com Flight. Ele tem vários painéis que podem ajudá-lo a depurar sua aplicação. Também é muito fácil de estender e adicionar seus próprios painéis. +- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado com o manipulador de erros [Tracy](/awesome-plugins/tracy), este plugin adiciona alguns painéis extras para ajudar na depuração especificamente para projetos Flight. ## Bancos de Dados @@ -61,7 +61,7 @@ Bancos de dados são o núcleo da maioria das aplicações. É assim que você a ## Criptografia -Criptografia é crucial para qualquer aplicação que armazena dados sensíveis. Criptografar e descriptografar os dados não é terrivelmente difícil, mas armazenar corretamente a chave de criptografia [pode](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [ser](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difícil](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). A coisa mais importante é nunca armazenar sua chave de criptografia em um diretório público ou commitá-la em seu repositório de código. +Criptografia é crucial para qualquer aplicação que armazena dados sensíveis. Criptografar e descriptografar os dados não é terrivelmente difícil, mas armazenar adequadamente a chave de criptografia [pode](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [ser](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difícil](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). O mais importante é nunca armazenar sua chave de criptografia em um diretório público ou commitá-la em seu repositório de código. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Esta é uma biblioteca que pode ser usada para criptografar e descriptografar dados. Começar a usar é bastante simples para começar a criptografar e descriptografar dados. @@ -69,21 +69,22 @@ Criptografia é crucial para qualquer aplicação que armazena dados sensíveis. Filas de tarefas são realmente úteis para processar tarefas de forma assíncrona. Isso pode ser enviar e-mails, processar imagens ou qualquer coisa que não precise ser feita em tempo real. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue é uma biblioteca que pode ser usada para processar tarefas de forma assíncrona. Ela pode ser usada com beanstalkd, MySQL/MariaDB, SQLite e PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue é uma biblioteca que pode ser usada para processar tarefas de forma assíncrona. Pode ser usada com beanstalkd, MySQL/MariaDB, SQLite e PostgreSQL. ## Sessão Sessões não são realmente úteis para APIs, mas para construir uma aplicação web, sessões podem ser cruciais para manter o estado e informações de login. -- oficial [flightphp/session](/awesome-plugins/session) - Biblioteca de Sessão oficial do Flight. Esta é uma biblioteca de sessão simples que pode ser usada para armazenar e recuperar dados de sessão. Ela usa o manipulador de sessão integrado do PHP. +- oficial [flightphp/session](/awesome-plugins/session) - Biblioteca de Sessão oficial do Flight. Esta é uma biblioteca de sessão simples que pode ser usada para armazenar e recuperar dados de sessão. Ela usa o manuseio de sessão integrado do PHP. - [Ghostff/Session](/awesome-plugins/ghost-session) - Gerenciador de Sessão PHP (não bloqueante, flash, segmento, criptografia de sessão). Usa PHP open_ssl para criptografia/descriptografia opcional de dados de sessão. -## Templating +## Modelagem -Templating é o núcleo de qualquer aplicação web com uma UI. Existem vários motores de templating que podem ser usados com Flight. +Modelagem é o núcleo de qualquer aplicação web com uma UI. Existem vários motores de modelagem que podem ser usados com Flight. -- deprecado [flightphp/core View](/learn#views) - Este é um motor de templating muito básico que faz parte do núcleo. Não é recomendado usá-lo se você tiver mais de algumas páginas em seu projeto. -- [latte/latte](/awesome-plugins/latte) - Latte é um motor de templating completo que é muito fácil de usar e se sente mais próximo da sintaxe PHP do que Twig ou Smarty. Também é muito fácil de estender e adicionar seus próprios filtros e funções. +- deprecado [flightphp/core View](/learn#views) - Este é um motor de modelagem muito básico que faz parte do núcleo. Não é recomendado usá-lo se você tiver mais do que algumas páginas em seu projeto. +- [latte/latte](/awesome-plugins/latte) - Latte é um motor de modelagem completo que é muito fácil de usar e se sente mais próximo da sintaxe PHP do que Twig ou Smarty. Também é muito fácil de estender e adicionar seus próprios filtros e funções. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate é um poderoso motor de template PHP com compilação de assets, herança de templates e processamento de variáveis. Recursos incluem minificação automática de CSS/JS, cache, codificação Base64 e integração opcional com o framework PHP Flight. ## Integração com WordPress diff --git a/content/v3/pt/awesome-plugins/comment_template.md b/content/v3/pt/awesome-plugins/comment_template.md new file mode 100644 index 00000000..0161b222 --- /dev/null +++ b/content/v3/pt/awesome-plugins/comment_template.md @@ -0,0 +1,257 @@ +# CommentTemplate + +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) é um poderoso motor de templates PHP com compilação de assets, herança de templates e processamento de variáveis. Ele fornece uma maneira simples, mas flexível, de gerenciar templates com minificação integrada de CSS/JS e cache. + +## Recursos + +- **Herança de Templates**: Use layouts e inclua outros templates +- **Compilação de Assets**: Minificação e cache automáticos de CSS/JS +- **Processamento de Variáveis**: Variáveis de template com filtros e comandos +- **Codificação Base64**: Assets inline como URIs de dados +- **Integração com o Framework Flight**: Integração opcional com o framework PHP Flight + +## Instalação + +Instale com o composer. + +```bash +composer require knifelemon/comment-template +``` + +## Configuração Básica + +Existem algumas opções de configuração básicas para começar. Você pode ler mais sobre elas no [Repositório CommentTemplate](https://github.com/KnifeLemon/CommentTemplate). + +### Método 1: Usando Função de Callback + +```php +register('view', Engine::class, [], function (Engine $engine) use ($app) { + // Onde seus arquivos de template estão armazenados + $engine->setTemplatesPath(__DIR__ . '/views'); + + // Onde seus assets públicos serão servidos + $engine->setPublicPath(__DIR__ . '/public'); + + // Onde os assets compilados serão armazenados + $engine->setAssetPath('assets'); + + // Extensão do arquivo de template + $engine->setFileExtension('.php'); +}); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +### Método 2: Usando Parâmetros do Construtor + +```php +register('view', Engine::class, [ + __DIR__ . '/public', // publicPath - onde os assets serão servidos + __DIR__ . '/views', // skinPath - onde os arquivos de template estão armazenados + 'assets', // assetPath - onde os assets compilados serão armazenados + '.php' // fileExtension - extensão do arquivo de template +]); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +## Diretivas de Template + +### Herança de Layout + +Use layouts para criar uma estrutura comum: + +**layout/global_layout.php**: +```html + + + + {$title} + + + + + +``` + +**view/page.php**: +```html + +

{$title}

+

{$content}

+``` + +### Gerenciamento de Assets + +#### Arquivos CSS +```html + + +``` + +#### Arquivos JavaScript +O CommentTemplate suporta diferentes estratégias de carregamento de JavaScript: + +```html + + + + + + + + + +``` + +#### Diretivas de Assets em Arquivos CSS/JS + +O CommentTemplate também processa diretivas de assets dentro de arquivos CSS e JavaScript durante a compilação: + +**Exemplo CSS:** +```css +/* Em seus arquivos CSS */ +@font-face { + font-family: 'CustomFont'; + src: url('') format('woff2'); +} + +.background-image { + background: url(''); +} + +.inline-icon { + background: url(''); +} +``` + +**Exemplo JavaScript:** +```javascript +/* Em seus arquivos JS */ +const fontUrl = ''; +const imageData = ''; +``` + +#### Codificação Base64 +```html + +``` +** Exemplo: ** +```html + +Logo +
+ Ícone pequeno como fundo +
+``` + +#### Cópia de Assets +```html + + +``` +** Exemplo: ** +```html + +Banner Heroico +Baixar Brochura + + + + +``` + +### Inclusões de Template +```html + +``` +** Exemplo: ** +```html + + + +
+

Bem-vindo ao nosso site

+ + +
+

Conteúdo principal aqui...

+
+
+ + +``` + +### Processamento de Variáveis + +#### Variáveis Básicas +```html +

{$title}

+

{$description}

+``` + +#### Filtros de Variáveis +```html +{$title|upper} +{$content|lower} +{$html|striptag} +{$text|escape} +{$multiline|nl2br} +{$html|br2nl} +{$description|trim} +{$subject|title} +``` + +#### Comandos de Variáveis +```html +{$title|default=Default Title} +{$name|concat= (Admin)} +``` + +#### Comandos de Variáveis +```html +{$content|striptag|trim|escape} +``` + +## Estrutura de Projeto Exemplo + +``` +project/ +├── source/ +│ ├── layouts/ +│ │ └── default.php +│ ├── components/ +│ │ ├── header.php +│ │ └── footer.php +│ ├── css/ +│ │ ├── bootstrap.min.css +│ │ └── custom.css +│ ├── js/ +│ │ ├── app.js +│ │ └── bootstrap.min.js +│ └── homepage.php +├── public/ +│ └── assets/ # Assets gerados +│ ├── css/ +│ └── js/ +└── vendor/ +``` \ No newline at end of file diff --git a/content/v3/pt/examples.md b/content/v3/pt/examples.md index 052b71e9..30358c64 100644 --- a/content/v3/pt/examples.md +++ b/content/v3/pt/examples.md @@ -16,9 +16,10 @@ Exemplos contribuídos pela comunidade: Embora estes não sejam oficialmente patrocinados pela Equipe Flight, eles podem dar ideias sobre como estruturar seus próprios projetos construídos com Flight! -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental é uma aplicação web de aluguel de carros de página única, amigável para mobile, construída com PHP (FlightPHP), JavaScript e MySQL. Ela suporta registro de usuários, navegação e reserva de carros, enquanto administradores podem gerenciar carros, usuários e reservas. O app possui uma API REST, autenticação JWT e um design responsivo para uma experiência de aluguel moderna. +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify é um app de página única que conecta organizadores de eventos com participantes. Construído com PHP (FlightPHP), JavaScript e MySQL, possui autenticação JWT, gerenciamento de eventos e documentação de API RESTful usando OpenAPI. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental é uma aplicação web de aluguel de carros de página única e amigável para mobile, construída com PHP (FlightPHP), JavaScript e MySQL. Suporta registro de usuários, navegação e reserva de carros, enquanto administradores podem gerenciar carros, usuários e reservas. O app possui uma API REST, autenticação JWT e design responsivo para uma experiência de aluguel moderna. - [Decay](https://github.com/boxybird/decay) - Flight v3 com HTMX e SleekDB tudo sobre zumbis! ([Demo](https://decay.andrewrhyand.com)) -- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 com Middleware, Controladores, Active Record e Latte. +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 com Middleware, Controllers, Active Record e Latte. - [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Projeto simples de API CRUD usando o framework Flight, que fornece uma estrutura básica para novos usuários configurarem rapidamente uma aplicação PHP com operações CRUD e conectividade de banco de dados. O projeto demonstra como usar Flight para desenvolvimento de API RESTful, tornando-o uma ferramenta de aprendizado ideal para iniciantes e um kit inicial útil para desenvolvedores mais experientes. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 diff --git a/content/v3/ru/awesome-plugins/awesome_plugins.md b/content/v3/ru/awesome-plugins/awesome_plugins.md index 79487883..144f4c55 100644 --- a/content/v3/ru/awesome-plugins/awesome_plugins.md +++ b/content/v3/ru/awesome-plugins/awesome_plugins.md @@ -4,93 +4,95 @@ Flight невероятно расширяем. Существует множе ## Документация API -Документация API крайне важна для любого API. Она помогает разработчикам понять, как взаимодействовать с вашим API и чего ожидать в ответ. Есть несколько инструментов, которые помогут вам генерировать документацию API для ваших проектов Flight. +Документация API крайне важна для любого API. Она помогает разработчикам понять, как взаимодействовать с вашим API и чего ожидать в ответ. Есть несколько инструментов, доступных для генерации документации API для ваших проектов Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Пост в блоге, написанный Даниэлем Шрайбером, о том, как использовать спецификацию OpenAPI с FlightPHP для построения вашего API с использованием подхода "API first". -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI — отличный инструмент для генерации документации API для ваших проектов Flight. Его очень легко использовать, и его можно настроить под ваши нужды. Это PHP-библиотека, которая поможет вам генерировать документацию Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) — Пост в блоге, написанный Daniel Schreiber, о том, как использовать спецификацию OpenAPI с FlightPHP для построения вашего API с использованием подхода API first. +- [SwaggerUI](https://github.com/zircote/swagger-php) — Swagger UI — отличный инструмент для генерации документации API для ваших проектов Flight. Его очень легко использовать, и его можно настроить под ваши нужды. Это PHP-библиотека для генерации документации Swagger. ## Мониторинг производительности приложений (APM) Мониторинг производительности приложений (APM) крайне важен для любого приложения. Он помогает понять, как работает ваше приложение и где находятся узкие места. Существует множество инструментов APM, которые можно использовать с Flight. -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM — это простая библиотека APM, которая может использоваться для мониторинга приложений Flight. Она может использоваться для мониторинга производительности вашего приложения и помощи в выявлении узких мест. + +- official [flightphp/apm](/awesome-plugins/apm) — Flight APM — это простая библиотека APM, которую можно использовать для мониторинга приложений Flight. Она может использоваться для мониторинга производительности вашего приложения и помощи в выявлении узких мест. ## Асинхронность -Flight уже является быстрым фреймворком, но добавление к нему турбо-двигателя делает всё ещё веселее (и сложнее)! +Flight уже является быстрым фреймворком, но добавление турбо-двигателя делает всё ещё веселее (и сложнее)! -- [flightphp/async](/awesome-plugins/async) - Официальная библиотека Flight Async. Эта библиотека — простой способ добавить асинхронную обработку в ваше приложение. Она использует Swoole/Openswoole под капотом, чтобы предоставить простой и эффективный способ запуска задач асинхронно. +- [flightphp/async](/awesome-plugins/async) — Официальная библиотека Flight Async. Эта библиотека — простой способ добавить асинхронную обработку в ваше приложение. Она использует Swoole/Openswoole под капотом, чтобы предоставить простой и эффективный способ запуска задач асинхронно. ## Авторизация/Разрешения Авторизация и разрешения крайне важны для любого приложения, которое требует контроля над тем, кто может получить доступ к чему. -- official [flightphp/permissions](/awesome-plugins/permissions) - Официальная библиотека Flight Permissions. Эта библиотека — простой способ добавить разрешения на уровне пользователя и приложения в ваше приложение. +- official [flightphp/permissions](/awesome-plugins/permissions) — Официальная библиотека Flight Permissions. Эта библиотека — простой способ добавить разрешения на уровне пользователя и приложения в ваше приложение. ## Кэширование Кэширование — отличный способ ускорить ваше приложение. Существует множество библиотек кэширования, которые можно использовать с Flight. -- official [flightphp/cache](/awesome-plugins/php-file-cache) - Лёгкий, простой и автономный класс PHP для кэширования в файлах +- official [flightphp/cache](/awesome-plugins/php-file-cache) — Легкая, простая и автономная PHP-библиотека кэширования в файле. ## CLI -CLI-приложения — отличный способ взаимодействовать с вашим приложением. Вы можете использовать их для генерации контроллеров, отображения всех маршрутов и многого другого. +CLI-приложения — отличный способ взаимодействовать с вашим приложением. Их можно использовать для генерации контроллеров, отображения всех маршрутов и многого другого. -- official [flightphp/runway](/awesome-plugins/runway) - Runway — это CLI-приложение, которое помогает управлять вашими приложениями Flight. +- official [flightphp/runway](/awesome-plugins/runway) — Runway — это CLI-приложение, которое помогает управлять вашими приложениями Flight. ## Куки Куки — отличный способ хранить небольшие объёмы данных на стороне клиента. Их можно использовать для хранения предпочтений пользователя, настроек приложения и многого другого. -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie — это PHP-библиотека, которая предоставляет простой и эффективный способ управления куки. +- [overclokk/cookie](/awesome-plugins/php-cookie) — PHP Cookie — это PHP-библиотека, которая предоставляет простой и эффективный способ управления куки. ## Отладка Отладка крайне важна при разработке в локальной среде. Есть несколько плагинов, которые могут улучшить ваш опыт отладки. -- [tracy/tracy](/awesome-plugins/tracy) - Это полнофункциональный обработчик ошибок, который можно использовать с Flight. У него есть несколько панелей, которые помогут вам отлаживать ваше приложение. Его также очень легко расширять и добавлять собственные панели. -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Используется с обработчиком ошибок [Tracy](/awesome-plugins/tracy), этот плагин добавляет несколько дополнительных панелей для помощи в отладке специально для проектов Flight. +- [tracy/tracy](/awesome-plugins/tracy) — Это полнофункциональный обработчик ошибок, который можно использовать с Flight. У него есть несколько панелей, которые могут помочь вам отлаживать ваше приложение. Его также очень легко расширять и добавлять свои собственные панели. +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) — Используется с обработчиком ошибок [Tracy](/awesome-plugins/tracy), этот плагин добавляет несколько дополнительных панелей для помощи в отладке специально для проектов Flight. ## Базы данных Базы данных — основа большинства приложений. Это способ хранения и извлечения данных. Некоторые библиотеки баз данных — просто обёртки для написания запросов, а некоторые — полноценные ORM. -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Официальная обёртка Flight PDO, которая является частью ядра. Это простая обёртка, которая помогает упростить процесс написания и выполнения запросов. Это не ORM. -- official [flightphp/active-record](/awesome-plugins/active-record) - Официальный ORM/Mapper Flight ActiveRecord. Отличная маленькая библиотека для лёгкого извлечения и хранения данных в вашей базе данных. -- [byjg/php-migration](/awesome-plugins/migrations) - Плагин для отслеживания всех изменений базы данных в вашем проекте. +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) — Официальная обёртка Flight PDO, которая является частью ядра. Это простая обёртка, чтобы упростить процесс написания и выполнения запросов. Это не ORM. +- official [flightphp/active-record](/awesome-plugins/active-record) — Официальный ORM/Mapper Flight ActiveRecord. Отличная маленькая библиотека для лёгкого извлечения и хранения данных в вашей базе данных. +- [byjg/php-migration](/awesome-plugins/migrations) — Плагин для отслеживания всех изменений базы данных в вашем проекте. ## Шифрование Шифрование крайне важно для любого приложения, которое хранит конфиденциальные данные. Шифрование и дешифрование данных не так уж сложно, но правильное хранение ключа шифрования [может](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [быть](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [сложным](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Самое важное — никогда не хранить ключ шифрования в публичной директории или коммитить его в репозиторий кода. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Это библиотека, которую можно использовать для шифрования и дешифрования данных. Запуск и работа с ней довольно просты для начала шифрования и дешифрования данных. +- [defuse/php-encryption](/awesome-plugins/php-encryption) — Это библиотека, которую можно использовать для шифрования и дешифрования данных. Запуск и работа с ней довольно просты для начала шифрования и дешифрования данных. ## Очередь заданий Очереди заданий очень полезны для асинхронной обработки задач. Это может быть отправка email, обработка изображений или что-то, что не требует выполнения в реальном времени. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue — это библиотека, которую можно использовать для асинхронной обработки заданий. Её можно использовать с beanstalkd, MySQL/MariaDB, SQLite и PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) — Simple Job Queue — это библиотека, которую можно использовать для асинхронной обработки заданий. Её можно использовать с beanstalkd, MySQL/MariaDB, SQLite и PostgreSQL. ## Сессии Сессии не очень полезны для API, но для построения веб-приложения сессии могут быть крайне важны для поддержания состояния и информации о входе. -- official [flightphp/session](/awesome-plugins/session) - Официальная библиотека Flight Session. Это простая библиотека сессий, которую можно использовать для хранения и извлечения данных сессии. Она использует встроенную обработку сессий PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - Менеджер сессий PHP (неблокирующий, flash, сегмент, шифрование сессий). Использует PHP open_ssl для опционального шифрования/дешифрования данных сессии. +- official [flightphp/session](/awesome-plugins/session) — Официальная библиотека Flight Session. Это простая библиотека сессий, которую можно использовать для хранения и извлечения данных сессии. Она использует встроенную обработку сессий PHP. +- [Ghostff/Session](/awesome-plugins/ghost-session) — PHP Session Manager (неблокирующий, flash, сегмент, шифрование сессий). Использует PHP open_ssl для опционального шифрования/дешифрования данных сессии. ## Шаблонизация Шаблонизация — основа любого веб-приложения с UI. Существует множество шаблонизаторов, которые можно использовать с Flight. -- deprecated [flightphp/core View](/learn#views) - Это очень базовый шаблонизатор, который является частью ядра. Не рекомендуется использовать, если в вашем проекте больше нескольких страниц. -- [latte/latte](/awesome-plugins/latte) - Latte — полнофункциональный шаблонизатор, который очень легко использовать и ближе к синтаксису PHP, чем Twig или Smarty. Его также очень легко расширять и добавлять собственные фильтры и функции. +- deprecated [flightphp/core View](/learn#views) — Это очень базовый шаблонизатор, который является частью ядра. Не рекомендуется использовать, если в вашем проекте больше нескольких страниц. +- [latte/latte](/awesome-plugins/latte) — Latte — полнофункциональный шаблонизатор, который очень легко использовать и ближе к синтаксису PHP, чем Twig или Smarty. Его также очень легко расширять и добавлять свои фильтры и функции. +- [knifelemon/comment-template](/awesome-plugins/comment-template) — CommentTemplate — мощный PHP-шаблонизатор с компиляцией ассетов, наследованием шаблонов и обработкой переменных. Поддерживает автоматическую минификацию CSS/JS, кэширование, кодирование Base64 и опциональную интеграцию с фреймворком Flight PHP. ## Интеграция с WordPress Хотите использовать Flight в вашем проекте WordPress? Для этого есть удобный плагин! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Этот плагин WordPress позволяет запускать Flight прямо рядом с WordPress. Он идеален для добавления пользовательских API, микросервисов или даже полноценных приложений на ваш сайт WordPress с использованием фреймворка Flight. Супер полезно, если вы хотите лучшее из двух миров! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) — Этот плагин WordPress позволяет запускать Flight параллельно с WordPress. Он идеален для добавления пользовательских API, микросервисов или даже полноценных приложений на ваш сайт WordPress с использованием фреймворка Flight. Суперполезно, если вы хотите лучшее из двух миров! -## Вклад +## Вклад в проект Есть плагин, которым вы хотите поделиться? Отправьте pull request, чтобы добавить его в список! \ No newline at end of file diff --git a/content/v3/ru/awesome-plugins/comment_template.md b/content/v3/ru/awesome-plugins/comment_template.md new file mode 100644 index 00000000..7776361a --- /dev/null +++ b/content/v3/ru/awesome-plugins/comment_template.md @@ -0,0 +1,257 @@ +# CommentTemplate + +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) — это мощный шаблонизатор PHP с компиляцией активов, наследованием шаблонов и обработкой переменных. Он предоставляет простой и гибкий способ управления шаблонами с встроенной минификацией CSS/JS и кэшированием. + +## Особенности + +- **Наследование шаблонов**: Использование макетов и включение других шаблонов +- **Компиляция активов**: Автоматическая минификация и кэширование CSS/JS +- **Обработка переменных**: Переменные шаблонов с фильтрами и командами +- **Кодирование Base64**: Встраивание активов как data URI +- **Интеграция с фреймворком Flight**: Необязательная интеграция с фреймворком PHP Flight + +## Установка + +Установите с помощью composer. + +```bash +composer require knifelemon/comment-template +``` + +## Базовая конфигурация + +Есть некоторые базовые опции конфигурации для начала работы. Вы можете прочитать больше о них в [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate). + +### Метод 1: Использование функции обратного вызова + +```php +register('view', Engine::class, [], function (Engine $engine) use ($app) { + // Где хранятся файлы шаблонов + $engine->setTemplatesPath(__DIR__ . '/views'); + + // Откуда будут обслуживаться публичные активы + $engine->setPublicPath(__DIR__ . '/public'); + + // Где будут храниться скомпилированные активы + $engine->setAssetPath('assets'); + + // Расширение файла шаблона + $engine->setFileExtension('.php'); +}); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +### Метод 2: Использование параметров конструктора + +```php +register('view', Engine::class, [ + __DIR__ . '/public', // publicPath - откуда будут обслуживаться активы + __DIR__ . '/views', // skinPath - где хранятся файлы шаблонов + 'assets', // assetPath - где будут храниться скомпилированные активы + '.php' // fileExtension - расширение файла шаблона +]); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +## Директивы шаблонов + +### Наследование макетов + +Используйте макеты для создания общей структуры: + +**layout/global_layout.php**: +```html + + + + {$title} + + + + + +``` + +**view/page.php**: +```html + +

{$title}

+

{$content}

+``` + +### Управление активами + +#### Файлы CSS +```html + + +``` + +#### Файлы JavaScript +CommentTemplate поддерживает различные стратегии загрузки JavaScript: + +```html + + + + + + + + + +``` + +#### Директивы активов в файлах CSS/JS + +CommentTemplate также обрабатывает директивы активов в файлах CSS и JavaScript во время компиляции: + +**Пример CSS:** +```css +/* В ваших файлах CSS */ +@font-face { + font-family: 'CustomFont'; + src: url('') format('woff2'); +} + +.background-image { + background: url(''); +} + +.inline-icon { + background: url(''); +} +``` + +**Пример JavaScript:** +```javascript +/* В ваших файлах JS */ +const fontUrl = ''; +const imageData = ''; +``` + +#### Кодирование Base64 +```html + +``` +** Пример: ** +```html + +Logo +
+ Маленькая иконка как фон +
+``` + +#### Копирование активов +```html + + +``` +** Пример: ** +```html + +Hero Banner +Скачать брошюру + + + + +``` + +### Включение шаблонов +```html + +``` +** Пример: ** +```html + + + +
+

Добро пожаловать на наш сайт

+ + +
+

Основной контент здесь...

+
+
+ + +``` + +### Обработка переменных + +#### Базовые переменные +```html +

{$title}

+

{$description}

+``` + +#### Фильтры переменных +```html +{$title|upper} +{$content|lower} +{$html|striptag} +{$text|escape} +{$multiline|nl2br} +{$html|br2nl} +{$description|trim} +{$subject|title} +``` + +#### Команды переменных +```html +{$title|default=Default Title} +{$name|concat= (Admin)} +``` + +#### Команды переменных +```html +{$content|striptag|trim|escape} +``` + +## Структура примера проекта + +``` +project/ +├── source/ +│ ├── layouts/ +│ │ └── default.php +│ ├── components/ +│ │ ├── header.php +│ │ └── footer.php +│ ├── css/ +│ │ ├── bootstrap.min.css +│ │ └── custom.css +│ ├── js/ +│ │ ├── app.js +│ │ └── bootstrap.min.js +│ └── homepage.php +├── public/ +│ └── assets/ # Сгенерированные активы +│ ├── css/ +│ └── js/ +└── vendor/ +``` \ No newline at end of file diff --git a/content/v3/ru/examples.md b/content/v3/ru/examples.md index 9b7ef8ad..d50aa5f7 100644 --- a/content/v3/ru/examples.md +++ b/content/v3/ru/examples.md @@ -3,23 +3,24 @@ У вас есть два варианта для начала работы с новым проектом Flight: - [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Более полный пример с контроллерами и представлениями. -- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Один файл, который включает всё необходимое для запуска вашего приложения в одном простом файле. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Один файл, содержащий всё необходимое для запуска вашего приложения в одном простом файле. Примеры, внесённые сообществом: - [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP с директориями Laravel, с инструментами PHP + GH Actions -- [fleact](https://github.com/flightphp/fleact) - Стартовый набор FlightPHP с интеграцией ReactJS. -- [flastro](https://github.com/flightphp/flastro) - Стартовый набор FlightPHP с интеграцией Astro. +- [fleact](https://github.com/flightphp/fleact) - Стартовый комплект FlightPHP с интеграцией ReactJS. +- [flastro](https://github.com/flightphp/flastro) - Стартовый комплект FlightPHP с интеграцией Astro. - [velt](https://github.com/flightphp/velt) - Velt — это быстрый и простой шаблон Svelte для старта с бэкендом на FlightPHP. -## Нужен ли вам вдохновение? +## Нужен ли вам источник вдохновения? -Хотя эти примеры не спонсируются официально командой Flight, они могут дать вам идеи о том, как структурировать свои собственные проекты, построенные на Flight! +Хотя эти проекты не спонсируются официально командой Flight, они могут дать вам идеи о том, как структурировать свои собственные проекты, построенные на Flight! -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental — это одностраничное, мобильно-дружественное веб-приложение для аренды автомобилей, построенное на PHP (FlightPHP), JavaScript и MySQL. Оно поддерживает регистрацию пользователей, просмотр и бронирование автомобилей, в то время как администраторы могут управлять автомобилями, пользователями и бронированиями. Приложение включает REST API, аутентификацию JWT и адаптивный дизайн для современного опыта аренды. +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify — это одностраничное приложение, соединяющее организаторов событий с участниками. Построено на PHP (FlightPHP), JavaScript и MySQL, с функциями JWT-аутентификации, управления событиями и документацией RESTful API с использованием OpenAPI. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental — это одностраничное, мобильно-дружественное веб-приложение для аренды автомобилей, построенное на PHP (FlightPHP), JavaScript и MySQL. Оно поддерживает регистрацию пользователей, просмотр и бронирование автомобилей, а администраторы могут управлять автомобилями, пользователями и бронированиями. Приложение включает REST API, JWT-аутентификацию и адаптивный дизайн для современного опыта аренды. - [Decay](https://github.com/boxybird/decay) - Flight v3 с HTMX и SleekDB, всё о зомби! ([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 с Middleware, Controllers, Active Record и Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Простой проект CRUD API с использованием фреймворка Flight, который предоставляет базовую структуру для новых пользователей, чтобы быстро настроить PHP-приложение с операциями CRUD и подключением к базе данных. Проект демонстрирует, как использовать Flight для разработки RESTful API, делая его идеальным инструментом для обучения новичков и полезным стартовым набором для более опытных разработчиков. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Простой проект CRUD API с использованием фреймворка Flight, который предоставляет базовую структуру для новых пользователей, чтобы быстро настроить PHP-приложение с операциями CRUD и подключением к базе данных. Проект демонстрирует, как использовать Flight для разработки RESTful API, делая его идеальным инструментом для обучения новичков и полезным стартовым комплектом для более опытных разработчиков. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -30,7 +31,7 @@ - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Готовый к производству фреймворк аутентификации, который сэкономит вам недели разработки. Функции корпоративного уровня безопасности: 2FA/TOTP, интеграция LDAP, Azure SSO, интеллектуальное ограничение скорости, отпечатки сессий, защита от brute-force, панель аналитики безопасности, всестороннее логирование аудита и гранулярный контроль доступа на основе ролей. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Готовый для производства фреймворк аутентификации, который сэкономит вам недели разработки. Функции корпоративного уровня безопасности: 2FA/TOTP, интеграция LDAP, Azure SSO, интеллектуальное ограничение скорости, отпечатки сессий, защита от brute-force, панель аналитики безопасности, всестороннее ведение логов аудита и гранулярный контроль доступа на основе ролей. ## Хотите поделиться своим примером? diff --git a/content/v3/uk/awesome-plugins/awesome_plugins.md b/content/v3/uk/awesome-plugins/awesome_plugins.md index 22a05c79..545434b5 100644 --- a/content/v3/uk/awesome-plugins/awesome_plugins.md +++ b/content/v3/uk/awesome-plugins/awesome_plugins.md @@ -1,95 +1,96 @@ # Круті Плагіни -Flight є надзвичайно розширюваним. Існує низка плагінів, які можна використовувати для додавання функціональності до вашої програми Flight. Деякі з них офіційно підтримуються командою Flight, а інші є мікро/лайт бібліотеками, щоб допомогти вам розпочати. +Flight є надзвичайно розширюваним. Існує низка плагінів, які можна використовувати для додавання функціональності до вашого додатка Flight. Деякі з них офіційно підтримуються командою Flight, а інші є мікро/лайт бібліотеками, щоб допомогти вам розпочати. ## Документація API -Документація API є критичною для будь-якого API. Вона допомагає розробникам зрозуміти, як взаємодіяти з вашим API та що очікувати у відповідь. Існує кілька інструментів, доступних для допомоги у генерації документації API для ваших проектів Flight. +Документація API є ключовою для будь-якого API. Вона допомагає розробникам зрозуміти, як взаємодіяти з вашим API та що очікувати натомість. Існує кілька інструментів, доступних для допомоги у генерації документації API для ваших проєктів Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Публікація в блозі, написана Даніелем Шрайбером, про те, як використовувати специфікацію OpenAPI з FlightPHP для побудови вашого API з використанням підходу API first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI є чудовим інструментом для допомоги у генерації документації API для ваших проектів Flight. Його дуже легко використовувати, і його можна налаштувати відповідно до ваших потреб. Це PHP-бібліотека для допомоги у генерації документації Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Блог-пост, написаний Даніелем Шрайбером, про те, як використовувати специфікацію OpenAPI з FlightPHP для побудови вашого API з використанням підходу API first. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI є чудовим інструментом для допомоги у генерації документації API для ваших проєктів Flight. Його дуже легко використовувати, і його можна налаштувати відповідно до ваших потреб. Це PHP-бібліотека для допомоги у генерації документації Swagger. -## Моніторинг Продуктивності Застосунку (APM) +## Моніторинг продуктивності додатків (APM) -Моніторинг продуктивності застосунку (APM) є критичним для будь-якого застосунку. Він допомагає вам зрозуміти, як працює ваш застосунок і де знаходяться вузькі місця. Існує низка інструментів APM, які можна використовувати з Flight. -- офіційний [flightphp/apm](/awesome-plugins/apm) - Flight APM є простою бібліотекою APM, яка може використовуватися для моніторингу ваших програм Flight. Її можна використовувати для моніторингу продуктивності вашого застосунку та допомоги у виявленні вузьких місць. +Моніторинг продуктивності додатків (APM) є ключовим для будь-якого додатка. Він допомагає вам зрозуміти, як працює ваш додаток і де знаходяться вузькі місця. Існує низка інструментів APM, які можна використовувати з Flight. +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM є простою бібліотекою APM, яка може бути використана для моніторингу ваших додатків Flight. Її можна використовувати для моніторингу продуктивності вашого додатка та допомоги у виявленні вузьких місць. ## Асинхронність -Flight вже є швидким фреймворком, але додавання до нього турбо-двигуна робить усе ще веселішим (і складнішим)! +Flight вже є швидким фреймворком, але додавання до нього турбо-двигуна робить все ще веселішим (і складнішим)! -- [flightphp/async](/awesome-plugins/async) - Офіційна бібліотека Flight Async. Ця бібліотека є простим способом додати асинхронну обробку до вашого застосунку. Вона використовує Swoole/Openswoole під капотом, щоб надати простий та ефективний спосіб запуску завдань асинхронно. +- [flightphp/async](/awesome-plugins/async) - Офіційна бібліотека Flight Async. Ця бібліотека є простим способом додати асинхронну обробку до вашого додатка. Вона використовує Swoole/Openswoole під капотом, щоб надати простий та ефективний спосіб запуску завдань асинхронно. ## Авторизація/Дозволи -Авторизація та дозволи є критичними для будь-якого застосунку, який вимагає контролю за тим, хто може отримати доступ до чого. +Авторизація та дозволи є ключовими для будь-якого додатка, який вимагає контролю за тим, хто може отримати доступ до чого. -- офіційний [flightphp/permissions](/awesome-plugins/permissions) - Офіційна бібліотека Flight Permissions. Ця бібліотека є простим способом додати дозволи на рівні користувача та застосунку до вашого застосунку. +- official [flightphp/permissions](/awesome-plugins/permissions) - Офіційна бібліотека Flight Permissions. Ця бібліотека є простим способом додати дозволи на рівні користувача та додатка до вашого додатка. ## Кешування -Кешування є чудовим способом прискорити ваш застосунок. Існує низка бібліотек кешування, які можна використовувати з Flight. +Кешування є чудовим способом прискорити ваш додаток. Існує низка бібліотек кешування, які можна використовувати з Flight. -- офіційний [flightphp/cache](/awesome-plugins/php-file-cache) - Легка, проста та автономна PHP-клас кешування в файлі +- official [flightphp/cache](/awesome-plugins/php-file-cache) - Легка, проста та автономна PHP-клас для кешування в файлі ## CLI -CLI-застосунки є чудовим способом взаємодіяти з вашим застосунком. Ви можете використовувати їх для генерації контролерів, відображення всіх маршрутів та багато іншого. +CLI-додатки є чудовим способом взаємодіяти з вашим додатком. Їх можна використовувати для генерації контролерів, відображення всіх маршрутів та багато іншого. -- офіційний [flightphp/runway](/awesome-plugins/runway) - Runway є CLI-застосунком, який допомагає вам керувати вашими програмами Flight. +- official [flightphp/runway](/awesome-plugins/runway) - Runway є CLI-додатком, який допомагає вам керувати вашими додатками Flight. ## Куки -Куки є чудовим способом зберігати малі шматки даних на стороні клієнта. Їх можна використовувати для зберігання уподобань користувача, налаштувань застосунку та багато іншого. +Кукі є чудовим способом зберігати невеликі обсяги даних на стороні клієнта. Їх можна використовувати для зберігання уподобань користувача, налаштувань додатка та багато іншого. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie є PHP-бібліотекою, яка надає простий та ефективний спосіб керування куками. ## Налагодження -Налагодження є критичним, коли ви розробляєте у локальному середовищі. Існує кілька плагінів, які можуть покращити ваш досвід налагодження. +Налагодження є ключовим під час розробки у вашому локальному середовищі. Існує кілька плагінів, які можуть покращити ваш досвід налагодження. -- [tracy/tracy](/awesome-plugins/tracy) - Це повнофункціональний обробник помилок, який можна використовувати з Flight. Він має низку панелей, які можуть допомогти вам налагоджувати ваш застосунок. Його також дуже легко розширювати та додавати власні панелі. -- офіційний [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Використовується з обробником помилок [Tracy](/awesome-plugins/tracy), цей плагін додає кілька додаткових панелей для допомоги з налагодженням спеціально для проектів Flight. +- [tracy/tracy](/awesome-plugins/tracy) - Це повнофункціональний обробник помилок, який можна використовувати з Flight. Він має низку панелей, які можуть допомогти вам налагоджувати ваш додаток. Його також дуже легко розширювати та додавати власні панелі. +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Використовується з обробником помилок [Tracy](/awesome-plugins/tracy), цей плагін додає кілька додаткових панелей для допомоги з налагодженням, спеціально для проєктів Flight. -## Бази Даних +## Бази даних -Бази даних є основою для більшості застосунків. Це спосіб зберігати та отримувати дані. Деякі бібліотеки баз даних є просто обгортками для написання запитів, а деякі є повноцінними ORM. +Бази даних є основою для більшості додатків. Це спосіб зберігати та отримувати дані. Деякі бібліотеки баз даних є просто обгортками для написання запитів, а деякі є повноцінними ORM. -- офіційний [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Офіційний обгорт Flight PDO, який є частиною ядра. Це проста обгортка, щоб спростити процес написання запитів та їх виконання. Це не ORM. -- офіційний [flightphp/active-record](/awesome-plugins/active-record) - Офіційний ORM/Mapper Flight ActiveRecord. Чудова маленька бібліотека для легкого отримання та зберігання даних у вашій базі даних. -- [byjg/php-migration](/awesome-plugins/migrations) - Плагін для відстеження всіх змін бази даних для вашого проекту. +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Офіційний обгорт Flight PDO Wrapper, який є частиною ядра. Це проста обгортка для спрощення процесу написання запитів та їх виконання. Це не ORM. +- official [flightphp/active-record](/awesome-plugins/active-record) - Офіційний ORM/Mapper Flight ActiveRecord. Чудова маленька бібліотека для легкого отримання та зберігання даних у вашій базі даних. +- [byjg/php-migration](/awesome-plugins/migrations) - Плагін для відстеження всіх змін бази даних для вашого проєкту. ## Шифрування -Шифрування є критичним для будь-якого застосунку, який зберігає чутливі дані. Шифрування та дешифрування даних не є надто складним, але правильне зберігання ключа шифрування [може](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [бути](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [складним](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Найважливіше — ніколи не зберігати ключ шифрування в публічній директорії або комітити його до вашого репозиторію коду. +Шифрування є ключовим для будь-якого додатка, який зберігає чутливі дані. Шифрування та дешифрування даних не є надто складними, але правильне зберігання ключа шифрування [може](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [бути](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [складним](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Найважливіше — ніколи не зберігати ключ шифрування в публічній директорії або комітити його до вашого репозиторію коду. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Це бібліотека, яка може використовуватися для шифрування та дешифрування даних. Запуск та налаштування є досить простим для початку шифрування та дешифрування даних. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - Це бібліотека, яка може бути використана для шифрування та дешифрування даних. Запуск та налагодження є досить простими для початку шифрування та дешифрування даних. -## Черга Завдань +## Черга завдань Черги завдань дійсно корисні для асинхронної обробки завдань. Це може бути відправка email, обробка зображень або будь-що, що не потребує виконання в реальному часі. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue є бібліотекою, яка може використовуватися для асинхронної обробки завдань. Її можна використовувати з beanstalkd, MySQL/MariaDB, SQLite та PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue є бібліотекою, яка може бути використана для асинхронної обробки завдань. Її можна використовувати з beanstalkd, MySQL/MariaDB, SQLite та PostgreSQL. ## Сесії -Сесії не дуже корисні для API, але для побудови веб-застосунку сесії можуть бути критичними для підтримки стану та інформації про вхід. +Сесії не дуже корисні для API, але для побудови веб-додатка сесії можуть бути ключовими для підтримки стану та інформації про вхід. -- офіційний [flightphp/session](/awesome-plugins/session) - Офіційна бібліотека Flight Session. Це проста бібліотека сесій, яка може використовуватися для зберігання та отримання даних сесії. Вона використовує вбудоване керування сесіями PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (неблокуючий, flash, сегмент, шифрування сесії). Використовує PHP open_ssl для необов'язкового шифрування/дешифрування даних сесії. +- official [flightphp/session](/awesome-plugins/session) - Офіційна бібліотека Flight Session. Це проста бібліотека сесій, яка може бути використана для зберігання та отримання даних сесії. Вона використовує вбудовану обробку сесій PHP. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (неблокуючий, flash, сегмент, шифрування сесії). Використовує PHP open_ssl для опціонального шифрування/дешифрування даних сесії. ## Шаблонізація -Шаблонізація є основою для будь-якого веб-застосунку з UI. Існує низка рушіїв шаблонізації, які можна використовувати з Flight. +Шаблонізація є основою для будь-якого веб-додатка з UI. Існує низка шаблонних двигунів, які можна використовувати з Flight. -- застарілий [flightphp/core View](/learn#views) - Це дуже базовий рушій шаблонізації, який є частиною ядра. Не рекомендується використовувати, якщо у вашому проекті більше кількох сторінок. -- [latte/latte](/awesome-plugins/latte) - Latte є повнофункціональним рушієм шаблонізації, який дуже легко використовувати та відчувається ближчим до синтаксису PHP, ніж Twig чи Smarty. Його також дуже легко розширювати та додавати власні фільтри та функції. +- deprecated [flightphp/core View](/learn#views) - Це дуже базовий шаблонний двигун, який є частиною ядра. Не рекомендується використовувати, якщо у вашому проєкті більше кількох сторінок. +- [latte/latte](/awesome-plugins/latte) - Latte є повнофункціональним шаблонним двигуном, який дуже легко використовувати та ближчий до синтаксису PHP, ніж Twig чи Smarty. Його також дуже легко розширювати та додавати власні фільтри та функції. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate є потужним PHP-шаблонним двигуном з компіляцією активів, спадкуванням шаблонів та обробкою змінних. Має автоматичну мініфікацію CSS/JS, кешування, кодування Base64 та опціональну інтеграцію з фреймворком Flight PHP. ## Інтеграція з WordPress -Хочете використовувати Flight у вашому проекті WordPress? Є зручний плагін для цього! +Хочете використовувати Flight у вашому проєкті WordPress? Є зручний плагін для цього! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Цей плагін WordPress дозволяє запускати Flight поруч з WordPress. Він ідеальний для додавання кастомних API, мікросервісів або навіть повноцінних застосунків до вашого сайту WordPress з використанням фреймворку Flight. Надзвичайно корисний, якщо ви хочете найкраще з обох світів! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Цей плагін WordPress дозволяє запускати Flight прямо поруч з WordPress. Він ідеальний для додавання кастомних API, мікросервісів або навіть повноцінних додатків до вашого сайту WordPress з використанням фреймворку Flight. Надзвичайно корисний, якщо ви хочете найкраще з обох світів! ## Внесок diff --git a/content/v3/uk/awesome-plugins/comment_template.md b/content/v3/uk/awesome-plugins/comment_template.md new file mode 100644 index 00000000..236d9c25 --- /dev/null +++ b/content/v3/uk/awesome-plugins/comment_template.md @@ -0,0 +1,257 @@ +# CommentTemplate + +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) — потужний рушій шаблонів PHP з компіляцією активів, успадкуванням шаблонів та обробкою змінних. Він надає простий, але гнучкий спосіб керування шаблонами з вбудованою мініфікацією CSS/JS та кешуванням. + +## Особливості + +- **Успадкування шаблонів**: Використовуйте макети та включайте інші шаблони +- **Компіляція активів**: Автоматична мініфікація CSS/JS та кешування +- **Обробка змінних**: Змінні шаблонів з фільтрами та командами +- **Кодування Base64**: Вбудовані активи як data URI +- **Інтеграція з Flight Framework**: Опціональна інтеграція з PHP фреймворком Flight + +## Встановлення + +Встановіть за допомогою composer. + +```bash +composer require knifelemon/comment-template +``` + +## Базова конфігурація + +Є деякі базові опції конфігурації для початку. Ви можете прочитати більше про них у [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate). + +### Метод 1: Використання функції зворотного виклику + +```php +register('view', Engine::class, [], function (Engine $engine) use ($app) { + // Де зберігаються ваші файли шаблонів + $engine->setTemplatesPath(__DIR__ . '/views'); + + // Де ваші публічні активи будуть обслуговуватися + $engine->setPublicPath(__DIR__ . '/public'); + + // Де зберігатимуться скомпільовані активи + $engine->setAssetPath('assets'); + + // Розширення файлу шаблону + $engine->setFileExtension('.php'); +}); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +### Метод 2: Використання параметрів конструктора + +```php +register('view', Engine::class, [ + __DIR__ . '/public', // publicPath - де активи будуть обслуговуватися + __DIR__ . '/views', // skinPath - де зберігаються файли шаблонів + 'assets', // assetPath - де зберігатимуться скомпільовані активи + '.php' // fileExtension - розширення файлу шаблону +]); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +## Директиви шаблонів + +### Успадкування макетів + +Використовуйте макети для створення спільної структури: + +**layout/global_layout.php**: +```html + + + + {$title} + + + + + +``` + +**view/page.php**: +```html + +

{$title}

+

{$content}

+``` + +### Керування активами + +#### Файли CSS +```html + + +``` + +#### Файли JavaScript +CommentTemplate підтримує різні стратегії завантаження JavaScript: + +```html + + + + + + + + + +``` + +#### Директиви активів у файлах CSS/JS + +CommentTemplate також обробляє директиви активів у CSS та JavaScript файлах під час компіляції: + +**Приклад CSS:** +```css +/* У ваших CSS файлах */ +@font-face { + font-family: 'CustomFont'; + src: url('') format('woff2'); +} + +.background-image { + background: url(''); +} + +.inline-icon { + background: url(''); +} +``` + +**Приклад JavaScript:** +```javascript +/* У ваших JS файлах */ +const fontUrl = ''; +const imageData = ''; +``` + +#### Кодування Base64 +```html + +``` +** Приклад: ** +```html + +Logo +
+ Маленька іконка як фон +
+``` + +#### Копіювання активів +```html + + +``` +** Приклад: ** +```html + +Hero Banner +Завантажити Брошуру + + + + +``` + +### Включення шаблонів +```html + +``` +** Приклад: ** +```html + + + +
+

Ласкаво просимо на наш веб-сайт

+ + +
+

Основний контент тут...

+
+
+ + +``` + +### Обробка змінних + +#### Базові змінні +```html +

{$title}

+

{$description}

+``` + +#### Фільтри змінних +```html +{$title|upper} +{$content|lower} +{$html|striptag} +{$text|escape} +{$multiline|nl2br} +{$html|br2nl} +{$description|trim} +{$subject|title} +``` + +#### Команди змінних +```html +{$title|default=Default Title} +{$name|concat= (Admin)} +``` + +#### Команди змінних +```html +{$content|striptag|trim|escape} +``` + +## Приклад структури проекту + +``` +project/ +├── source/ +│ ├── layouts/ +│ │ └── default.php +│ ├── components/ +│ │ ├── header.php +│ │ └── footer.php +│ ├── css/ +│ │ ├── bootstrap.min.css +│ │ └── custom.css +│ ├── js/ +│ │ ├── app.js +│ │ └── bootstrap.min.js +│ └── homepage.php +├── public/ +│ └── assets/ # Згенеровані активи +│ ├── css/ +│ └── js/ +└── vendor/ +``` \ No newline at end of file diff --git a/content/v3/uk/examples.md b/content/v3/uk/examples.md index 415d826a..56ecfe79 100644 --- a/content/v3/uk/examples.md +++ b/content/v3/uk/examples.md @@ -3,23 +3,24 @@ У вас є два варіанти для початку роботи з новим проектом Flight: - [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Більш повноцінний приклад з контролерами та видами. -- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Один файл, що містить усе необхідне для запуску вашого додатка в одному простому файлі. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Один файл, що включає все необхідне для запуску вашого додатка в одному простому файлі. Приклади, надані спільнотою: - [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP з директоріями Laravel, з інструментами PHP + GH Actions -- [fleact](https://github.com/flightphp/fleact) - Стартові набір FlightPHP з інтеграцією ReactJS. -- [flastro](https://github.com/flightphp/flastro) - Стартові набір FlightPHP з інтеграцією Astro. -- [velt](https://github.com/flightphp/velt) - Velt — це швидкий і простий шаблон Svelte з бекендом на FlightPHP. +- [fleact](https://github.com/flightphp/fleact) - Стартер-кіт FlightPHP з інтеграцією ReactJS. +- [flastro](https://github.com/flightphp/flastro) - Стартер-кіт FlightPHP з інтеграцією Astro. +- [velt](https://github.com/flightphp/velt) - Velt — це швидкий і простий шаблон стартера Svelte з бекендом FlightPHP. ## Потрібне натхнення? -Хоча ці приклади не спонсоровані офіційно командою Flight, вони можуть дати вам ідеї щодо структуризації власних проектів, побудованих на Flight! +Хоча ці приклади не є офіційно спонсорованими командою Flight, вони можуть дати вам ідеї щодо структуризації власних проектів, побудованих на Flight! +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify — це односторінковий додаток, що з'єднує організаторів подій з учасниками. Побудований на PHP (FlightPHP), JavaScript та MySQL, з JWT-аутентифікацією, керуванням подіями та документацією RESTful API за допомогою OpenAPI. - [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental — це односторінковий, мобільно-дружній веб-додаток для оренди автомобілів, побудований на PHP (FlightPHP), JavaScript та MySQL. Він підтримує реєстрацію користувачів, перегляд та бронювання автомобілів, тоді як адміністратори можуть керувати автомобілями, користувачами та бронюваннями. Додаток має REST API, JWT-аутентифікацію та адаптивний дизайн для сучасного досвіду оренди. - [Decay](https://github.com/boxybird/decay) - Flight v3 з HTMX та SleekDB, все про зомбі! ([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 з Middleware, Controllers, Active Record та Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Простий проект CRUD API з використанням фреймворку Flight, який надає базову структуру для нових користувачів, щоб швидко налаштувати PHP-додаток з операціями CRUD та підключенням до бази даних. Проект демонструє, як використовувати Flight для розробки RESTful API, роблячи його ідеальним навчальним інструментом для початківців та корисним стартовим набором для більш досвідчених розробників. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Простий проект CRUD API з використанням фреймворку Flight, який надає базову структуру для нових користувачів, щоб швидко налаштувати PHP-додаток з операціями CRUD та підключенням до бази даних. Проект демонструє, як використовувати Flight для розробки RESTful API, роблячи його ідеальним інструментом для навчання для початківців та корисним стартер-кітом для більш досвідчених розробників. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -30,7 +31,7 @@ - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Готовий до виробництва фреймворк аутентифікації, який заощаджує тижні розробки. Функції корпоративного рівня безпеки: 2FA/TOTP, інтеграція LDAP, Azure SSO, інтелектуальне обмеження швидкості, відбитки сесій, захист від brute-force, панель аналітики безпеки, всебічний аудит-логування та гранульний контроль доступу на основі ролей. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Готовий до виробництва фреймворк аутентифікації, що заощаджує тижні розробки. Функції корпоративного рівня безпеки: 2FA/TOTP, інтеграція LDAP, Azure SSO, інтелектуальне обмеження швидкості, відбиток сесії, захист від brute-force, панель аналітики безпеки, всебічний аудит-логування та гранульований контроль доступу на основі ролей. ## Хочете поділитися своїм прикладом? diff --git a/content/v3/zh/awesome-plugins/awesome_plugins.md b/content/v3/zh/awesome-plugins/awesome_plugins.md index fc6415de..34042188 100644 --- a/content/v3/zh/awesome-plugins/awesome_plugins.md +++ b/content/v3/zh/awesome-plugins/awesome_plugins.md @@ -1,30 +1,30 @@ -# 精彩插件 +# 优秀的插件 -Flight 极具可扩展性。有许多插件可用于为您的 Flight 应用程序添加功能。其中一些由 Flight 团队正式支持,其他则是帮助您入门的小型/轻量级库。 +Flight 具有极强的可扩展性。有许多插件可用于为您的 Flight 应用程序添加功能。其中一些由 Flight 团队官方支持,其他则是一些微型/轻量级库,帮助您快速上手。 ## API 文档 -API 文档对任何 API 都至关重要。它帮助开发者理解如何与您的 API 交互以及期望返回的内容。有几个工具可用于帮助您为 Flight 项目生成 API 文档。 +API 文档对于任何 API 都至关重要。它帮助开发者理解如何与您的 API 交互以及预期返回结果。有几个工具可用于帮助您为 Flight 项目生成 API 文档。 -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - 由 Daniel Schreiber 撰写的博客文章,介绍如何使用 OpenAPI 规范与 FlightPHP 结合,以 API 优先方法构建您的 API。 +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - 由 Daniel Schreiber 撰写的博客文章,介绍如何使用 OpenAPI 规范与 FlightPHP 结合,采用 API 优先方法构建您的 API。 - [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI 是一个优秀的工具,可帮助您为 Flight 项目生成 API 文档。它非常易用,并且可以自定义以满足您的需求。这是用于生成 Swagger 文档的 PHP 库。 ## 应用程序性能监控 (APM) -应用程序性能监控 (APM) 对任何应用程序都至关重要。它帮助您了解应用程序的性能以及瓶颈所在。有许多 APM 工具可与 Flight 一起使用。 +应用程序性能监控 (APM) 对于任何应用程序都至关重要。它帮助您了解应用程序的性能表现以及瓶颈所在。有许多 APM 工具可与 Flight 一起使用。 - official [flightphp/apm](/awesome-plugins/apm) - Flight APM 是一个简单的 APM 库,可用于监控您的 Flight 应用程序。它可用于监控应用程序性能并帮助您识别瓶颈。 ## 异步 -Flight 已经是一个快速的框架,但为其添加涡轮引擎会让一切变得更有趣(且具挑战性)! +Flight 已经是一个快速的框架,但为其添加涡轮引擎会让一切变得更有趣(且更具挑战性)! -- [flightphp/async](/awesome-plugins/async) - 官方 Flight Async 库。此库是一种简单的方式,可为您的应用程序添加异步处理。它在底层使用 Swoole/Openswoole,提供简单有效的任务异步运行方式。 +- [flightphp/async](/awesome-plugins/async) - 官方 Flight Async 库。此库是一种简单的方式,为您的应用程序添加异步处理。它在底层使用 Swoole/Openswoole,提供简单有效的异步运行任务的方法。 ## 授权/权限 -授权和权限对任何需要控制访问权限的应用程序都至关重要。 +授权和权限对于任何需要控制访问权限的应用程序都至关重要。 -- official [flightphp/permissions](/awesome-plugins/permissions) - 官方 Flight Permissions 库。此库是一种简单的方式,可为您的应用程序添加用户和应用程序级别的权限。 +- official [flightphp/permissions](/awesome-plugins/permissions) - 官方 Flight Permissions 库。此库是一种简单的方式,为您的应用程序添加用户和应用程序级别的权限。 ## 缓存 @@ -42,54 +42,55 @@ CLI 应用程序是与您的应用程序交互的绝佳方式。您可以使用 Cookies 是存储客户端小量数据的绝佳方式。它们可用于存储用户偏好、应用程序设置等。 -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie 是一个 PHP 库,提供简单有效的 cookies 管理方式。 +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie 是一个 PHP 库,提供简单有效的方式来管理 cookies。 ## 调试 在本地环境中开发时,调试至关重要。有几个插件可以提升您的调试体验。 -- [tracy/tracy](/awesome-plugins/tracy) - 这是一个功能齐全的错误处理程序,可与 Flight 一起使用。它有多个面板可帮助您调试应用程序。它也非常易于扩展并添加您自己的面板。 -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - 与 [Tracy](/awesome-plugins/tracy) 错误处理程序一起使用,此插件添加了一些额外的面板,专门帮助调试 Flight 项目。 +- [tracy/tracy](/awesome-plugins/tracy) - 这是一个功能齐全的错误处理器,可与 Flight 一起使用。它有多个面板可帮助您调试应用程序。它也非常易于扩展并添加您自己的面板。 +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - 与 [Tracy](/awesome-plugins/tracy) 错误处理器一起使用,此插件添加了一些额外的面板,专门帮助调试 Flight 项目。 ## 数据库 数据库是大多数应用程序的核心。这是存储和检索数据的方式。有些数据库库只是用于编写查询的包装器,有些则是完整的 ORM。 - official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 官方 Flight PDO Wrapper,是核心的一部分。这是一个简单的包装器,帮助简化编写和执行查询的过程。它不是 ORM。 -- official [flightphp/active-record](/awesome-plugins/active-record) - 官方 Flight ActiveRecord ORM/Mapper。优秀的库,用于轻松检索和存储数据库中的数据。 -- [byjg/php-migration](/awesome-plugins/migrations) - 用于跟踪项目所有数据库变更的插件。 +- official [flightphp/active-record](/awesome-plugins/active-record) - 官方 Flight ActiveRecord ORM/Mapper。一个优秀的库,用于轻松检索和存储数据库中的数据。 +- [byjg/php-migration](/awesome-plugins/migrations) - 用于跟踪项目中所有数据库更改的插件。 ## 加密 -加密对任何存储敏感数据的应用程序都至关重要。加密和解密数据并不太难,但正确存储加密密钥 [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [会](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [困难](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)。最重要的是,切勿将加密密钥存储在公共目录中或提交到代码仓库。 +对于任何存储敏感数据的应用程序,加密至关重要。加密和解密数据并不难,但正确存储加密密钥 [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [会](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [困难](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)。最重要的是,切勿将加密密钥存储在公共目录中或提交到您的代码仓库。 - [defuse/php-encryption](/awesome-plugins/php-encryption) - 这是一个可用于加密和解密数据的库。启动并运行非常简单,即可开始加密和解密数据。 ## 作业队列 -作业队列对于异步处理任务非常有帮助。这可以包括发送电子邮件、处理图像或任何不需要实时完成的任务。 +作业队列对于异步处理任务非常有用。这可以是发送电子邮件、处理图像,或任何不需要实时完成的任务。 -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue 是一个库,可用于异步处理作业。它可与 beanstalkd、MySQL/MariaDB、SQLite 和 PostgreSQL 一起使用。 +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue 是一个可用于异步处理作业的库。它可与 beanstalkd、MySQL/MariaDB、SQLite 和 PostgreSQL 一起使用。 ## 会话 会话对于 API 并不太有用,但对于构建 Web 应用程序,会话对于维护状态和登录信息至关重要。 - official [flightphp/session](/awesome-plugins/session) - 官方 Flight Session 库。这是一个简单的会话库,可用于存储和检索会话数据。它使用 PHP 内置的会话处理。 -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager(非阻塞、闪存、分段、会话加密)。使用 PHP open_ssl 进行可选的会话数据加密/解密。 +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 会话管理器(非阻塞、闪存、段、会话加密)。使用 PHP open_ssl 可选地加密/解密会话数据。 ## 模板 模板是任何具有 UI 的 Web 应用程序的核心。有许多模板引擎可与 Flight 一起使用。 -- deprecated [flightphp/core View](/learn#views) - 这是一个非常基本的模板引擎,是核心的一部分。如果您的项目有超过几页,不推荐使用。 +- deprecated [flightphp/core View](/learn#views) - 这是一个非常基本的模板引擎,是核心的一部分。如果您的项目超过几个页面,不推荐使用。 - [latte/latte](/awesome-plugins/latte) - Latte 是一个功能齐全的模板引擎,非常易用,其语法比 Twig 或 Smarty 更接近 PHP。它也非常易于扩展并添加您自己的过滤器和函数。 +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate 是一个强大的 PHP 模板引擎,支持资产生成、模板继承和变量处理。具有自动 CSS/JS 压缩、缓存、Base64 编码,以及可选的 Flight PHP 框架集成。 ## WordPress 集成 想在您的 WordPress 项目中使用 Flight 吗?有一个方便的插件可供使用! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 此 WordPress 插件允许您在 WordPress 旁边运行 Flight。它非常适合使用 Flight 框架为您的 WordPress 站点添加自定义 API、微服务,甚至完整应用程序。如果您想兼得两者的优点,这超级有用! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 此 WordPress 插件让您可以与 WordPress 并行运行 Flight。它非常适合使用 Flight 框架为您的 WordPress 站点添加自定义 API、微服务,甚至完整应用程序。如果您想兼得两者的优点,这超级有用! ## 贡献 diff --git a/content/v3/zh/awesome-plugins/comment_template.md b/content/v3/zh/awesome-plugins/comment_template.md new file mode 100644 index 00000000..ae0a701e --- /dev/null +++ b/content/v3/zh/awesome-plugins/comment_template.md @@ -0,0 +1,257 @@ +# CommentTemplate + +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) 是一个强大的 PHP 模板引擎,具有资产生成、模板继承和变量处理功能。它提供了一种简单而灵活的管理模板的方式,内置 CSS/JS 压缩和缓存。 + +## 功能 + +- **模板继承**:使用布局并包含其他模板 +- **资产生成**:自动 CSS/JS 压缩和缓存 +- **变量处理**:带有过滤器和命令的模板变量 +- **Base64 编码**:将内联资产生成为数据 URI +- **Flight 框架集成**:与 Flight PHP 框架的可选集成 + +## 安装 + +使用 Composer 安装。 + +```bash +composer require knifelemon/comment-template +``` + +## 基本配置 + +有一些基本的配置选项来开始使用。您可以在 [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate) 中阅读更多关于它们的信息。 + +### 方法 1:使用回调函数 + +```php +register('view', Engine::class, [], function (Engine $engine) use ($app) { + // 模板文件存储的位置 + $engine->setTemplatesPath(__DIR__ . '/views'); + + // 公共资产服务的路径 + $engine->setPublicPath(__DIR__ . '/public'); + + // 编译资产的存储位置 + $engine->setAssetPath('assets'); + + // 模板文件扩展名 + $engine->setFileExtension('.php'); +}); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +### 方法 2:使用构造函数参数 + +```php +register('view', Engine::class, [ + __DIR__ . '/public', // publicPath - 资产服务的路径 + __DIR__ . '/views', // skinPath - 模板文件存储的位置 + 'assets', // assetPath - 编译资产的存储位置 + '.php' // fileExtension - 模板文件扩展名 +]); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +## 模板指令 + +### 布局继承 + +使用布局来创建共同结构: + +**layout/global_layout.php**: +```html + + + + {$title} + + + + + +``` + +**view/page.php**: +```html + +

{$title}

+

{$content}

+``` + +### 资产管理 + +#### CSS 文件 +```html + + +``` + +#### JavaScript 文件 +CommentTemplate 支持不同的 JavaScript 加载策略: + +```html + + + + + + + + + +``` + +#### CSS/JS 文件中的资产指令 + +CommentTemplate 还在编译期间处理 CSS 和 JavaScript 文件中的资产指令: + +**CSS 示例:** +```css +/* 在您的 CSS 文件中 */ +@font-face { + font-family: 'CustomFont'; + src: url('') format('woff2'); +} + +.background-image { + background: url(''); +} + +.inline-icon { + background: url(''); +} +``` + +**JavaScript 示例:** +```javascript +/* 在您的 JS 文件中 */ +const fontUrl = ''; +const imageData = ''; +``` + +#### Base64 编码 +```html + +``` +** 示例: ** +```html + +Logo +
+ 小图标作为背景 +
+``` + +#### 资产复制 +```html + + +``` +** 示例: ** +```html + +Hero Banner +下载宣传册 + + + + +``` + +### 模板包含 +```html + +``` +** 示例: ** +```html + + + +
+

欢迎访问我们的网站

+ + +
+

主要内容在这里...

+
+
+ + +``` + +### 变量处理 + +#### 基本变量 +```html +

{$title}

+

{$description}

+``` + +#### 变量过滤器 +```html +{$title|upper} +{$content|lower} +{$html|striptag} +{$text|escape} +{$multiline|nl2br} +{$html|br2nl} +{$description|trim} +{$subject|title} +``` + +#### 变量命令 +```html +{$title|default=Default Title} +{$name|concat= (Admin)} +``` + +#### 变量命令 +```html +{$content|striptag|trim|escape} +``` + +## 示例项目结构 + +``` +project/ +├── source/ +│ ├── layouts/ +│ │ └── default.php +│ ├── components/ +│ │ ├── header.php +│ │ └── footer.php +│ ├── css/ +│ │ ├── bootstrap.min.css +│ │ └── custom.css +│ ├── js/ +│ │ ├── app.js +│ │ └── bootstrap.min.js +│ └── homepage.php +├── public/ +│ └── assets/ # 生成的资产 +│ ├── css/ +│ └── js/ +└── vendor/ +``` \ No newline at end of file diff --git a/content/v3/zh/examples.md b/content/v3/zh/examples.md index 4bf23702..01a02082 100644 --- a/content/v3/zh/examples.md +++ b/content/v3/zh/examples.md @@ -1,9 +1,9 @@ -# 需要快速开始吗? +# 需要快速入门吗? 您有两种选项来开始一个新的 Flight 项目: - [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton):一个更完整的示例,包括控制器和视图。 -- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple):一个单一文件,包含运行您的应用程序所需的一切,简单易用。 +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple):一个单一文件,包含运行您的应用所需的一切,简单易用。 社区贡献的示例: @@ -16,10 +16,11 @@ 虽然这些并非由 Flight 团队正式赞助,但它们可以为您构建基于 Flight 的项目提供结构思路! -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental 是一个单页、移动友好的汽车租赁 Web 应用程序,使用 PHP (FlightPHP)、JavaScript 和 MySQL 构建。它支持用户注册、浏览和预订汽车,而管理员可以管理汽车、用户和预订。该应用程序具有 REST API、JWT 认证和响应式设计,提供现代租赁体验。 +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify 是一个单页应用,将活动组织者与参与者连接起来。使用 PHP (FlightPHP)、JavaScript 和 MySQL 构建,具有 JWT 认证、活动管理以及使用 OpenAPI 的 RESTful API 文档。 +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental 是一个单页、移动友好的租车网络应用,使用 PHP (FlightPHP)、JavaScript 和 MySQL 构建。它支持用户注册、浏览和预订车辆,而管理员可以管理车辆、用户和预订。该应用具有 REST API、JWT 认证以及响应式设计,提供现代租车体验。 - [Decay](https://github.com/boxybird/decay) - Flight v3 与 HTMX 和 SleekDB 结合,全是关于僵尸的!([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 带有中间件、控制器、Active Record 和 Latte。 -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - 使用 Flight 框架的简单 CRUD API 项目,为新用户提供基本结构,快速设置带有 CRUD 操作和数据库连接的 PHP 应用程序。该项目演示了如何使用 Flight 进行 RESTful API 开发,是初学者理想的学习工具,也是经验丰富的开发者的有用启动套件。 +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - 使用 Flight 框架的简单 CRUD API 项目,为新用户提供基本结构,以便快速设置带有 CRUD 操作和数据库连接的 PHP 应用。该项目演示了如何使用 Flight 进行 RESTful API 开发,是初学者理想的学习工具,也是经验丰富的开发者的有用启动套件。 - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) From cab4b74bc76e01dc399d9d9997ca41bf51fa77a2 Mon Sep 17 00:00:00 2001 From: KnifeLemon Date: Wed, 22 Oct 2025 16:18:14 +0900 Subject: [PATCH 16/36] docs: Update CommentTemplate documentation across all languages --- .../v3/de/awesome-plugins/comment_template.md | 117 ++++++++++++-- .../v3/en/awesome-plugins/comment_template.md | 115 ++++++++++++-- .../v3/es/awesome-plugins/comment_template.md | 117 ++++++++++++-- .../v3/fr/awesome-plugins/comment_template.md | 117 ++++++++++++-- .../v3/id/awesome-plugins/comment_template.md | 107 ++++++++++++- .../v3/ja/awesome-plugins/comment_template.md | 149 +++++++++++++++++- .../v3/ko/awesome-plugins/comment_template.md | 117 ++++++++++++-- .../v3/lv/awesome-plugins/comment_template.md | 117 ++++++++++++-- .../v3/pt/awesome-plugins/comment_template.md | 117 ++++++++++++-- .../v3/ru/awesome-plugins/comment_template.md | 117 ++++++++++++-- .../v3/uk/awesome-plugins/comment_template.md | 117 ++++++++++++-- .../v3/zh/awesome-plugins/comment_template.md | 117 ++++++++++++-- 12 files changed, 1317 insertions(+), 107 deletions(-) diff --git a/content/v3/de/awesome-plugins/comment_template.md b/content/v3/de/awesome-plugins/comment_template.md index b5ee6482..86457b5e 100644 --- a/content/v3/de/awesome-plugins/comment_template.md +++ b/content/v3/de/awesome-plugins/comment_template.md @@ -33,14 +33,14 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Wo Ihre Template-Dateien gespeichert sind - $engine->setTemplatesPath(__DIR__ . '/views'); + // Wurzelverzeichnis (wo sich index.php befindet) - das Document Root Ihrer Webanwendung + $engine->setPublicPath(__DIR__); - // Wo Ihre öffentlichen Assets serviert werden - $engine->setPublicPath(__DIR__ . '/public'); + // Template-Dateiverzeichnis - unterstützt relative und absolute Pfade + $engine->setSkinPath('views'); // Relativ zum öffentlichen Pfad - // Wo kompilierte Assets gespeichert werden - $engine->setAssetPath('assets'); + // Wo kompilierte Assets gespeichert werden - unterstützt relative und absolute Pfade + $engine->setAssetPath('assets'); // Relativ zum öffentlichen Pfad // Template-Dateierweiterung $engine->setFileExtension('.php'); @@ -63,9 +63,9 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__ . '/public', // publicPath - wo Assets serviert werden - __DIR__ . '/views', // skinPath - wo Template-Dateien gespeichert sind - 'assets', // assetPath - wo kompilierte Assets gespeichert werden + __DIR__, // publicPath - Wurzelverzeichnis (wo index.php ist) + 'views', // skinPath - Template-Pfad (unterstützt relativ/absolut) + 'assets', // assetPath - kompilierter Asset-Pfad (unterstützt relativ/absolut) '.php' // fileExtension - Template-Dateierweiterung ]); @@ -74,6 +74,83 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` +## Pfad-Konfiguration + +CommentTemplate bietet intelligente Pfad-Behandlung für relative und absolute Pfade: + +### Öffentlicher Pfad + +Der **Öffentliche Pfad** ist das Wurzelverzeichnis Ihrer Webanwendung, typischerweise wo sich `index.php` befindet. Dies ist das Document Root, von dem Webserver Dateien bereitstellen. + +```php +// Beispiel: wenn Ihre index.php bei /var/www/html/myapp/index.php liegt +$template->setPublicPath('/var/www/html/myapp'); // Wurzelverzeichnis + +// Windows-Beispiel: wenn Ihre index.php bei C:\xampp\htdocs\myapp\index.php liegt +$template->setPublicPath('C:\\xampp\\htdocs\\myapp'); +``` + +### Template-Pfad-Konfiguration + +Template-Pfad unterstützt sowohl relative als auch absolute Pfade: + +```php +$template = new Engine(); +$template->setPublicPath('/var/www/html/myapp'); // Wurzelverzeichnis (wo index.php ist) + +// Relative Pfade - automatisch mit öffentlichem Pfad kombiniert +$template->setSkinPath('views'); // → /var/www/html/myapp/views/ +$template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ + +// Absolute Pfade - wie sie sind verwendet (Unix/Linux) +$template->setSkinPath('/var/www/templates'); // → /var/www/templates/ +$template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ + +// Windows absolute Pfade +$template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ +$template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ + +// UNC-Pfade (Windows-Netzwerkfreigaben) +$template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ +``` + +### Asset-Pfad-Konfiguration + +Asset-Pfad unterstützt auch sowohl relative als auch absolute Pfade: + +```php +// Relative Pfade - automatisch mit öffentlichem Pfad kombiniert +$template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ +$template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ + +// Absolute Pfade - wie sie sind verwendet (Unix/Linux) +$template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ +$template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ + +// Windows absolute Pfade +$template->setAssetPath('C:\\www\\static'); // → C:\www\static\ +$template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ + +// UNC-Pfade (Windows-Netzwerkfreigaben) +$template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ +``` + +**Intelligente Pfad-Erkennung:** + +- **Relative Pfade**: Keine führenden Trennzeichen (`/`, `\`) oder Laufwerksbuchstaben +- **Unix Absolut**: Beginnt mit `/` (z.B. `/var/www/assets`) +- **Windows Absolut**: Beginnt mit Laufwerksbuchstabe (z.B. `C:\www`, `D:/assets`) +- **UNC-Pfade**: Beginnt mit `\\` (z.B. `\\server\share`) + +**Wie es funktioniert:** + +- Alle Pfade werden automatisch basierend auf dem Typ aufgelöst (relativ vs absolut) +- Relative Pfade werden mit dem öffentlichen Pfad kombiniert +- `@css` und `@js` erstellen minifizierte Dateien in: `{resolvedAssetPath}/css/` oder `{resolvedAssetPath}/js/` +- `@asset` kopiert einzelne Dateien nach: `{resolvedAssetPath}/{relativePath}` +- `@assetDir` kopiert Verzeichnisse nach: `{resolvedAssetPath}/{relativePath}` +- Intelligente Zwischenspeicherung: Dateien werden nur kopiert, wenn die Quelle neuer ist als das Ziel + ## Template-Direktiven ### Layout-Vererbung @@ -227,11 +304,31 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### Variablenbefehle +#### Mehrere Filter verketten ```html {$content|striptag|trim|escape} ``` +### Kommentare + +Template-Kommentare werden vollständig aus der Ausgabe entfernt und erscheinen nicht im finalen HTML: + +```html +{* Dies ist ein einzeiliger Template-Kommentar *} + +{* + Dies ist ein mehrzeiliger + Template-Kommentar + über mehrere Zeilen +*} + +

{$title}

+{* Debug-Kommentar: Prüfen ob title-Variable funktioniert *} +

{$content}

+``` + +**Hinweis**: Template-Kommentare `{* ... *}` unterscheiden sich von HTML-Kommentaren ``. Template-Kommentare werden während der Verarbeitung entfernt und erreichen nie den Browser. + ## Beispiel-Projektstruktur ``` diff --git a/content/v3/en/awesome-plugins/comment_template.md b/content/v3/en/awesome-plugins/comment_template.md index c3e5fb66..ce337a9f 100644 --- a/content/v3/en/awesome-plugins/comment_template.md +++ b/content/v3/en/awesome-plugins/comment_template.md @@ -33,14 +33,14 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Where your template files are stored - $engine->setTemplatesPath(__DIR__ . '/views'); + // Root directory (where index.php is) - the document root of your web application + $engine->setPublicPath(__DIR__); - // Where your public assets will be served from - $engine->setPublicPath(__DIR__ . '/public'); + // Template files directory - supports both relative and absolute paths + $engine->setSkinPath('views'); // Relative to public path - // Where compiled assets will be stored - $engine->setAssetPath('assets'); + // Where compiled assets will be stored - supports both relative and absolute paths + $engine->setAssetPath('assets'); // Relative to public path // Template file extension $engine->setFileExtension('.php'); @@ -63,9 +63,9 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__ . '/public', // publicPath - where assets will be served from - __DIR__ . '/views', // skinPath - where template files are stored - 'assets', // assetPath - where compiled assets will be stored + __DIR__, // publicPath - root directory (where index.php is) + 'views', // skinPath - templates path (supports relative/absolute) + 'assets', // assetPath - compiled assets path (supports relative/absolute) '.php' // fileExtension - template file extension ]); @@ -74,6 +74,83 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` +## Path Configuration + +CommentTemplate provides intelligent path handling for both relative and absolute paths: + +### Public Path + +The **Public Path** is the root directory of your web application, typically where `index.php` resides. This is the document root that web servers serve files from. + +```php +// Example: if your index.php is at /var/www/html/myapp/index.php +$template->setPublicPath('/var/www/html/myapp'); // Root directory + +// Windows example: if your index.php is at C:\xampp\htdocs\myapp\index.php +$template->setPublicPath('C:\\xampp\\htdocs\\myapp'); +``` + +### Templates Path Configuration + +Templates path supports both relative and absolute paths: + +```php +$template = new Engine(); +$template->setPublicPath('/var/www/html/myapp'); // Root directory (where index.php is) + +// Relative paths - automatically combined with public path +$template->setSkinPath('views'); // → /var/www/html/myapp/views/ +$template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ + +// Absolute paths - used as-is (Unix/Linux) +$template->setSkinPath('/var/www/templates'); // → /var/www/templates/ +$template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ + +// Windows absolute paths +$template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ +$template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ + +// UNC paths (Windows network shares) +$template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ +``` + +### Asset Path Configuration + +Asset path also supports both relative and absolute paths: + +```php +// Relative paths - automatically combined with public path +$template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ +$template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ + +// Absolute paths - used as-is (Unix/Linux) +$template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ +$template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ + +// Windows absolute paths +$template->setAssetPath('C:\\www\\static'); // → C:\www\static\ +$template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ + +// UNC paths (Windows network shares) +$template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ +``` + +**Smart Path Detection:** + +- **Relative Paths**: No leading separators (`/`, `\`) or drive letters +- **Unix Absolute**: Starts with `/` (e.g., `/var/www/assets`) +- **Windows Absolute**: Starts with drive letter (e.g., `C:\www`, `D:/assets`) +- **UNC Paths**: Starts with `\\` (e.g., `\\server\share`) + +**How it works:** + +- All paths are automatically resolved based on type (relative vs absolute) +- Relative paths are combined with the public path +- `@css` and `@js` create minified files in: `{resolvedAssetPath}/css/` or `{resolvedAssetPath}/js/` +- `@asset` copies single files to: `{resolvedAssetPath}/{relativePath}` +- `@assetDir` copies directories to: `{resolvedAssetPath}/{relativePath}` +- Smart caching: files only copied when source is newer than destination + ## Template Directives ### Layout Inheritance @@ -232,6 +309,26 @@ const imageData = ''; {$content|striptag|trim|escape} ``` +### Comments + +Template comments are completely removed from the output and won't appear in the final HTML: + +```html +{* This is a single-line template comment *} + +{* + This is a multi-line + template comment + that spans several lines +*} + +

{$title}

+{* Debug comment: checking if title variable works *} +

{$content}

+``` + +**Note**: Template comments `{* ... *}` are different from HTML comments ``. Template comments are removed during processing and never reach the browser. + ## Example Project Structure ``` diff --git a/content/v3/es/awesome-plugins/comment_template.md b/content/v3/es/awesome-plugins/comment_template.md index 6bc1d53d..16a9a152 100644 --- a/content/v3/es/awesome-plugins/comment_template.md +++ b/content/v3/es/awesome-plugins/comment_template.md @@ -33,14 +33,14 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Donde se almacenan tus archivos de plantilla - $engine->setTemplatesPath(__DIR__ . '/views'); + // Directorio raíz (donde está index.php) - la raíz del documento de su aplicación web + $engine->setPublicPath(__DIR__); - // Donde se servirán tus activos públicos - $engine->setPublicPath(__DIR__ . '/public'); + // Directorio de archivos de plantilla - soporta rutas relativas y absolutas + $engine->setSkinPath('views'); // Relativo a la ruta pública - // Donde se almacenarán los activos compilados - $engine->setAssetPath('assets'); + // Donde se almacenarán los activos compilados - soporta rutas relativas y absolutas + $engine->setAssetPath('assets'); // Relativo a la ruta pública // Extensión de archivo de plantilla $engine->setFileExtension('.php'); @@ -63,9 +63,9 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__ . '/public', // publicPath - donde se servirán los activos - __DIR__ . '/views', // skinPath - donde se almacenan los archivos de plantilla - 'assets', // assetPath - donde se almacenarán los activos compilados + __DIR__, // publicPath - directorio raíz (donde está index.php) + 'views', // skinPath - ruta de plantillas (soporta relativa/absoluta) + 'assets', // assetPath - ruta de activos compilados (soporta relativa/absoluta) '.php' // fileExtension - extensión de archivo de plantilla ]); @@ -74,6 +74,83 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` +## Configuración de Rutas + +CommentTemplate proporciona manejo inteligente de rutas para rutas relativas y absolutas: + +### Ruta Pública + +La **Ruta Pública** es el directorio raíz de su aplicación web, típicamente donde reside `index.php`. Este es el document root desde donde los servidores web sirven archivos. + +```php +// Ejemplo: si su index.php está en /var/www/html/myapp/index.php +$template->setPublicPath('/var/www/html/myapp'); // Directorio raíz + +// Ejemplo Windows: si su index.php está en C:\xampp\htdocs\myapp\index.php +$template->setPublicPath('C:\\xampp\\htdocs\\myapp'); +``` + +### Configuración de Ruta de Plantillas + +La ruta de plantillas soporta tanto rutas relativas como absolutas: + +```php +$template = new Engine(); +$template->setPublicPath('/var/www/html/myapp'); // Directorio raíz (donde está index.php) + +// Rutas relativas - automáticamente combinadas con la ruta pública +$template->setSkinPath('views'); // → /var/www/html/myapp/views/ +$template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ + +// Rutas absolutas - usadas tal como están (Unix/Linux) +$template->setSkinPath('/var/www/templates'); // → /var/www/templates/ +$template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ + +// Rutas absolutas Windows +$template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ +$template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ + +// Rutas UNC (recursos compartidos de red Windows) +$template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ +``` + +### Configuración de Ruta de Activos + +La ruta de activos también soporta tanto rutas relativas como absolutas: + +```php +// Rutas relativas - automáticamente combinadas con la ruta pública +$template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ +$template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ + +// Rutas absolutas - usadas tal como están (Unix/Linux) +$template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ +$template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ + +// Rutas absolutas Windows +$template->setAssetPath('C:\\www\\static'); // → C:\www\static\ +$template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ + +// Rutas UNC (recursos compartidos de red Windows) +$template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ +``` + +**Detección Inteligente de Rutas:** + +- **Rutas Relativas**: Sin separadores principales (`/`, `\`) o letras de unidad +- **Unix Absoluta**: Comienza con `/` (ej. `/var/www/assets`) +- **Windows Absoluta**: Comienza con letra de unidad (ej. `C:\www`, `D:/assets`) +- **Rutas UNC**: Comienza con `\\` (ej. `\\server\share`) + +**Cómo funciona:** + +- Todas las rutas se resuelven automáticamente basándose en el tipo (relativa vs absoluta) +- Las rutas relativas se combinan con la ruta pública +- `@css` y `@js` crean archivos minificados en: `{resolvedAssetPath}/css/` o `{resolvedAssetPath}/js/` +- `@asset` copia archivos únicos a: `{resolvedAssetPath}/{relativePath}` +- `@assetDir` copia directorios a: `{resolvedAssetPath}/{relativePath}` +- Caché inteligente: los archivos solo se copian cuando el origen es más nuevo que el destino + ## Directivas de Plantilla ### Herencia de Diseño @@ -227,11 +304,31 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### Comandos de Variables +#### Encadenar Múltiples Filtros ```html {$content|striptag|trim|escape} ``` +### Comentarios + +Los comentarios de plantilla se eliminan completamente de la salida y no aparecen en el HTML final: + +```html +{* Este es un comentario de plantilla de una línea *} + +{* + Este es un comentario de plantilla + de múltiples líneas + que abarca varias líneas +*} + +

{$title}

+{* Comentario de depuración: verificar si la variable title funciona *} +

{$content}

+``` + +**Nota**: Los comentarios de plantilla `{* ... *}` son diferentes de los comentarios HTML ``. Los comentarios de plantilla se eliminan durante el procesamiento y nunca llegan al navegador. + ## Estructura de Proyecto de Ejemplo ``` diff --git a/content/v3/fr/awesome-plugins/comment_template.md b/content/v3/fr/awesome-plugins/comment_template.md index d23634ae..0a26bb97 100644 --- a/content/v3/fr/awesome-plugins/comment_template.md +++ b/content/v3/fr/awesome-plugins/comment_template.md @@ -33,14 +33,14 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Où vos fichiers de templates sont stockés - $engine->setTemplatesPath(__DIR__ . '/views'); + // Répertoire racine (où se trouve index.php) - la racine du document de votre application web + $engine->setPublicPath(__DIR__); - // D'où vos actifs publics seront servis - $engine->setPublicPath(__DIR__ . '/public'); + // Répertoire des fichiers de templates - supporte les chemins relatifs et absolus + $engine->setSkinPath('views'); // Relatif au chemin public - // Où les actifs compilés seront stockés - $engine->setAssetPath('assets'); + // Où les actifs compilés seront stockés - supporte les chemins relatifs et absolus + $engine->setAssetPath('assets'); // Relatif au chemin public // Extension des fichiers de template $engine->setFileExtension('.php'); @@ -63,9 +63,9 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__ . '/public', // publicPath - d'où les actifs seront servis - __DIR__ . '/views', // skinPath - où les fichiers de templates sont stockés - 'assets', // assetPath - où les actifs compilés seront stockés + __DIR__, // publicPath - répertoire racine (où se trouve index.php) + 'views', // skinPath - chemin des templates (supporte relatif/absolu) + 'assets', // assetPath - chemin des actifs compilés (supporte relatif/absolu) '.php' // fileExtension - extension des fichiers de template ]); @@ -74,6 +74,83 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` +## Configuration des Chemins + +CommentTemplate offre une gestion intelligente des chemins pour les chemins relatifs et absolus : + +### Chemin Public + +Le **Chemin Public** est le répertoire racine de votre application web, généralement où se trouve `index.php`. C'est la racine du document que les serveurs web utilisent pour servir les fichiers. + +```php +// Exemple : si votre index.php est à /var/www/html/myapp/index.php +$template->setPublicPath('/var/www/html/myapp'); // Répertoire racine + +// Exemple Windows : si votre index.php est à C:\xampp\htdocs\myapp\index.php +$template->setPublicPath('C:\\xampp\\htdocs\\myapp'); +``` + +### Configuration du Chemin des Templates + +Le chemin des templates supporte les chemins relatifs et absolus : + +```php +$template = new Engine(); +$template->setPublicPath('/var/www/html/myapp'); // Répertoire racine (où se trouve index.php) + +// Chemins relatifs - automatiquement combinés avec le chemin public +$template->setSkinPath('views'); // → /var/www/html/myapp/views/ +$template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ + +// Chemins absolus - utilisés tel quel (Unix/Linux) +$template->setSkinPath('/var/www/templates'); // → /var/www/templates/ +$template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ + +// Chemins absolus Windows +$template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ +$template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ + +// Chemins UNC (partages réseau Windows) +$template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ +``` + +### Configuration du Chemin des Actifs + +Le chemin des actifs supporte aussi les chemins relatifs et absolus : + +```php +// Chemins relatifs - automatiquement combinés avec le chemin public +$template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ +$template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ + +// Chemins absolus - utilisés tel quel (Unix/Linux) +$template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ +$template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ + +// Chemins absolus Windows +$template->setAssetPath('C:\\www\\static'); // → C:\www\static\ +$template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ + +// Chemins UNC (partages réseau Windows) +$template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ +``` + +**Détection Intelligente des Chemins :** + +- **Chemins Relatifs** : Pas de séparateurs de début (`/`, `\`) ou de lettres de lecteur +- **Unix Absolu** : Commence par `/` (ex : `/var/www/assets`) +- **Windows Absolu** : Commence par une lettre de lecteur (ex : `C:\www`, `D:/assets`) +- **Chemins UNC** : Commence par `\\` (ex : `\\server\share`) + +**Comment ça fonctionne :** + +- Tous les chemins sont automatiquement résolus selon le type (relatif vs absolu) +- Les chemins relatifs sont combinés avec le chemin public +- `@css` et `@js` créent des fichiers minifiés dans : `{resolvedAssetPath}/css/` ou `{resolvedAssetPath}/js/` +- `@asset` copie les fichiers uniques vers : `{resolvedAssetPath}/{relativePath}` +- `@assetDir` copie les répertoires vers : `{resolvedAssetPath}/{relativePath}` +- Cache intelligent : les fichiers ne sont copiés que lorsque la source est plus récente que la destination + ## Directives de Template ### Héritage de Layout @@ -227,11 +304,31 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### Commandes de Variables +#### Chaîner Plusieurs Filtres ```html {$content|striptag|trim|escape} ``` +### Commentaires + +Les commentaires de template sont entièrement supprimés de la sortie et n'apparaissent pas dans le HTML final : + +```html +{* Ceci est un commentaire de template sur une ligne *} + +{* + Ceci est un commentaire de template + multi-lignes qui s'étend sur + plusieurs lignes +*} + +

{$title}

+{* Commentaire de débogage : vérifie si la variable title fonctionne *} +

{$content}

+``` + +**Note** : Les commentaires de template `{* ... *}` sont différents des commentaires HTML ``. Les commentaires de template sont supprimés lors du traitement et n'atteignent jamais le navigateur. + ## Structure de Projet Exemple ``` diff --git a/content/v3/id/awesome-plugins/comment_template.md b/content/v3/id/awesome-plugins/comment_template.md index 0d27b752..ea132625 100644 --- a/content/v3/id/awesome-plugins/comment_template.md +++ b/content/v3/id/awesome-plugins/comment_template.md @@ -33,14 +33,14 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Tempat file template disimpan - $engine->setTemplatesPath(__DIR__ . '/views'); + // Direktori root (tempat index.php berada) - root dokumen aplikasi web Anda + $engine->setPublicPath(__DIR__); - // Tempat aset publik akan disajikan - $engine->setPublicPath(__DIR__ . '/public'); + // Direktori file template - mendukung path relatif dan absolut + $engine->setSkinPath('views'); // Relatif terhadap path publik - // Tempat aset yang dikompilasi akan disimpan - $engine->setAssetPath('assets'); + // Tempat aset yang dikompilasi akan disimpan - mendukung path relatif dan absolut + $engine->setAssetPath('assets'); // Relatif terhadap path publik // Ekstensi file template $engine->setFileExtension('.php'); @@ -74,6 +74,79 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` +### Konfigurasi Path + +CommentTemplate mendukung path relatif dan absolut dengan resolusi cerdas: + +#### Path Relatif +```php +setPublicPath(__DIR__ . '/public'); +$engine->setSkinPath('templates'); // Akan di-resolve ke {publicPath}/templates +$engine->setAssetPath('compiled'); // Akan di-resolve ke {publicPath}/compiled + +// Juga dapat menggunakan subdirektori +$engine->setSkinPath('views/templates'); +$engine->setAssetPath('assets/compiled'); +``` + +#### Path Absolut +```php +setSkinPath('/var/www/templates'); +$engine->setAssetPath('/var/www/public/assets'); + +// Path Windows +$engine->setSkinPath('C:\xampp\htdocs\templates'); +$engine->setAssetPath('C:\xampp\htdocs\public\assets'); + +// Path UNC (Windows network) +$engine->setSkinPath('\\server\share\templates'); +$engine->setAssetPath('\\server\share\public\assets'); +``` + +#### Path Campuran +```php +setPublicPath('/var/www/public'); + +// Campurkan path relatif dan absolut berdasarkan kebutuhan +$engine->setSkinPath('views'); // Relatif: /var/www/public/views +$engine->setAssetPath('/tmp/compiled-assets'); // Absolut: /tmp/compiled-assets +``` + +#### Tips Praktis + +**Pengembangan Lokal:** +```php +$engine->setPublicPath(__DIR__ . '/public'); +$engine->setSkinPath('views'); // Mudah untuk pengembangan +$engine->setAssetPath('assets'); // Aset terorganisir dalam struktur proyek +``` + +**Produksi:** +```php +$engine->setPublicPath('/var/www/myapp/public'); +$engine->setSkinPath('/var/www/myapp/templates'); // Path absolut untuk kontrol penuh +$engine->setAssetPath('/var/www/myapp/public/dist'); // Aset di direktori yang dapat diakses web +``` + +**Docker/Container:** +```php +$engine->setPublicPath('/app/public'); +$engine->setSkinPath('/app/resources/views'); +$engine->setAssetPath('/app/public/assets'); +``` + +CommentTemplate secara otomatis mendeteksi jenis path dan menanganinya dengan benar, memberikan fleksibilitas maksimum untuk setup deployment yang berbeda. + ## Direktif Template ### Pewarisan Layout @@ -227,11 +300,31 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### Perintah Variabel +#### Rantai Beberapa Filter ```html {$content|striptag|trim|escape} ``` +### Komentar + +Komentar template sepenuhnya dihapus dari output dan tidak muncul di HTML final: + +```html +{* Ini adalah komentar template satu baris *} + +{* + Ini adalah komentar template + multi-baris yang mencakup + beberapa baris +*} + +

{$title}

+{* Komentar debugging: memeriksa apakah variabel title berfungsi *} +

{$content}

+``` + +**Catatan**: Komentar template `{* ... *}` berbeda dari komentar HTML ``. Komentar template dihapus selama pemrosesan dan tidak pernah sampai ke browser. + ## Struktur Proyek Contoh ``` diff --git a/content/v3/ja/awesome-plugins/comment_template.md b/content/v3/ja/awesome-plugins/comment_template.md index 710e6808..a5c528dd 100644 --- a/content/v3/ja/awesome-plugins/comment_template.md +++ b/content/v3/ja/awesome-plugins/comment_template.md @@ -32,6 +32,133 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); +$app->register('view', Engine::class, [], function (Engine $engine) use ($app) { + // ルートディレクトリ(index.phpがある場所)- Webアプリケーションのドキュメントルート + $engine->setPublicPath(__DIR__); + + // テンプレートファイルディレクトリ - 相対パスと絶対パスの両方をサポート + $engine->setSkinPath('views'); // パブリックパス基準の相対パス + + // コンパイルされたアセットが保存される場所 - 相対パスと絶対パスの両方をサポート + $engine->setAssetPath('assets'); // パブリックパス基準の相対パス + + // テンプレートファイル拡張子 + $engine->setFileExtension('.php'); +}); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +### 方法 2: コンストラクタパラメータを使用 + +```php +register('view', Engine::class, [ + __DIR__, // publicPath - ルートディレクトリ(index.phpがある場所) + 'views', // skinPath - テンプレートパス(相対/絶対パスをサポート) + 'assets', // assetPath - コンパイルされたアセットパス(相対/絶対パスをサポート) + '.php' // fileExtension - テンプレートファイル拡張子 +]); + +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); +``` + +## パス設定 + +CommentTemplate は相対パスと絶対パスの両方に対するインテリジェントなパス処理を提供します: + +### パブリックパス + +**パブリックパス**は、通常 `index.php` が配置されている Web アプリケーションのルートディレクトリです。これは Web サーバーがファイルを提供するドキュメントルートです。 + +```php +// 例: index.phpが /var/www/html/myapp/index.php にある場合 +$template->setPublicPath('/var/www/html/myapp'); // ルートディレクトリ + +// Windows例: index.phpが C:\xampp\htdocs\myapp\index.php にある場合 +$template->setPublicPath('C:\\xampp\\htdocs\\myapp'); +``` + +### テンプレートパス設定 + +テンプレートパスは相対パスと絶対パスの両方をサポートします: + +```php +$template = new Engine(); +$template->setPublicPath('/var/www/html/myapp'); // ルートディレクトリ(index.phpがある場所) + +// 相対パス - パブリックパスと自動的に結合 +$template->setSkinPath('views'); // → /var/www/html/myapp/views/ +$template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ + +// 絶対パス - そのまま使用(Unix/Linux) +$template->setSkinPath('/var/www/templates'); // → /var/www/templates/ +$template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ + +// Windows絶対パス +$template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ +$template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ + +// UNCパス(Windowsネットワーク共有) +$template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ +``` + +### アセットパス設定 + +アセットパスも相対パスと絶対パスの両方をサポートします: + +```php +// 相対パス - パブリックパスと自動的に結合 +$template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ +$template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ + +// 絶対パス - そのまま使用(Unix/Linux) +$template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ +$template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ + +// Windows絶対パス +$template->setAssetPath('C:\\www\\static'); // → C:\www\static\ +$template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ + +// UNCパス(Windowsネットワーク共有) +$template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ +``` + +**スマートパス検出:** + +- **相対パス**: 先頭の区切り文字(`/`、`\`)やドライブ文字なし +- **Unix絶対**: `/` で始まる(例:`/var/www/assets`) +- **Windows絶対**: ドライブ文字で始まる(例:`C:\www`、`D:/assets`) +- **UNCパス**: `\\` で始まる(例:`\\server\share`) + +**動作方法:** + +- すべてのパスはタイプに基づいて自動的に解決されます(相対 vs 絶対) +- 相対パスはパブリックパスと結合されます +- `@css` と `@js` は以下の場所に最小化されたファイルを作成します:`{resolvedAssetPath}/css/` または `{resolvedAssetPath}/js/` +- `@asset` は単一ファイルを以下の場所にコピーします:`{resolvedAssetPath}/{relativePath}` +- `@assetDir` はディレクトリを以下の場所にコピーします:`{resolvedAssetPath}/{relativePath}` +- スマートキャッシュ: ソースが宛先より新しい場合のみファイルがコピーされます + +```php +register('view', Engine::class, [], function (Engine $engine) use ($app) { // テンプレートファイルが保存される場所 $engine->setTemplatesPath(__DIR__ . '/views'); @@ -228,11 +355,31 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### 変数コマンド +#### 複数フィルターのチェーン ```html {$content|striptag|trim|escape} ``` +### コメント + +テンプレートコメントは出力から完全に削除され、最終的な HTML には表示されません: + +```html +{* これは単一行のテンプレートコメントです *} + +{* + これは複数行にわたる + マルチライン + テンプレートコメントです +*} + +

{$title}

+{* デバッグコメント: title変数が動作するかチェック *} +

{$content}

+``` + +**注記**: テンプレートコメント `{* ... *}` は HTML コメント `` とは異なります。テンプレートコメントは処理中に削除され、ブラウザには届きません。 + ## 例のプロジェクト構造 ``` diff --git a/content/v3/ko/awesome-plugins/comment_template.md b/content/v3/ko/awesome-plugins/comment_template.md index 7a555178..a419aec9 100644 --- a/content/v3/ko/awesome-plugins/comment_template.md +++ b/content/v3/ko/awesome-plugins/comment_template.md @@ -33,14 +33,14 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // 템플릿 파일이 저장된 위치 - $engine->setTemplatesPath(__DIR__ . '/views'); + // 루트 디렉토리 (index.php가 있는 곳) - 웹 애플리케이션의 문서 루트 + $engine->setPublicPath(__DIR__); - // 공용 자산이 제공되는 위치 - $engine->setPublicPath(__DIR__ . '/public'); + // 템플릿 파일 디렉토리 - 상대 경로와 절대 경로 모두 지원 + $engine->setSkinPath('views'); // 공용 경로 기준 상대 경로 - // 컴파일된 자산이 저장되는 위치 - $engine->setAssetPath('assets'); + // 컴파일된 자산이 저장되는 위치 - 상대 경로와 절대 경로 모두 지원 + $engine->setAssetPath('assets'); // 공용 경로 기준 상대 경로 // 템플릿 파일 확장자 $engine->setFileExtension('.php'); @@ -63,9 +63,9 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__ . '/public', // publicPath - 자산이 제공되는 위치 - __DIR__ . '/views', // skinPath - 템플릿 파일이 저장된 위치 - 'assets', // assetPath - 컴파일된 자산이 저장되는 위치 + __DIR__, // publicPath - 루트 디렉토리 (index.php가 있는 곳) + 'views', // skinPath - 템플릿 경로 (상대/절대 경로 지원) + 'assets', // assetPath - 컴파일된 자산 경로 (상대/절대 경로 지원) '.php' // fileExtension - 템플릿 파일 확장자 ]); @@ -74,6 +74,83 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` +## 경로 설정 + +CommentTemplate은 상대 경로와 절대 경로 모두에 대한 지능형 경로 처리를 제공합니다: + +### 공용 경로 + +**공용 경로**는 일반적으로 `index.php`가 있는 웹 애플리케이션의 루트 디렉토리입니다. 이는 웹 서버가 파일을 제공하는 문서 루트입니다. + +```php +// 예: index.php가 /var/www/html/myapp/index.php에 있는 경우 +$template->setPublicPath('/var/www/html/myapp'); // 루트 디렉토리 + +// Windows 예: index.php가 C:\xampp\htdocs\myapp\index.php에 있는 경우 +$template->setPublicPath('C:\\xampp\\htdocs\\myapp'); +``` + +### 템플릿 경로 설정 + +템플릿 경로는 상대 경로와 절대 경로를 모두 지원합니다: + +```php +$template = new Engine(); +$template->setPublicPath('/var/www/html/myapp'); // 루트 디렉토리 (index.php가 있는 곳) + +// 상대 경로 - 공용 경로와 자동으로 결합 +$template->setSkinPath('views'); // → /var/www/html/myapp/views/ +$template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ + +// 절대 경로 - 그대로 사용 (Unix/Linux) +$template->setSkinPath('/var/www/templates'); // → /var/www/templates/ +$template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ + +// Windows 절대 경로 +$template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ +$template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ + +// UNC 경로 (Windows 네트워크 공유) +$template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ +``` + +### 자산 경로 설정 + +자산 경로도 상대 경로와 절대 경로를 모두 지원합니다: + +```php +// 상대 경로 - 공용 경로와 자동으로 결합 +$template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ +$template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ + +// 절대 경로 - 그대로 사용 (Unix/Linux) +$template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ +$template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ + +// Windows 절대 경로 +$template->setAssetPath('C:\\www\\static'); // → C:\www\static\ +$template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ + +// UNC 경로 (Windows 네트워크 공유) +$template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ +``` + +**스마트 경로 감지:** + +- **상대 경로**: 선행 구분자(`/`, `\`)나 드라이브 문자가 없음 +- **Unix 절대**: `/`로 시작 (예: `/var/www/assets`) +- **Windows 절대**: 드라이브 문자로 시작 (예: `C:\www`, `D:/assets`) +- **UNC 경로**: `\\`로 시작 (예: `\\server\share`) + +**작동 방식:** + +- 모든 경로는 유형에 따라 자동으로 해결됩니다 (상대 vs 절대) +- 상대 경로는 공용 경로와 결합됩니다 +- `@css`와 `@js`는 다음 위치에 압축된 파일을 생성합니다: `{resolvedAssetPath}/css/` 또는 `{resolvedAssetPath}/js/` +- `@asset`은 단일 파일을 다음 위치에 복사합니다: `{resolvedAssetPath}/{relativePath}` +- `@assetDir`은 디렉토리를 다음 위치에 복사합니다: `{resolvedAssetPath}/{relativePath}` +- 스마트 캐싱: 소스가 대상보다 최신인 경우에만 파일이 복사됩니다 + ## 템플릿 지시어 ### 레이아웃 상속 @@ -227,11 +304,31 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### 변수 명령어 +#### 다중 필터 체인 ```html {$content|striptag|trim|escape} ``` +### 주석 + +템플릿 주석은 출력에서 완전히 제거되며 최종 HTML에 나타나지 않습니다: + +```html +{* 이것은 한 줄 템플릿 주석입니다 *} + +{* + 이것은 여러 줄에 걸친 + 다중 줄 + 템플릿 주석입니다 +*} + +

{$title}

+{* 디버그 주석: title 변수가 작동하는지 확인 *} +

{$content}

+``` + +**참고**: 템플릿 주석 `{* ... *}`은 HTML 주석 ``과 다릅니다. 템플릿 주석은 처리 중에 제거되며 브라우저에 전달되지 않습니다. + ## 예시 프로젝트 구조 ``` diff --git a/content/v3/lv/awesome-plugins/comment_template.md b/content/v3/lv/awesome-plugins/comment_template.md index ad8a0d6e..d83f927b 100644 --- a/content/v3/lv/awesome-plugins/comment_template.md +++ b/content/v3/lv/awesome-plugins/comment_template.md @@ -33,14 +33,14 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Kur tiek glabāti jūsu veidņu faili - $engine->setTemplatesPath(__DIR__ . '/views'); + // Saknes direktorijs (kur atrodas index.php) - jūsu tīmekļa lietojumprogrammas dokumentu sakne + $engine->setPublicPath(__DIR__); - // Kur tiks apkalpoti jūsu publiskie resursi - $engine->setPublicPath(__DIR__ . '/public'); + // Veidņu failu direktorijs - atbalsta relatīvos un absolūtos ceļus + $engine->setSkinPath('views'); // Relatīvs pret publisko ceļu - // Kur tiks glabāti kompilētie resursi - $engine->setAssetPath('assets'); + // Kur tiks glabāti kompilētie resursi - atbalsta relatīvos un absolūtos ceļus + $engine->setAssetPath('assets'); // Relatīvs pret publisko ceļu // Veidnes faila paplašinājums $engine->setFileExtension('.php'); @@ -63,9 +63,9 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__ . '/public', // publicPath - kur tiks apkalpoti resursi - __DIR__ . '/views', // skinPath - kur tiek glabāti veidņu faili - 'assets', // assetPath - kur tiks glabāti kompilētie resursi + __DIR__, // publicPath - saknes direktorijs (kur atrodas index.php) + 'views', // skinPath - veidņu ceļš (atbalsta relatīvos/absolūtos) + 'assets', // assetPath - kompilēto resursu ceļš (atbalsta relatīvos/absolūtos) '.php' // fileExtension - veidnes faila paplašinājums ]); @@ -74,6 +74,83 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` +## Ceļa konfigurācija + +CommentTemplate nodrošina inteliģentu ceļu apstrādi relatīvajiem un absolūtajiem ceļiem: + +### Publiskais ceļš + +**Publiskais ceļš** ir jūsu tīmekļa lietojumprogrammas saknes direktorijs, parasti tur, kur atrodas `index.php`. Šis ir dokumentu sakne, no kuras tīmekļa serveri apkalpo failus. + +```php +// Piemērs: ja jūsu index.php atrodas /var/www/html/myapp/index.php +$template->setPublicPath('/var/www/html/myapp'); // Saknes direktorijs + +// Windows piemērs: ja jūsu index.php atrodas C:\xampp\htdocs\myapp\index.php +$template->setPublicPath('C:\\xampp\\htdocs\\myapp'); +``` + +### Veidņu ceļa konfigurācija + +Veidņu ceļš atbalsta gan relatīvos, gan absolūtos ceļus: + +```php +$template = new Engine(); +$template->setPublicPath('/var/www/html/myapp'); // Saknes direktorijs (kur atrodas index.php) + +// Relatīvie ceļi - automātiski apvienoti ar publisko ceļu +$template->setSkinPath('views'); // → /var/www/html/myapp/views/ +$template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ + +// Absolūtie ceļi - izmantoti kā ir (Unix/Linux) +$template->setSkinPath('/var/www/templates'); // → /var/www/templates/ +$template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ + +// Windows absolūtie ceļi +$template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ +$template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ + +// UNC ceļi (Windows tīkla koplietošana) +$template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ +``` + +### Resursu ceļa konfigurācija + +Resursu ceļš arī atbalsta gan relatīvos, gan absolūtos ceļus: + +```php +// Relatīvie ceļi - automātiski apvienoti ar publisko ceļu +$template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ +$template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ + +// Absolūtie ceļi - izmantoti kā ir (Unix/Linux) +$template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ +$template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ + +// Windows absolūtie ceļi +$template->setAssetPath('C:\\www\\static'); // → C:\www\static\ +$template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ + +// UNC ceļi (Windows tīkla koplietošana) +$template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ +``` + +**Viedā ceļa noteikšana:** + +- **Relatīvie ceļi**: Bez sākuma atdalītājiem (`/`, `\`) vai disku burtiem +- **Unix absolūtie**: Sākas ar `/` (piem. `/var/www/assets`) +- **Windows absolūtie**: Sākas ar disku burtu (piem. `C:\www`, `D:/assets`) +- **UNC ceļi**: Sākas ar `\\` (piem. `\\server\share`) + +**Kā tas darbojas:** + +- Visi ceļi tiek automātiski atrisināti, pamatojoties uz tipu (relatīvs vs absolūts) +- Relatīvie ceļi tiek apvienoti ar publisko ceļu +- `@css` un `@js` izveido minimizētus failus šeit: `{resolvedAssetPath}/css/` vai `{resolvedAssetPath}/js/` +- `@asset` kopē atsevišķus failus uz: `{resolvedAssetPath}/{relativePath}` +- `@assetDir` kopē direktorijus uz: `{resolvedAssetPath}/{relativePath}` +- Viedā kešošana: faili tiek kopēti tikai tad, ja avots ir jaunāks nekā mērķis + ## Veidnes direktīvas ### Izkārtojuma mantojums @@ -227,11 +304,31 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### Mainīgo komandas +#### Ķēdīt vairākus filtrus ```html {$content|striptag|trim|escape} ``` +### Komentāri + +Veidnes komentāri tiek pilnībā noņemti no izvades un neparādās gala HTML: + +```html +{* Šis ir vienas līnijas veidnes komentārs *} + +{* + Šis ir daudzrindas + veidnes komentārs + kas aptver vairākas līnijas +*} + +

{$title}

+{* Atkļūdošanas komentārs: pārbauda vai title mainīgais darbojas *} +

{$content}

+``` + +**Piezīme**: Veidnes komentāri `{* ... *}` atšķiras no HTML komentāriem ``. Veidnes komentāri tiek noņemti apstrādes laikā un nekad nesasniedz pārlūkprogrammu. + ## Piemēra projekta struktūra ``` diff --git a/content/v3/pt/awesome-plugins/comment_template.md b/content/v3/pt/awesome-plugins/comment_template.md index 0161b222..8c1899f6 100644 --- a/content/v3/pt/awesome-plugins/comment_template.md +++ b/content/v3/pt/awesome-plugins/comment_template.md @@ -33,14 +33,14 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Onde seus arquivos de template estão armazenados - $engine->setTemplatesPath(__DIR__ . '/views'); + // Diretório raiz (onde está o index.php) - a raiz do documento da sua aplicação web + $engine->setPublicPath(__DIR__); - // Onde seus assets públicos serão servidos - $engine->setPublicPath(__DIR__ . '/public'); + // Diretório dos arquivos de template - suporta caminhos relativos e absolutos + $engine->setSkinPath('views'); // Relativo ao caminho público - // Onde os assets compilados serão armazenados - $engine->setAssetPath('assets'); + // Onde os assets compilados serão armazenados - suporta caminhos relativos e absolutos + $engine->setAssetPath('assets'); // Relativo ao caminho público // Extensão do arquivo de template $engine->setFileExtension('.php'); @@ -63,9 +63,9 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__ . '/public', // publicPath - onde os assets serão servidos - __DIR__ . '/views', // skinPath - onde os arquivos de template estão armazenados - 'assets', // assetPath - onde os assets compilados serão armazenados + __DIR__, // publicPath - diretório raiz (onde está o index.php) + 'views', // skinPath - caminho dos templates (suporta relativo/absoluto) + 'assets', // assetPath - caminho dos assets compilados (suporta relativo/absoluto) '.php' // fileExtension - extensão do arquivo de template ]); @@ -74,6 +74,83 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` +## Configuração de Caminhos + +CommentTemplate fornece tratamento inteligente de caminhos para caminhos relativos e absolutos: + +### Caminho Público + +O **Caminho Público** é o diretório raiz da sua aplicação web, tipicamente onde o `index.php` reside. Esta é a raiz do documento de onde os servidores web servem arquivos. + +```php +// Exemplo: se seu index.php está em /var/www/html/myapp/index.php +$template->setPublicPath('/var/www/html/myapp'); // Diretório raiz + +// Exemplo Windows: se seu index.php está em C:\xampp\htdocs\myapp\index.php +$template->setPublicPath('C:\\xampp\\htdocs\\myapp'); +``` + +### Configuração do Caminho de Templates + +O caminho de templates suporta caminhos relativos e absolutos: + +```php +$template = new Engine(); +$template->setPublicPath('/var/www/html/myapp'); // Diretório raiz (onde está o index.php) + +// Caminhos relativos - automaticamente combinados com o caminho público +$template->setSkinPath('views'); // → /var/www/html/myapp/views/ +$template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ + +// Caminhos absolutos - usados como estão (Unix/Linux) +$template->setSkinPath('/var/www/templates'); // → /var/www/templates/ +$template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ + +// Caminhos absolutos Windows +$template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ +$template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ + +// Caminhos UNC (compartilhamentos de rede Windows) +$template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ +``` + +### Configuração do Caminho de Assets + +O caminho de assets também suporta caminhos relativos e absolutos: + +```php +// Caminhos relativos - automaticamente combinados com o caminho público +$template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ +$template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ + +// Caminhos absolutos - usados como estão (Unix/Linux) +$template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ +$template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ + +// Caminhos absolutos Windows +$template->setAssetPath('C:\\www\\static'); // → C:\www\static\ +$template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ + +// Caminhos UNC (compartilhamentos de rede Windows) +$template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ +``` + +**Detecção Inteligente de Caminhos:** + +- **Caminhos Relativos**: Sem separadores iniciais (`/`, `\`) ou letras de unidade +- **Unix Absoluto**: Começa com `/` (ex. `/var/www/assets`) +- **Windows Absoluto**: Começa com letra de unidade (ex. `C:\www`, `D:/assets`) +- **Caminhos UNC**: Começa com `\\` (ex. `\\server\share`) + +**Como funciona:** + +- Todos os caminhos são automaticamente resolvidos baseados no tipo (relativo vs absoluto) +- Caminhos relativos são combinados com o caminho público +- `@css` e `@js` criam arquivos minificados em: `{resolvedAssetPath}/css/` ou `{resolvedAssetPath}/js/` +- `@asset` copia arquivos únicos para: `{resolvedAssetPath}/{relativePath}` +- `@assetDir` copia diretórios para: `{resolvedAssetPath}/{relativePath}` +- Cache inteligente: arquivos só são copiados quando a fonte é mais nova que o destino + ## Diretivas de Template ### Herança de Layout @@ -227,11 +304,31 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### Comandos de Variáveis +#### Encadear Múltiplos Filtros ```html {$content|striptag|trim|escape} ``` +### Comentários + +Comentários de template são completamente removidos da saída e não aparecem no HTML final: + +```html +{* Este é um comentário de template de uma linha *} + +{* + Este é um comentário de template + de múltiplas linhas + que abrange várias linhas +*} + +

{$title}

+{* Comentário de debug: verificar se a variável title funciona *} +

{$content}

+``` + +**Nota**: Comentários de template `{* ... *}` são diferentes de comentários HTML ``. Comentários de template são removidos durante o processamento e nunca chegam ao navegador. + ## Estrutura de Projeto Exemplo ``` diff --git a/content/v3/ru/awesome-plugins/comment_template.md b/content/v3/ru/awesome-plugins/comment_template.md index 7776361a..3ce888c6 100644 --- a/content/v3/ru/awesome-plugins/comment_template.md +++ b/content/v3/ru/awesome-plugins/comment_template.md @@ -33,14 +33,14 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Где хранятся файлы шаблонов - $engine->setTemplatesPath(__DIR__ . '/views'); + // Корневая директория (где находится index.php) - корень документа вашего веб-приложения + $engine->setPublicPath(__DIR__); - // Откуда будут обслуживаться публичные активы - $engine->setPublicPath(__DIR__ . '/public'); + // Директория файлов шаблонов - поддерживает относительные и абсолютные пути + $engine->setSkinPath('views'); // Относительно публичного пути - // Где будут храниться скомпилированные активы - $engine->setAssetPath('assets'); + // Где будут храниться скомпилированные активы - поддерживает относительные и абсолютные пути + $engine->setAssetPath('assets'); // Относительно публичного пути // Расширение файла шаблона $engine->setFileExtension('.php'); @@ -63,9 +63,9 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__ . '/public', // publicPath - откуда будут обслуживаться активы - __DIR__ . '/views', // skinPath - где хранятся файлы шаблонов - 'assets', // assetPath - где будут храниться скомпилированные активы + __DIR__, // publicPath - корневая директория (где находится index.php) + 'views', // skinPath - путь шаблонов (поддерживает относительные/абсолютные) + 'assets', // assetPath - путь скомпилированных активов (поддерживает относительные/абсолютные) '.php' // fileExtension - расширение файла шаблона ]); @@ -74,6 +74,83 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` +## Конфигурация путей + +CommentTemplate обеспечивает интеллектуальную обработку путей для относительных и абсолютных путей: + +### Публичный путь + +**Публичный путь** — это корневая директория вашего веб-приложения, обычно где находится `index.php`. Это корень документа, откуда веб-серверы предоставляют файлы. + +```php +// Пример: если ваш index.php находится в /var/www/html/myapp/index.php +$template->setPublicPath('/var/www/html/myapp'); // Корневая директория + +// Пример Windows: если ваш index.php находится в C:\xampp\htdocs\myapp\index.php +$template->setPublicPath('C:\\xampp\\htdocs\\myapp'); +``` + +### Конфигурация пути шаблонов + +Путь шаблонов поддерживает как относительные, так и абсолютные пути: + +```php +$template = new Engine(); +$template->setPublicPath('/var/www/html/myapp'); // Корневая директория (где находится index.php) + +// Относительные пути - автоматически объединяются с публичным путем +$template->setSkinPath('views'); // → /var/www/html/myapp/views/ +$template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ + +// Абсолютные пути - используются как есть (Unix/Linux) +$template->setSkinPath('/var/www/templates'); // → /var/www/templates/ +$template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ + +// Абсолютные пути Windows +$template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ +$template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ + +// UNC пути (сетевые ресурсы Windows) +$template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ +``` + +### Конфигурация пути активов + +Путь активов также поддерживает как относительные, так и абсолютные пути: + +```php +// Относительные пути - автоматически объединяются с публичным путем +$template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ +$template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ + +// Абсолютные пути - используются как есть (Unix/Linux) +$template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ +$template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ + +// Абсолютные пути Windows +$template->setAssetPath('C:\\www\\static'); // → C:\www\static\ +$template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ + +// UNC пути (сетевые ресурсы Windows) +$template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ +``` + +**Умное определение путей:** + +- **Относительные пути**: Без начальных разделителей (`/`, `\`) или букв дисков +- **Unix абсолютные**: Начинаются с `/` (напр. `/var/www/assets`) +- **Windows абсолютные**: Начинаются с буквы диска (напр. `C:\www`, `D:/assets`) +- **UNC пути**: Начинаются с `\\` (напр. `\\server\share`) + +**Как это работает:** + +- Все пути автоматически разрешаются на основе типа (относительный vs абсолютный) +- Относительные пути объединяются с публичным путем +- `@css` и `@js` создают минимизированные файлы в: `{resolvedAssetPath}/css/` или `{resolvedAssetPath}/js/` +- `@asset` копирует отдельные файлы в: `{resolvedAssetPath}/{relativePath}` +- `@assetDir` копирует директории в: `{resolvedAssetPath}/{relativePath}` +- Умное кеширование: файлы копируются только когда источник новее цели + ## Директивы шаблонов ### Наследование макетов @@ -227,11 +304,31 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### Команды переменных +#### Цепочка нескольких фильтров ```html {$content|striptag|trim|escape} ``` +### Комментарии + +Комментарии шаблонов полностью удаляются из вывода и не появляются в финальном HTML: + +```html +{* Это однострочный комментарий шаблона *} + +{* + Это многострочный + комментарий шаблона + на несколько строк +*} + +

{$title}

+{* Отладочный комментарий: проверяем работает ли переменная title *} +

{$content}

+``` + +**Примечание**: Комментарии шаблонов `{* ... *}` отличаются от HTML комментариев ``. Комментарии шаблонов удаляются во время обработки и никогда не достигают браузера. + ## Структура примера проекта ``` diff --git a/content/v3/uk/awesome-plugins/comment_template.md b/content/v3/uk/awesome-plugins/comment_template.md index 236d9c25..828f7cc5 100644 --- a/content/v3/uk/awesome-plugins/comment_template.md +++ b/content/v3/uk/awesome-plugins/comment_template.md @@ -33,14 +33,14 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Де зберігаються ваші файли шаблонів - $engine->setTemplatesPath(__DIR__ . '/views'); + // Кореневий каталог (де знаходиться index.php) - кореневий документ вашого веб-застосунку + $engine->setPublicPath(__DIR__); - // Де ваші публічні активи будуть обслуговуватися - $engine->setPublicPath(__DIR__ . '/public'); + // Каталог файлів шаблонів - підтримує відносні та абсолютні шляхи + $engine->setSkinPath('views'); // Відносно публічного шляху - // Де зберігатимуться скомпільовані активи - $engine->setAssetPath('assets'); + // Де зберігатимуться скомпільовані активи - підтримує відносні та абсолютні шляхи + $engine->setAssetPath('assets'); // Відносно публічного шляху // Розширення файлу шаблону $engine->setFileExtension('.php'); @@ -63,9 +63,9 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__ . '/public', // publicPath - де активи будуть обслуговуватися - __DIR__ . '/views', // skinPath - де зберігаються файли шаблонів - 'assets', // assetPath - де зберігатимуться скомпільовані активи + __DIR__, // publicPath - кореневий каталог (де знаходиться index.php) + 'views', // skinPath - шлях шаблонів (підтримує відносні/абсолютні) + 'assets', // assetPath - шлях скомпільованих активів (підтримує відносні/абсолютні) '.php' // fileExtension - розширення файлу шаблону ]); @@ -74,6 +74,83 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` +## Конфігурація шляхів + +CommentTemplate забезпечує інтелектуальну обробку шляхів для відносних та абсолютних шляхів: + +### Публічний шлях + +**Публічний шлях** - це кореневий каталог вашого веб-застосунку, зазвичай де знаходиться `index.php`. Це кореневий документ, з якого веб-сервери надають файли. + +```php +// Приклад: якщо ваш index.php знаходиться в /var/www/html/myapp/index.php +$template->setPublicPath('/var/www/html/myapp'); // Кореневий каталог + +// Приклад Windows: якщо ваш index.php знаходиться в C:\xampp\htdocs\myapp\index.php +$template->setPublicPath('C:\\xampp\\htdocs\\myapp'); +``` + +### Конфігурація шляху шаблонів + +Шлях шаблонів підтримує як відносні, так і абсолютні шляхи: + +```php +$template = new Engine(); +$template->setPublicPath('/var/www/html/myapp'); // Кореневий каталог (де знаходиться index.php) + +// Відносні шляхи - автоматично поєднуються з публічним шляхом +$template->setSkinPath('views'); // → /var/www/html/myapp/views/ +$template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ + +// Абсолютні шляхи - використовуються як є (Unix/Linux) +$template->setSkinPath('/var/www/templates'); // → /var/www/templates/ +$template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ + +// Абсолютні шляхи Windows +$template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ +$template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ + +// UNC шляхи (мережеві ресурси Windows) +$template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ +``` + +### Конфігурація шляху активів + +Шлях активів також підтримує як відносні, так і абсолютні шляхи: + +```php +// Відносні шляхи - автоматично поєднуються з публічним шляхом +$template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ +$template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ + +// Абсолютні шляхи - використовуються як є (Unix/Linux) +$template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ +$template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ + +// Абсолютні шляхи Windows +$template->setAssetPath('C:\\www\\static'); // → C:\www\static\ +$template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ + +// UNC шляхи (мережеві ресурси Windows) +$template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ +``` + +**Розумне визначення шляхів:** + +- **Відносні шляхи**: Без початкових роздільників (`/`, `\`) або літер дисків +- **Unix абсолютні**: Починаються з `/` (напр. `/var/www/assets`) +- **Windows абсолютні**: Починаються з літери диска (напр. `C:\www`, `D:/assets`) +- **UNC шляхи**: Починаються з `\\` (напр. `\\server\share`) + +**Як це працює:** + +- Всі шляхи автоматично розв'язуються на основі типу (відносний vs абсолютний) +- Відносні шляхи поєднуються з публічним шляхом +- `@css` та `@js` створюють мінімізовані файли в: `{resolvedAssetPath}/css/` або `{resolvedAssetPath}/js/` +- `@asset` копіює окремі файли до: `{resolvedAssetPath}/{relativePath}` +- `@assetDir` копіює каталоги до: `{resolvedAssetPath}/{relativePath}` +- Розумне кешування: файли копіюються лише коли джерело новіше за призначення + ## Директиви шаблонів ### Успадкування макетів @@ -227,11 +304,31 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### Команди змінних +#### Ланцюжок кількох фільтрів ```html {$content|striptag|trim|escape} ``` +### Коментарі + +Коментарі шаблонів повністю видаляються з виводу і не з'являються в кінцевому HTML: + +```html +{* Це однорядковий коментар шаблону *} + +{* + Це багаторядковий + коментар шаблону + на кілька рядків +*} + +

{$title}

+{* Відлагоджувальний коментар: перевіряємо чи працює змінна title *} +

{$content}

+``` + +**Примітка**: Коментарі шаблонів `{* ... *}` відрізняються від HTML коментарів ``. Коментарі шаблонів видаляються під час обробки і ніколи не досягають браузера. + ## Приклад структури проекту ``` diff --git a/content/v3/zh/awesome-plugins/comment_template.md b/content/v3/zh/awesome-plugins/comment_template.md index ae0a701e..37b7dc4b 100644 --- a/content/v3/zh/awesome-plugins/comment_template.md +++ b/content/v3/zh/awesome-plugins/comment_template.md @@ -33,14 +33,14 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // 模板文件存储的位置 - $engine->setTemplatesPath(__DIR__ . '/views'); + // 根目录(index.php 所在位置)- Web 应用程序的文档根目录 + $engine->setPublicPath(__DIR__); - // 公共资产服务的路径 - $engine->setPublicPath(__DIR__ . '/public'); + // 模板文件目录 - 支持相对路径和绝对路径 + $engine->setSkinPath('views'); // 相对于公共路径 - // 编译资产的存储位置 - $engine->setAssetPath('assets'); + // 编译资产的存储位置 - 支持相对路径和绝对路径 + $engine->setAssetPath('assets'); // 相对于公共路径 // 模板文件扩展名 $engine->setFileExtension('.php'); @@ -63,9 +63,9 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__ . '/public', // publicPath - 资产服务的路径 - __DIR__ . '/views', // skinPath - 模板文件存储的位置 - 'assets', // assetPath - 编译资产的存储位置 + __DIR__, // publicPath - 根目录(index.php 所在位置) + 'views', // skinPath - 模板路径(支持相对/绝对路径) + 'assets', // assetPath - 编译资产路径(支持相对/绝对路径) '.php' // fileExtension - 模板文件扩展名 ]); @@ -74,6 +74,83 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` +## 路径配置 + +CommentTemplate 为相对路径和绝对路径提供智能路径处理: + +### 公共路径 + +**公共路径**是您的 Web 应用程序的根目录,通常是 `index.php` 所在的位置。这是 Web 服务器提供文件的文档根目录。 + +```php +// 示例:如果您的 index.php 位于 /var/www/html/myapp/index.php +$template->setPublicPath('/var/www/html/myapp'); // 根目录 + +// Windows 示例:如果您的 index.php 位于 C:\xampp\htdocs\myapp\index.php +$template->setPublicPath('C:\\xampp\\htdocs\\myapp'); +``` + +### 模板路径配置 + +模板路径支持相对路径和绝对路径: + +```php +$template = new Engine(); +$template->setPublicPath('/var/www/html/myapp'); // 根目录(index.php 所在位置) + +// 相对路径 - 自动与公共路径组合 +$template->setSkinPath('views'); // → /var/www/html/myapp/views/ +$template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ + +// 绝对路径 - 按原样使用(Unix/Linux) +$template->setSkinPath('/var/www/templates'); // → /var/www/templates/ +$template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ + +// Windows 绝对路径 +$template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ +$template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ + +// UNC 路径(Windows 网络共享) +$template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ +``` + +### 资产路径配置 + +资产路径也支持相对路径和绝对路径: + +```php +// 相对路径 - 自动与公共路径组合 +$template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ +$template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ + +// 绝对路径 - 按原样使用(Unix/Linux) +$template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ +$template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ + +// Windows 绝对路径 +$template->setAssetPath('C:\\www\\static'); // → C:\www\static\ +$template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ + +// UNC 路径(Windows 网络共享) +$template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ +``` + +**智能路径检测:** + +- **相对路径**:没有前导分隔符(`/`、`\`)或驱动器字母 +- **Unix 绝对**:以 `/` 开头(例如:`/var/www/assets`) +- **Windows 绝对**:以驱动器字母开头(例如:`C:\www`、`D:/assets`) +- **UNC 路径**:以 `\\` 开头(例如:`\\server\share`) + +**工作原理:** + +- 所有路径都根据类型自动解析(相对 vs 绝对) +- 相对路径与公共路径组合 +- `@css` 和 `@js` 在以下位置创建压缩文件:`{resolvedAssetPath}/css/` 或 `{resolvedAssetPath}/js/` +- `@asset` 将单个文件复制到:`{resolvedAssetPath}/{relativePath}` +- `@assetDir` 将目录复制到:`{resolvedAssetPath}/{relativePath}` +- 智能缓存:仅当源文件比目标文件新时才复制文件 + ## 模板指令 ### 布局继承 @@ -227,11 +304,31 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### 变量命令 +#### 链式多个过滤器 ```html {$content|striptag|trim|escape} ``` +### 注释 + +模板注释会从输出中完全删除,不会出现在最终的 HTML 中: + +```html +{* 这是单行模板注释 *} + +{* + 这是跨越多行的 + 多行 + 模板注释 +*} + +

{$title}

+{* 调试注释:检查 title 变量是否工作 *} +

{$content}

+``` + +**注意**:模板注释 `{* ... *}` 与 HTML 注释 `` 不同。模板注释在处理过程中被删除,不会到达浏览器。 + ## 示例项目结构 ``` From b03338767a996f875f16c47b20e3edc6852602f7 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Tue, 28 Oct 2025 07:12:21 -0600 Subject: [PATCH 17/36] added new example --- content/v3/en/examples.md | 1 + 1 file changed, 1 insertion(+) diff --git a/content/v3/en/examples.md b/content/v3/en/examples.md index f0bdf076..d91063e9 100644 --- a/content/v3/en/examples.md +++ b/content/v3/en/examples.md @@ -16,6 +16,7 @@ Community contributed examples: While these are not officially sponsored by the Flight Team, these could give you ideas on how to structure your own projects that are built with Flight! +- [ASC REST API Spell Checker](https://github.com/AlMosahih-ASC/asc-api-sample) - A lightweight REST API for Arabic spell checking built with FlightPHP and ArPHP library. This API provides Arabic text spell checking capabilities including misspelled word detection and correction suggestions. - [Eventify](https://github.com/ilhanklisura/eventify) - Eventify is a single-page app connecting event organizers with attendees. Built with PHP (FlightPHP), JavaScript, and MySQL, it features JWT auth, event management, and RESTful API docs using OpenAPI. - [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental is a single-page, mobile-friendly car rental web application built with PHP (FlightPHP), JavaScript, and MySQL. It supports user registration, browsing, and booking cars, while admins can manage cars, users, and bookings. The app features a REST API, JWT authentication, and a responsive design for a modern rental experience. - [Decay](https://github.com/boxybird/decay) - Flight v3 with HTMX and SleekDB all about zombies! ([Demo](https://decay.andrewrhyand.com)) From ccd7984a127b75cbf1abed43f556956a8c8b5729 Mon Sep 17 00:00:00 2001 From: Fredrik Sandebert Date: Fri, 31 Oct 2025 21:50:28 +0100 Subject: [PATCH 18/36] Update runway.md Removed function inputs --- content/v3/en/awesome-plugins/runway.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/v3/en/awesome-plugins/runway.md b/content/v3/en/awesome-plugins/runway.md index 8f925819..9f643dda 100644 --- a/content/v3/en/awesome-plugins/runway.md +++ b/content/v3/en/awesome-plugins/runway.md @@ -138,7 +138,7 @@ class ExampleCommand extends AbstractBaseCommand * * @return void */ - public function execute(string $controller) + public function execute() { $io = $this->app()->io(); @@ -190,4 +190,4 @@ If you need to customize the configuration for Runway, you can create a `.runway "app/my-unique-commands" ] } -``` \ No newline at end of file +``` From 6a669633f62b756ec7a64cf6c4e1edad80780eee Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Sat, 1 Nov 2025 16:05:56 -0600 Subject: [PATCH 19/36] Fixed missing PdoWrapper in APM docs --- content/v3/en/awesome-plugins/apm.md | 1 + 1 file changed, 1 insertion(+) diff --git a/content/v3/en/awesome-plugins/apm.md b/content/v3/en/awesome-plugins/apm.md index 9d81fa4a..b44fc88c 100644 --- a/content/v3/en/awesome-plugins/apm.md +++ b/content/v3/en/awesome-plugins/apm.md @@ -41,6 +41,7 @@ Drop this into your `index.php` or a `services.php` file to start tracking: ```php use flight\apm\logger\LoggerFactory; +use flight\database\PdoWrapper; use flight\Apm; $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); From 7734615f26fb03b40f33302e8c5b654b3b6a5d9f Mon Sep 17 00:00:00 2001 From: Paulo Ramos Date: Sat, 8 Nov 2025 18:01:49 -0500 Subject: [PATCH 20/36] Add new example vite-flightphp --- content/v3/de/examples.md | 1 + content/v3/en/examples.md | 1 + content/v3/es/examples.md | 1 + content/v3/fr/examples.md | 1 + content/v3/id/examples.md | 1 + content/v3/ja/examples.md | 1 + content/v3/ko/examples.md | 1 + content/v3/lv/examples.md | 1 + content/v3/pt/examples.md | 1 + content/v3/ru/examples.md | 1 + content/v3/uk/examples.md | 1 + content/v3/zh/examples.md | 1 + 12 files changed, 12 insertions(+) diff --git a/content/v3/de/examples.md b/content/v3/de/examples.md index 00f1b014..216f8e81 100644 --- a/content/v3/de/examples.md +++ b/content/v3/de/examples.md @@ -11,6 +11,7 @@ Von der Community beigetragene Beispiele: - [fleact](https://github.com/flightphp/fleact) - Ein FlightPHP-Starter-Kit mit ReactJS-Integration. - [flastro](https://github.com/flightphp/flastro) - Ein FlightPHP-Starter-Kit mit Astro-Integration. - [velt](https://github.com/flightphp/velt) - Velt ist eine schnelle und einfache Svelte-Starter-Vorlage mit einem FlightPHP-Backend. +- [vite-flightphp](https://github.com/pauloramoscuba/vite-flightphp) - FlightPHP mit modernem Frontend (Vite + Tailwind CSS) mit Hot Reload. ## Brauchen Sie etwas Inspiration? diff --git a/content/v3/en/examples.md b/content/v3/en/examples.md index d91063e9..5e4d0b49 100644 --- a/content/v3/en/examples.md +++ b/content/v3/en/examples.md @@ -11,6 +11,7 @@ Community contributed examples: - [fleact](https://github.com/flightphp/fleact) - A FlightPHP starter kit with ReactJS integration. - [flastro](https://github.com/flightphp/flastro) - A FlightPHP starter kit with Astro integration. - [velt](https://github.com/flightphp/velt) - Velt is a quick and easy Svelte starter template with a FlightPHP backend. +- [vite-flightphp](https://github.com/pauloramoscuba/vite-flightphp) - FlightPHP and modern frontend (Vite + Tailwind CSS) featuring hot reload. ## Need Some Inspiration? diff --git a/content/v3/es/examples.md b/content/v3/es/examples.md index 3dcf8760..9d79829b 100644 --- a/content/v3/es/examples.md +++ b/content/v3/es/examples.md @@ -11,6 +11,7 @@ Ejemplos contribuidos por la comunidad: - [fleact](https://github.com/flightphp/fleact) - Un kit de inicio de FlightPHP con integración de ReactJS. - [flastro](https://github.com/flightphp/flastro) - Un kit de inicio de FlightPHP con integración de Astro. - [velt](https://github.com/flightphp/velt) - Velt es una plantilla de inicio rápida y fácil de Svelte con un backend de FlightPHP. +- [vite-flightphp](https://github.com/pauloramoscuba/vite-flightphp) - FlightPHP y frontend moderno (Vite + Tailwind CSS) con hot reload (recarga en caliente). ## ¿Necesitas algo de inspiración? diff --git a/content/v3/fr/examples.md b/content/v3/fr/examples.md index 21e4a63a..9e2a3f7f 100644 --- a/content/v3/fr/examples.md +++ b/content/v3/fr/examples.md @@ -11,6 +11,7 @@ Exemples contributés par la communauté : - [fleact](https://github.com/flightphp/fleact) - Un kit de démarrage FlightPHP avec intégration ReactJS. - [flastro](https://github.com/flightphp/flastro) - Un kit de démarrage FlightPHP avec intégration Astro. - [velt](https://github.com/flightphp/velt) - Velt est un modèle de démarrage rapide et facile pour Svelte avec un backend FlightPHP. +- [vite-flightphp](https://github.com/pauloramoscuba/vite-flightphp) - FlightPHP et frontend moderne (Vite + Tailwind CSS) avec hot reload. ## Besoin d'inspiration ? diff --git a/content/v3/id/examples.md b/content/v3/id/examples.md index 500af2a7..3ae33c7e 100644 --- a/content/v3/id/examples.md +++ b/content/v3/id/examples.md @@ -11,6 +11,7 @@ Contoh yang disumbangkan oleh komunitas: - [fleact](https://github.com/flightphp/fleact) - Kit starter FlightPHP dengan integrasi ReactJS. - [flastro](https://github.com/flightphp/flastro) - Kit starter FlightPHP dengan integrasi Astro. - [velt](https://github.com/flightphp/velt) - Velt adalah template starter Svelte yang cepat dan mudah dengan backend FlightPHP. +- [vite-flightphp](https://github.com/pauloramoscuba/vite-flightphp) - FlightPHP dan frontend modern (Vite + Tailwind CSS) dengan hot reload. ## Butuh Inspirasi? diff --git a/content/v3/ja/examples.md b/content/v3/ja/examples.md index 881ab74e..c27c9f0d 100644 --- a/content/v3/ja/examples.md +++ b/content/v3/ja/examples.md @@ -11,6 +11,7 @@ - [fleact](https://github.com/flightphp/fleact) - ReactJS 統合の FlightPHP スターターキット。 - [flastro](https://github.com/flightphp/flastro) - Astro 統合の FlightPHP スターターキット。 - [velt](https://github.com/flightphp/velt) - Velt は FlightPHP バックエンド付きの Svelte スターターテンプレートで、クイックで簡単です。 +- [vite-flightphp](https://github.com/pauloramoscuba/vite-flightphp) - FlightPHPとViteとTailwind CSSを搭載したモダンフロントエンド、ホットリロード機能付き。 ## インスピレーションが必要ですか? diff --git a/content/v3/ko/examples.md b/content/v3/ko/examples.md index 861b6eb1..dc4dad2d 100644 --- a/content/v3/ko/examples.md +++ b/content/v3/ko/examples.md @@ -11,6 +11,7 @@ - [fleact](https://github.com/flightphp/fleact) - ReactJS 통합을 포함한 FlightPHP 스타터 키트입니다. - [flastro](https://github.com/flightphp/flastro) - Astro 통합을 포함한 FlightPHP 스타터 키트입니다. - [velt](https://github.com/flightphp/velt) - Velt는 FlightPHP 백엔드를 사용하는 빠르고 쉬운 Svelte 스타터 템플릿입니다. +- [vite-flightphp](https://github.com/pauloramoscuba/vite-flightphp) - FlightPHP와 모던 프론트엔드 (Vite + Tailwind CSS), 핫 리로드 기능 포함. ## 영감을 얻고 싶으신가요? diff --git a/content/v3/lv/examples.md b/content/v3/lv/examples.md index d1bbd8be..cc3d67c5 100644 --- a/content/v3/lv/examples.md +++ b/content/v3/lv/examples.md @@ -11,6 +11,7 @@ Kopienas sniegtie piemēri: - [fleact](https://github.com/flightphp/fleact) - FlightPHP starter komplekts ar ReactJS integrāciju. - [flastro](https://github.com/flightphp/flastro) - FlightPHP starter komplekts ar Astro integrāciju. - [velt](https://github.com/flightphp/velt) - Velt ir ātrs un viegls Svelte starter veidne ar FlightPHP backend. +- [vite-flightphp](https://github.com/pauloramoscuba/vite-flightphp) - FlightPHP ar mūsdienu front-end (Vite + Tailwind CSS) un karstās atjaunināšanas funkciju. ## Vai tev vajadzīga kāda iedvesma? diff --git a/content/v3/pt/examples.md b/content/v3/pt/examples.md index 30358c64..dd20ce34 100644 --- a/content/v3/pt/examples.md +++ b/content/v3/pt/examples.md @@ -11,6 +11,7 @@ Exemplos contribuídos pela comunidade: - [fleact](https://github.com/flightphp/fleact) - Um kit inicial FlightPHP com integração ReactJS. - [flastro](https://github.com/flightphp/flastro) - Um kit inicial FlightPHP com integração Astro. - [velt](https://github.com/flightphp/velt) - Velt é um template inicial rápido e fácil para Svelte com backend FlightPHP. +- [vite-flightphp](https://github.com/pauloramoscuba/vite-flightphp) - FlightPHP e frontend moderno (Vite + Tailwind CSS) com hot reload. ## Precisa de Alguma Inspiração? diff --git a/content/v3/ru/examples.md b/content/v3/ru/examples.md index d50aa5f7..e75114ea 100644 --- a/content/v3/ru/examples.md +++ b/content/v3/ru/examples.md @@ -11,6 +11,7 @@ - [fleact](https://github.com/flightphp/fleact) - Стартовый комплект FlightPHP с интеграцией ReactJS. - [flastro](https://github.com/flightphp/flastro) - Стартовый комплект FlightPHP с интеграцией Astro. - [velt](https://github.com/flightphp/velt) - Velt — это быстрый и простой шаблон Svelte для старта с бэкендом на FlightPHP. +- [vite-flightphp](https://github.com/pauloramoscuba/vite-flightphp) - FlightPHP и современный фронтенд (Vite + Tailwind CSS) с поддержкой hot reload. ## Нужен ли вам источник вдохновения? diff --git a/content/v3/uk/examples.md b/content/v3/uk/examples.md index 56ecfe79..459d8424 100644 --- a/content/v3/uk/examples.md +++ b/content/v3/uk/examples.md @@ -11,6 +11,7 @@ - [fleact](https://github.com/flightphp/fleact) - Стартер-кіт FlightPHP з інтеграцією ReactJS. - [flastro](https://github.com/flightphp/flastro) - Стартер-кіт FlightPHP з інтеграцією Astro. - [velt](https://github.com/flightphp/velt) - Velt — це швидкий і простий шаблон стартера Svelte з бекендом FlightPHP. +- [vite-flightphp](https://github.com/pauloramoscuba/vite-flightphp) - FlightPHP та сучасний фронтенд (Vite + Tailwind CSS) з підтримкою hot reload. ## Потрібне натхнення? diff --git a/content/v3/zh/examples.md b/content/v3/zh/examples.md index 01a02082..2e592877 100644 --- a/content/v3/zh/examples.md +++ b/content/v3/zh/examples.md @@ -11,6 +11,7 @@ - [fleact](https://github.com/flightphp/fleact) - 一个带有 ReactJS 集成的 FlightPHP 启动套件。 - [flastro](https://github.com/flightphp/flastro) - 一个带有 Astro 集成的 FlightPHP 启动套件。 - [velt](https://github.com/flightphp/velt) - Velt 是一个快速易用的 Svelte 启动模板,带有 FlightPHP 后端。 +- [vite-flightphp](https://github.com/pauloramoscuba/vite-flightphp) - FlightPHP 和现代前端技术(Vite + Tailwind CSS),支持热重载功能。 ## 需要一些灵感吗? From 711c0e523c2697d811ce720289674a45ee528485 Mon Sep 17 00:00:00 2001 From: Fredrik Sandebert Date: Wed, 12 Nov 2025 19:46:15 +0100 Subject: [PATCH 21/36] Update permissions.md Fixed minor typo --- content/v3/en/awesome-plugins/permissions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/v3/en/awesome-plugins/permissions.md b/content/v3/en/awesome-plugins/permissions.md index ab334554..b0346054 100644 --- a/content/v3/en/awesome-plugins/permissions.md +++ b/content/v3/en/awesome-plugins/permissions.md @@ -57,7 +57,7 @@ class SomeController { ``` You can also use this to track if they have permission to do something in your application. -For instance, if your have a way that users can interact with posting on your software, you can +For instance, if you have a way that users can interact with posting on your software, you can check if they have permission to perform certain actions. ```php From 9a7d91e522131e7cdd5dd07ec9dbf8e2ff8abb25 Mon Sep 17 00:00:00 2001 From: KnifeLemon Date: Thu, 13 Nov 2025 14:42:22 +0900 Subject: [PATCH 22/36] Add Tracy Debugger integration section to CommentTemplate docs --- .../v3/de/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/en/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/es/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/fr/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/id/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/ja/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/ko/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/lv/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/pt/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/ru/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/uk/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/zh/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ 12 files changed, 696 insertions(+) diff --git a/content/v3/de/awesome-plugins/comment_template.md b/content/v3/de/awesome-plugins/comment_template.md index 86457b5e..43dfc87b 100644 --- a/content/v3/de/awesome-plugins/comment_template.md +++ b/content/v3/de/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` kopiert Verzeichnisse nach: `{resolvedAssetPath}/{relativePath}` - Intelligente Zwischenspeicherung: Dateien werden nur kopiert, wenn die Quelle neuer ist als das Ziel +## Tracy Debugger Integration + +CommentTemplate beinhaltet Integration mit [Tracy Debugger](https://tracy.nette.org/) für Entwicklungs-Logging und Debugging. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Installation + +```bash +composer require tracy/tracy +``` + +### Verwendung + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Debug-Panel-Funktionen + +CommentTemplate fügt Tracys Debug-Leiste ein benutzerdefiniertes Panel mit vier Tabs hinzu: + +- **Overview**: Konfiguration, Leistungsmetriken und Zähler +- **Assets**: CSS/JS-Kompilierungsdetails mit Kompressionsraten +- **Variables**: Original- und transformierte Werte mit angewendeten Filtern +- **Timeline**: Chronologische Ansicht aller Template-Operationen + +### Was wird protokolliert + +- Template-Rendering (Start/Ende, Dauer, Layouts, Imports) +- Asset-Kompilierung (CSS/JS-Dateien, Größen, Kompressionsraten) +- Variablenverarbeitung (Original/transformierte Werte, Filter) +- Asset-Operationen (Base64-Kodierung, Dateikopieren) +- Leistungsmetriken (Dauer, Speicherverbrauch) + +**Hinweis:** Keine Leistungseinbußen, wenn Tracy nicht installiert oder deaktiviert ist. + +Siehe [vollständiges funktionierendes Beispiel mit Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Template-Direktiven ### Layout-Vererbung diff --git a/content/v3/en/awesome-plugins/comment_template.md b/content/v3/en/awesome-plugins/comment_template.md index ce337a9f..2a74586b 100644 --- a/content/v3/en/awesome-plugins/comment_template.md +++ b/content/v3/en/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` copies directories to: `{resolvedAssetPath}/{relativePath}` - Smart caching: files only copied when source is newer than destination +## Tracy Debugger Integration + +CommentTemplate includes integration with [Tracy Debugger](https://tracy.nette.org/) for development logging and debugging. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Installation + +```bash +composer require tracy/tracy +``` + +### Usage + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Debug Panel Features + +CommentTemplate adds a custom panel to Tracy's debug bar with four tabs: + +- **Overview**: Configuration, performance metrics, and counts +- **Assets**: CSS/JS compilation details with compression ratios +- **Variables**: Original and transformed values with applied filters +- **Timeline**: Chronological view of all template operations + +### What Gets Logged + +- Template rendering (start/end, duration, layouts, imports) +- Asset compilation (CSS/JS files, sizes, compression ratios) +- Variable processing (original/transformed values, filters) +- Asset operations (base64 encoding, file copying) +- Performance metrics (duration, memory usage) + +**Note:** Zero performance impact when Tracy is not installed or disabled. + +See [complete working example with Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Template Directives ### Layout Inheritance diff --git a/content/v3/es/awesome-plugins/comment_template.md b/content/v3/es/awesome-plugins/comment_template.md index 16a9a152..53beee68 100644 --- a/content/v3/es/awesome-plugins/comment_template.md +++ b/content/v3/es/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` copia directorios a: `{resolvedAssetPath}/{relativePath}` - Caché inteligente: los archivos solo se copian cuando el origen es más nuevo que el destino +## Integración con Tracy Debugger + +CommentTemplate incluye integración con [Tracy Debugger](https://tracy.nette.org/) para registro y depuración en desarrollo. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Instalación + +```bash +composer require tracy/tracy +``` + +### Uso + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Características del Panel de Depuración + +CommentTemplate agrega un panel personalizado a la barra de depuración de Tracy con cuatro pestañas: + +- **Overview**: Configuración, métricas de rendimiento y contadores +- **Assets**: Detalles de compilación CSS/JS con ratios de compresión +- **Variables**: Valores originales y transformados con filtros aplicados +- **Timeline**: Vista cronológica de todas las operaciones de plantilla + +### Qué se Registra + +- Renderizado de plantillas (inicio/fin, duración, diseños, importaciones) +- Compilación de activos (archivos CSS/JS, tamaños, ratios de compresión) +- Procesamiento de variables (valores originales/transformados, filtros) +- Operaciones de activos (codificación base64, copia de archivos) +- Métricas de rendimiento (duración, uso de memoria) + +**Nota:** Cero impacto en el rendimiento cuando Tracy no está instalado o deshabilitado. + +Consulte el [ejemplo completo funcional con Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Directivas de Plantilla ### Herencia de Diseño diff --git a/content/v3/fr/awesome-plugins/comment_template.md b/content/v3/fr/awesome-plugins/comment_template.md index 0a26bb97..7ee8eb08 100644 --- a/content/v3/fr/awesome-plugins/comment_template.md +++ b/content/v3/fr/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` copie les répertoires vers : `{resolvedAssetPath}/{relativePath}` - Cache intelligent : les fichiers ne sont copiés que lorsque la source est plus récente que la destination +## Intégration avec Tracy Debugger + +CommentTemplate inclut une intégration avec [Tracy Debugger](https://tracy.nette.org/) pour la journalisation et le débogage en développement. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Installation + +```bash +composer require tracy/tracy +``` + +### Utilisation + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Fonctionnalités du Panneau de Débogage + +CommentTemplate ajoute un panneau personnalisé à la barre de débogage de Tracy avec quatre onglets : + +- **Overview** : Configuration, métriques de performance et compteurs +- **Assets** : Détails de compilation CSS/JS avec ratios de compression +- **Variables** : Valeurs originales et transformées avec filtres appliqués +- **Timeline** : Vue chronologique de toutes les opérations de template + +### Ce Qui Est Enregistré + +- Rendu de template (début/fin, durée, layouts, imports) +- Compilation d'actifs (fichiers CSS/JS, tailles, ratios de compression) +- Traitement des variables (valeurs originales/transformées, filtres) +- Opérations sur les actifs (encodage base64, copie de fichiers) +- Métriques de performance (durée, utilisation de la mémoire) + +**Note :** Aucun impact sur les performances lorsque Tracy n'est pas installé ou désactivé. + +Consultez [l'exemple complet fonctionnel avec Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Directives de Template ### Héritage de Layout diff --git a/content/v3/id/awesome-plugins/comment_template.md b/content/v3/id/awesome-plugins/comment_template.md index ea132625..2a92f26d 100644 --- a/content/v3/id/awesome-plugins/comment_template.md +++ b/content/v3/id/awesome-plugins/comment_template.md @@ -147,6 +147,64 @@ $engine->setAssetPath('/app/public/assets'); CommentTemplate secara otomatis mendeteksi jenis path dan menanganinya dengan benar, memberikan fleksibilitas maksimum untuk setup deployment yang berbeda. +## Integrasi Tracy Debugger + +CommentTemplate menyertakan integrasi dengan [Tracy Debugger](https://tracy.nette.org/) untuk logging dan debugging pengembangan. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Instalasi + +```bash +composer require tracy/tracy +``` + +### Penggunaan + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Fitur Panel Debug + +CommentTemplate menambahkan panel kustom ke debug bar Tracy dengan empat tab: + +- **Overview**: Konfigurasi, metrik kinerja, dan penghitungan +- **Assets**: Detail kompilasi CSS/JS dengan rasio kompresi +- **Variables**: Nilai asli dan yang ditransformasi dengan filter yang diterapkan +- **Timeline**: Tampilan kronologis dari semua operasi template + +### Apa yang Dicatat + +- Rendering template (mulai/selesai, durasi, layout, impor) +- Kompilasi aset (file CSS/JS, ukuran, rasio kompresi) +- Pemrosesan variabel (nilai asli/yang ditransformasi, filter) +- Operasi aset (encoding base64, penyalinan file) +- Metrik kinerja (durasi, penggunaan memori) + +**Catatan:** Tidak ada dampak kinerja ketika Tracy tidak diinstal atau dinonaktifkan. + +Lihat [contoh lengkap yang berfungsi dengan Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Direktif Template ### Pewarisan Layout diff --git a/content/v3/ja/awesome-plugins/comment_template.md b/content/v3/ja/awesome-plugins/comment_template.md index a5c528dd..e927eb6d 100644 --- a/content/v3/ja/awesome-plugins/comment_template.md +++ b/content/v3/ja/awesome-plugins/comment_template.md @@ -201,6 +201,64 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` +## Tracy デバッガー統合 + +CommentTemplateは開発ログとデバッグのために[Tracy Debugger](https://tracy.nette.org/)との統合を含んでいます。 + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### インストール + +```bash +composer require tracy/tracy +``` + +### 使用方法 + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### デバッグパネル機能 + +CommentTemplateは4つのタブを持つカスタムパネルをTracyのデバッグバーに追加します: + +- **Overview**: 設定、パフォーマンス指標、カウント +- **Assets**: 圧縮率を含むCSS/JSコンパイルの詳細 +- **Variables**: 適用されたフィルターを含む元の値と変換された値 +- **Timeline**: すべてのテンプレート操作の時系列ビュー + +### ログに記録される内容 + +- テンプレートレンダリング(開始/終了、期間、レイアウト、インポート) +- アセットコンパイル(CSS/JSファイル、サイズ、圧縮率) +- 変数処理(元の値/変換された値、フィルター) +- アセット操作(base64エンコーディング、ファイルコピー) +- パフォーマンス指標(期間、メモリ使用量) + +**注意:** Tracyがインストールされていないか無効になっている場合、パフォーマンスへの影響はゼロです。 + +[Flight PHPでの完全な動作例](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp)を参照してください。 + ## テンプレートディレクティブ ### レイアウトの継承 diff --git a/content/v3/ko/awesome-plugins/comment_template.md b/content/v3/ko/awesome-plugins/comment_template.md index a419aec9..1a7e97c3 100644 --- a/content/v3/ko/awesome-plugins/comment_template.md +++ b/content/v3/ko/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir`은 디렉토리를 다음 위치에 복사합니다: `{resolvedAssetPath}/{relativePath}` - 스마트 캐싱: 소스가 대상보다 최신인 경우에만 파일이 복사됩니다 +## Tracy 디버거 통합 + +CommentTemplate은 개발 로깅 및 디버깅을 위해 [Tracy Debugger](https://tracy.nette.org/)와 통합됩니다. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### 설치 + +```bash +composer require tracy/tracy +``` + +### 사용법 + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### 디버그 패널 기능 + +CommentTemplate은 Tracy의 디버그 바에 4개의 탭이 있는 사용자 정의 패널을 추가합니다: + +- **Overview**: 구성, 성능 지표 및 카운트 +- **Assets**: 압축률이 포함된 CSS/JS 컴파일 세부정보 +- **Variables**: 적용된 필터가 있는 원본 및 변환된 값 +- **Timeline**: 모든 템플릿 작업의 시간순 보기 + +### 로깅되는 항목 + +- 템플릿 렌더링 (시작/종료, 기간, 레이아웃, 가져오기) +- 자산 컴파일 (CSS/JS 파일, 크기, 압축률) +- 변수 처리 (원본/변환된 값, 필터) +- 자산 작업 (base64 인코딩, 파일 복사) +- 성능 지표 (기간, 메모리 사용량) + +**참고:** Tracy가 설치되지 않았거나 비활성화된 경우 성능에 영향이 없습니다. + +[Flight PHP와 함께 사용하는 완전한 예제](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp)를 참조하세요. + ## 템플릿 지시어 ### 레이아웃 상속 diff --git a/content/v3/lv/awesome-plugins/comment_template.md b/content/v3/lv/awesome-plugins/comment_template.md index d83f927b..7ab69fc5 100644 --- a/content/v3/lv/awesome-plugins/comment_template.md +++ b/content/v3/lv/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` kopē direktorijus uz: `{resolvedAssetPath}/{relativePath}` - Viedā kešošana: faili tiek kopēti tikai tad, ja avots ir jaunāks nekā mērķis +## Tracy atkļūdotāja integrācija + +CommentTemplate ietver integrāciju ar [Tracy Debugger](https://tracy.nette.org/) izstrādes reģistrēšanai un atkļūdošanai. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Instalācija + +```bash +composer require tracy/tracy +``` + +### Lietošana + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Atkļūdošanas paneļa funkcijas + +CommentTemplate pievieno pielāgotu paneli Tracy atkļūdošanas joslai ar četrām cilnēm: + +- **Overview**: Konfigurācija, veiktspējas metrika un skaitītāji +- **Assets**: CSS/JS kompilācijas detaļas ar saspiešanas proporcijām +- **Variables**: Oriģinālās un pārveidotās vērtības ar lietotajiem filtriem +- **Timeline**: Hronoloģisks visu veidņu operāciju skats + +### Kas tiek reģistrēts + +- Veidņu renderēšana (sākums/beigas, ilgums, izkārtojumi, importi) +- Aktīvu kompilācija (CSS/JS faili, izmēri, saspiešanas proporcijas) +- Mainīgo apstrāde (oriģinālās/pārveidotās vērtības, filtri) +- Aktīvu operācijas (base64 kodēšana, failu kopēšana) +- Veiktspējas metrika (ilgums, atmiņas izmantošana) + +**Piezīme:** Nulles ietekme uz veiktspēju, ja Tracy nav instalēts vai ir atspējots. + +Skatiet [pilnīgu darba piemēru ar Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Veidnes direktīvas ### Izkārtojuma mantojums diff --git a/content/v3/pt/awesome-plugins/comment_template.md b/content/v3/pt/awesome-plugins/comment_template.md index 8c1899f6..4541b144 100644 --- a/content/v3/pt/awesome-plugins/comment_template.md +++ b/content/v3/pt/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` copia diretórios para: `{resolvedAssetPath}/{relativePath}` - Cache inteligente: arquivos só são copiados quando a fonte é mais nova que o destino +## Integração com Tracy Debugger + +CommentTemplate inclui integração com [Tracy Debugger](https://tracy.nette.org/) para registro e depuração em desenvolvimento. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Instalação + +```bash +composer require tracy/tracy +``` + +### Uso + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Recursos do Painel de Depuração + +CommentTemplate adiciona um painel personalizado à barra de depuração do Tracy com quatro abas: + +- **Overview**: Configuração, métricas de desempenho e contadores +- **Assets**: Detalhes de compilação CSS/JS com taxas de compressão +- **Variables**: Valores originais e transformados com filtros aplicados +- **Timeline**: Visualização cronológica de todas as operações de template + +### O Que É Registrado + +- Renderização de template (início/fim, duração, layouts, importações) +- Compilação de ativos (arquivos CSS/JS, tamanhos, taxas de compressão) +- Processamento de variáveis (valores originais/transformados, filtros) +- Operações de ativos (codificação base64, cópia de arquivos) +- Métricas de desempenho (duração, uso de memória) + +**Nota:** Nenhum impacto no desempenho quando Tracy não está instalado ou desabilitado. + +Consulte o [exemplo completo funcional com Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Diretivas de Template ### Herança de Layout diff --git a/content/v3/ru/awesome-plugins/comment_template.md b/content/v3/ru/awesome-plugins/comment_template.md index 3ce888c6..8ef581ce 100644 --- a/content/v3/ru/awesome-plugins/comment_template.md +++ b/content/v3/ru/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` копирует директории в: `{resolvedAssetPath}/{relativePath}` - Умное кеширование: файлы копируются только когда источник новее цели +## Интеграция с Tracy Debugger + +CommentTemplate включает интеграцию с [Tracy Debugger](https://tracy.nette.org/) для логирования и отладки в разработке. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Установка + +```bash +composer require tracy/tracy +``` + +### Использование + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Функции панели отладки + +CommentTemplate добавляет пользовательскую панель в панель отладки Tracy с четырьмя вкладками: + +- **Overview**: Конфигурация, метрики производительности и счетчики +- **Assets**: Детали компиляции CSS/JS с коэффициентами сжатия +- **Variables**: Исходные и преобразованные значения с примененными фильтрами +- **Timeline**: Хронологический вид всех операций шаблонов + +### Что логируется + +- Рендеринг шаблонов (начало/конец, длительность, макеты, импорты) +- Компиляция ассетов (файлы CSS/JS, размеры, коэффициенты сжатия) +- Обработка переменных (исходные/преобразованные значения, фильтры) +- Операции с ассетами (кодирование base64, копирование файлов) +- Метрики производительности (длительность, использование памяти) + +**Примечание:** Нулевое влияние на производительность, когда Tracy не установлен или отключен. + +См. [полный рабочий пример с Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Директивы шаблонов ### Наследование макетов diff --git a/content/v3/uk/awesome-plugins/comment_template.md b/content/v3/uk/awesome-plugins/comment_template.md index 828f7cc5..ba0cddf2 100644 --- a/content/v3/uk/awesome-plugins/comment_template.md +++ b/content/v3/uk/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` копіює каталоги до: `{resolvedAssetPath}/{relativePath}` - Розумне кешування: файли копіюються лише коли джерело новіше за призначення +## Інтеграція з Tracy Debugger + +CommentTemplate включає інтеграцію з [Tracy Debugger](https://tracy.nette.org/) для логування та налагодження під час розробки. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Встановлення + +```bash +composer require tracy/tracy +``` + +### Використання + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Функції панелі налагодження + +CommentTemplate додає користувацьку панель до панелі налагодження Tracy з чотирма вкладками: + +- **Overview**: Конфігурація, метрики продуктивності та лічильники +- **Assets**: Деталі компіляції CSS/JS з коефіцієнтами стиснення +- **Variables**: Оригінальні та перетворені значення з застосованими фільтрами +- **Timeline**: Хронологічний вигляд усіх операцій шаблонів + +### Що логується + +- Рендеринг шаблонів (початок/кінець, тривалість, макети, імпорти) +- Компіляція активів (файли CSS/JS, розміри, коефіцієнти стиснення) +- Обробка змінних (оригінальні/перетворені значення, фільтри) +- Операції з активами (кодування base64, копіювання файлів) +- Метрики продуктивності (тривалість, використання пам'яті) + +**Примітка:** Нульовий вплив на продуктивність, коли Tracy не встановлено або вимкнено. + +Див. [повний робочий приклад з Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Директиви шаблонів ### Успадкування макетів diff --git a/content/v3/zh/awesome-plugins/comment_template.md b/content/v3/zh/awesome-plugins/comment_template.md index 37b7dc4b..f64ebb6b 100644 --- a/content/v3/zh/awesome-plugins/comment_template.md +++ b/content/v3/zh/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` 将目录复制到:`{resolvedAssetPath}/{relativePath}` - 智能缓存:仅当源文件比目标文件新时才复制文件 +## Tracy 调试器集成 + +CommentTemplate 包含与 [Tracy Debugger](https://tracy.nette.org/) 的集成,用于开发日志记录和调试。 + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### 安装 + +```bash +composer require tracy/tracy +``` + +### 使用方法 + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### 调试面板功能 + +CommentTemplate 为 Tracy 的调试栏添加了一个包含四个选项卡的自定义面板: + +- **Overview**:配置、性能指标和计数 +- **Assets**:包含压缩率的 CSS/JS 编译详情 +- **Variables**:包含应用过滤器的原始值和转换值 +- **Timeline**:所有模板操作的时间顺序视图 + +### 记录的内容 + +- 模板渲染(开始/结束、持续时间、布局、导入) +- 资源编译(CSS/JS 文件、大小、压缩率) +- 变量处理(原始/转换值、过滤器) +- 资源操作(base64 编码、文件复制) +- 性能指标(持续时间、内存使用) + +**注意:** 当 Tracy 未安装或被禁用时,对性能没有任何影响。 + +请参阅 [Flight PHP 完整工作示例](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp)。 + ## 模板指令 ### 布局继承 From b46ec602668cf405c67f6a08f35d4addd5f9032a Mon Sep 17 00:00:00 2001 From: KnifeLemon Date: Thu, 13 Nov 2025 14:44:20 +0900 Subject: [PATCH 23/36] Add Tracy Debugger integration section to CommentTemplate docs --- .../v3/de/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/en/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/es/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/fr/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/id/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/ja/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/ko/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/lv/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/pt/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/ru/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/uk/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ .../v3/zh/awesome-plugins/comment_template.md | 58 +++++++++++++++++++ 12 files changed, 696 insertions(+) diff --git a/content/v3/de/awesome-plugins/comment_template.md b/content/v3/de/awesome-plugins/comment_template.md index 86457b5e..43dfc87b 100644 --- a/content/v3/de/awesome-plugins/comment_template.md +++ b/content/v3/de/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` kopiert Verzeichnisse nach: `{resolvedAssetPath}/{relativePath}` - Intelligente Zwischenspeicherung: Dateien werden nur kopiert, wenn die Quelle neuer ist als das Ziel +## Tracy Debugger Integration + +CommentTemplate beinhaltet Integration mit [Tracy Debugger](https://tracy.nette.org/) für Entwicklungs-Logging und Debugging. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Installation + +```bash +composer require tracy/tracy +``` + +### Verwendung + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Debug-Panel-Funktionen + +CommentTemplate fügt Tracys Debug-Leiste ein benutzerdefiniertes Panel mit vier Tabs hinzu: + +- **Overview**: Konfiguration, Leistungsmetriken und Zähler +- **Assets**: CSS/JS-Kompilierungsdetails mit Kompressionsraten +- **Variables**: Original- und transformierte Werte mit angewendeten Filtern +- **Timeline**: Chronologische Ansicht aller Template-Operationen + +### Was wird protokolliert + +- Template-Rendering (Start/Ende, Dauer, Layouts, Imports) +- Asset-Kompilierung (CSS/JS-Dateien, Größen, Kompressionsraten) +- Variablenverarbeitung (Original/transformierte Werte, Filter) +- Asset-Operationen (Base64-Kodierung, Dateikopieren) +- Leistungsmetriken (Dauer, Speicherverbrauch) + +**Hinweis:** Keine Leistungseinbußen, wenn Tracy nicht installiert oder deaktiviert ist. + +Siehe [vollständiges funktionierendes Beispiel mit Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Template-Direktiven ### Layout-Vererbung diff --git a/content/v3/en/awesome-plugins/comment_template.md b/content/v3/en/awesome-plugins/comment_template.md index ce337a9f..2a74586b 100644 --- a/content/v3/en/awesome-plugins/comment_template.md +++ b/content/v3/en/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` copies directories to: `{resolvedAssetPath}/{relativePath}` - Smart caching: files only copied when source is newer than destination +## Tracy Debugger Integration + +CommentTemplate includes integration with [Tracy Debugger](https://tracy.nette.org/) for development logging and debugging. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Installation + +```bash +composer require tracy/tracy +``` + +### Usage + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Debug Panel Features + +CommentTemplate adds a custom panel to Tracy's debug bar with four tabs: + +- **Overview**: Configuration, performance metrics, and counts +- **Assets**: CSS/JS compilation details with compression ratios +- **Variables**: Original and transformed values with applied filters +- **Timeline**: Chronological view of all template operations + +### What Gets Logged + +- Template rendering (start/end, duration, layouts, imports) +- Asset compilation (CSS/JS files, sizes, compression ratios) +- Variable processing (original/transformed values, filters) +- Asset operations (base64 encoding, file copying) +- Performance metrics (duration, memory usage) + +**Note:** Zero performance impact when Tracy is not installed or disabled. + +See [complete working example with Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Template Directives ### Layout Inheritance diff --git a/content/v3/es/awesome-plugins/comment_template.md b/content/v3/es/awesome-plugins/comment_template.md index 16a9a152..53beee68 100644 --- a/content/v3/es/awesome-plugins/comment_template.md +++ b/content/v3/es/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` copia directorios a: `{resolvedAssetPath}/{relativePath}` - Caché inteligente: los archivos solo se copian cuando el origen es más nuevo que el destino +## Integración con Tracy Debugger + +CommentTemplate incluye integración con [Tracy Debugger](https://tracy.nette.org/) para registro y depuración en desarrollo. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Instalación + +```bash +composer require tracy/tracy +``` + +### Uso + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Características del Panel de Depuración + +CommentTemplate agrega un panel personalizado a la barra de depuración de Tracy con cuatro pestañas: + +- **Overview**: Configuración, métricas de rendimiento y contadores +- **Assets**: Detalles de compilación CSS/JS con ratios de compresión +- **Variables**: Valores originales y transformados con filtros aplicados +- **Timeline**: Vista cronológica de todas las operaciones de plantilla + +### Qué se Registra + +- Renderizado de plantillas (inicio/fin, duración, diseños, importaciones) +- Compilación de activos (archivos CSS/JS, tamaños, ratios de compresión) +- Procesamiento de variables (valores originales/transformados, filtros) +- Operaciones de activos (codificación base64, copia de archivos) +- Métricas de rendimiento (duración, uso de memoria) + +**Nota:** Cero impacto en el rendimiento cuando Tracy no está instalado o deshabilitado. + +Consulte el [ejemplo completo funcional con Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Directivas de Plantilla ### Herencia de Diseño diff --git a/content/v3/fr/awesome-plugins/comment_template.md b/content/v3/fr/awesome-plugins/comment_template.md index 0a26bb97..7ee8eb08 100644 --- a/content/v3/fr/awesome-plugins/comment_template.md +++ b/content/v3/fr/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` copie les répertoires vers : `{resolvedAssetPath}/{relativePath}` - Cache intelligent : les fichiers ne sont copiés que lorsque la source est plus récente que la destination +## Intégration avec Tracy Debugger + +CommentTemplate inclut une intégration avec [Tracy Debugger](https://tracy.nette.org/) pour la journalisation et le débogage en développement. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Installation + +```bash +composer require tracy/tracy +``` + +### Utilisation + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Fonctionnalités du Panneau de Débogage + +CommentTemplate ajoute un panneau personnalisé à la barre de débogage de Tracy avec quatre onglets : + +- **Overview** : Configuration, métriques de performance et compteurs +- **Assets** : Détails de compilation CSS/JS avec ratios de compression +- **Variables** : Valeurs originales et transformées avec filtres appliqués +- **Timeline** : Vue chronologique de toutes les opérations de template + +### Ce Qui Est Enregistré + +- Rendu de template (début/fin, durée, layouts, imports) +- Compilation d'actifs (fichiers CSS/JS, tailles, ratios de compression) +- Traitement des variables (valeurs originales/transformées, filtres) +- Opérations sur les actifs (encodage base64, copie de fichiers) +- Métriques de performance (durée, utilisation de la mémoire) + +**Note :** Aucun impact sur les performances lorsque Tracy n'est pas installé ou désactivé. + +Consultez [l'exemple complet fonctionnel avec Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Directives de Template ### Héritage de Layout diff --git a/content/v3/id/awesome-plugins/comment_template.md b/content/v3/id/awesome-plugins/comment_template.md index ea132625..2a92f26d 100644 --- a/content/v3/id/awesome-plugins/comment_template.md +++ b/content/v3/id/awesome-plugins/comment_template.md @@ -147,6 +147,64 @@ $engine->setAssetPath('/app/public/assets'); CommentTemplate secara otomatis mendeteksi jenis path dan menanganinya dengan benar, memberikan fleksibilitas maksimum untuk setup deployment yang berbeda. +## Integrasi Tracy Debugger + +CommentTemplate menyertakan integrasi dengan [Tracy Debugger](https://tracy.nette.org/) untuk logging dan debugging pengembangan. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Instalasi + +```bash +composer require tracy/tracy +``` + +### Penggunaan + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Fitur Panel Debug + +CommentTemplate menambahkan panel kustom ke debug bar Tracy dengan empat tab: + +- **Overview**: Konfigurasi, metrik kinerja, dan penghitungan +- **Assets**: Detail kompilasi CSS/JS dengan rasio kompresi +- **Variables**: Nilai asli dan yang ditransformasi dengan filter yang diterapkan +- **Timeline**: Tampilan kronologis dari semua operasi template + +### Apa yang Dicatat + +- Rendering template (mulai/selesai, durasi, layout, impor) +- Kompilasi aset (file CSS/JS, ukuran, rasio kompresi) +- Pemrosesan variabel (nilai asli/yang ditransformasi, filter) +- Operasi aset (encoding base64, penyalinan file) +- Metrik kinerja (durasi, penggunaan memori) + +**Catatan:** Tidak ada dampak kinerja ketika Tracy tidak diinstal atau dinonaktifkan. + +Lihat [contoh lengkap yang berfungsi dengan Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Direktif Template ### Pewarisan Layout diff --git a/content/v3/ja/awesome-plugins/comment_template.md b/content/v3/ja/awesome-plugins/comment_template.md index a5c528dd..e927eb6d 100644 --- a/content/v3/ja/awesome-plugins/comment_template.md +++ b/content/v3/ja/awesome-plugins/comment_template.md @@ -201,6 +201,64 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` +## Tracy デバッガー統合 + +CommentTemplateは開発ログとデバッグのために[Tracy Debugger](https://tracy.nette.org/)との統合を含んでいます。 + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### インストール + +```bash +composer require tracy/tracy +``` + +### 使用方法 + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### デバッグパネル機能 + +CommentTemplateは4つのタブを持つカスタムパネルをTracyのデバッグバーに追加します: + +- **Overview**: 設定、パフォーマンス指標、カウント +- **Assets**: 圧縮率を含むCSS/JSコンパイルの詳細 +- **Variables**: 適用されたフィルターを含む元の値と変換された値 +- **Timeline**: すべてのテンプレート操作の時系列ビュー + +### ログに記録される内容 + +- テンプレートレンダリング(開始/終了、期間、レイアウト、インポート) +- アセットコンパイル(CSS/JSファイル、サイズ、圧縮率) +- 変数処理(元の値/変換された値、フィルター) +- アセット操作(base64エンコーディング、ファイルコピー) +- パフォーマンス指標(期間、メモリ使用量) + +**注意:** Tracyがインストールされていないか無効になっている場合、パフォーマンスへの影響はゼロです。 + +[Flight PHPでの完全な動作例](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp)を参照してください。 + ## テンプレートディレクティブ ### レイアウトの継承 diff --git a/content/v3/ko/awesome-plugins/comment_template.md b/content/v3/ko/awesome-plugins/comment_template.md index a419aec9..1a7e97c3 100644 --- a/content/v3/ko/awesome-plugins/comment_template.md +++ b/content/v3/ko/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir`은 디렉토리를 다음 위치에 복사합니다: `{resolvedAssetPath}/{relativePath}` - 스마트 캐싱: 소스가 대상보다 최신인 경우에만 파일이 복사됩니다 +## Tracy 디버거 통합 + +CommentTemplate은 개발 로깅 및 디버깅을 위해 [Tracy Debugger](https://tracy.nette.org/)와 통합됩니다. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### 설치 + +```bash +composer require tracy/tracy +``` + +### 사용법 + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### 디버그 패널 기능 + +CommentTemplate은 Tracy의 디버그 바에 4개의 탭이 있는 사용자 정의 패널을 추가합니다: + +- **Overview**: 구성, 성능 지표 및 카운트 +- **Assets**: 압축률이 포함된 CSS/JS 컴파일 세부정보 +- **Variables**: 적용된 필터가 있는 원본 및 변환된 값 +- **Timeline**: 모든 템플릿 작업의 시간순 보기 + +### 로깅되는 항목 + +- 템플릿 렌더링 (시작/종료, 기간, 레이아웃, 가져오기) +- 자산 컴파일 (CSS/JS 파일, 크기, 압축률) +- 변수 처리 (원본/변환된 값, 필터) +- 자산 작업 (base64 인코딩, 파일 복사) +- 성능 지표 (기간, 메모리 사용량) + +**참고:** Tracy가 설치되지 않았거나 비활성화된 경우 성능에 영향이 없습니다. + +[Flight PHP와 함께 사용하는 완전한 예제](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp)를 참조하세요. + ## 템플릿 지시어 ### 레이아웃 상속 diff --git a/content/v3/lv/awesome-plugins/comment_template.md b/content/v3/lv/awesome-plugins/comment_template.md index d83f927b..7ab69fc5 100644 --- a/content/v3/lv/awesome-plugins/comment_template.md +++ b/content/v3/lv/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` kopē direktorijus uz: `{resolvedAssetPath}/{relativePath}` - Viedā kešošana: faili tiek kopēti tikai tad, ja avots ir jaunāks nekā mērķis +## Tracy atkļūdotāja integrācija + +CommentTemplate ietver integrāciju ar [Tracy Debugger](https://tracy.nette.org/) izstrādes reģistrēšanai un atkļūdošanai. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Instalācija + +```bash +composer require tracy/tracy +``` + +### Lietošana + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Atkļūdošanas paneļa funkcijas + +CommentTemplate pievieno pielāgotu paneli Tracy atkļūdošanas joslai ar četrām cilnēm: + +- **Overview**: Konfigurācija, veiktspējas metrika un skaitītāji +- **Assets**: CSS/JS kompilācijas detaļas ar saspiešanas proporcijām +- **Variables**: Oriģinālās un pārveidotās vērtības ar lietotajiem filtriem +- **Timeline**: Hronoloģisks visu veidņu operāciju skats + +### Kas tiek reģistrēts + +- Veidņu renderēšana (sākums/beigas, ilgums, izkārtojumi, importi) +- Aktīvu kompilācija (CSS/JS faili, izmēri, saspiešanas proporcijas) +- Mainīgo apstrāde (oriģinālās/pārveidotās vērtības, filtri) +- Aktīvu operācijas (base64 kodēšana, failu kopēšana) +- Veiktspējas metrika (ilgums, atmiņas izmantošana) + +**Piezīme:** Nulles ietekme uz veiktspēju, ja Tracy nav instalēts vai ir atspējots. + +Skatiet [pilnīgu darba piemēru ar Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Veidnes direktīvas ### Izkārtojuma mantojums diff --git a/content/v3/pt/awesome-plugins/comment_template.md b/content/v3/pt/awesome-plugins/comment_template.md index 8c1899f6..4541b144 100644 --- a/content/v3/pt/awesome-plugins/comment_template.md +++ b/content/v3/pt/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` copia diretórios para: `{resolvedAssetPath}/{relativePath}` - Cache inteligente: arquivos só são copiados quando a fonte é mais nova que o destino +## Integração com Tracy Debugger + +CommentTemplate inclui integração com [Tracy Debugger](https://tracy.nette.org/) para registro e depuração em desenvolvimento. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Instalação + +```bash +composer require tracy/tracy +``` + +### Uso + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Recursos do Painel de Depuração + +CommentTemplate adiciona um painel personalizado à barra de depuração do Tracy com quatro abas: + +- **Overview**: Configuração, métricas de desempenho e contadores +- **Assets**: Detalhes de compilação CSS/JS com taxas de compressão +- **Variables**: Valores originais e transformados com filtros aplicados +- **Timeline**: Visualização cronológica de todas as operações de template + +### O Que É Registrado + +- Renderização de template (início/fim, duração, layouts, importações) +- Compilação de ativos (arquivos CSS/JS, tamanhos, taxas de compressão) +- Processamento de variáveis (valores originais/transformados, filtros) +- Operações de ativos (codificação base64, cópia de arquivos) +- Métricas de desempenho (duração, uso de memória) + +**Nota:** Nenhum impacto no desempenho quando Tracy não está instalado ou desabilitado. + +Consulte o [exemplo completo funcional com Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Diretivas de Template ### Herança de Layout diff --git a/content/v3/ru/awesome-plugins/comment_template.md b/content/v3/ru/awesome-plugins/comment_template.md index 3ce888c6..8ef581ce 100644 --- a/content/v3/ru/awesome-plugins/comment_template.md +++ b/content/v3/ru/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` копирует директории в: `{resolvedAssetPath}/{relativePath}` - Умное кеширование: файлы копируются только когда источник новее цели +## Интеграция с Tracy Debugger + +CommentTemplate включает интеграцию с [Tracy Debugger](https://tracy.nette.org/) для логирования и отладки в разработке. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Установка + +```bash +composer require tracy/tracy +``` + +### Использование + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Функции панели отладки + +CommentTemplate добавляет пользовательскую панель в панель отладки Tracy с четырьмя вкладками: + +- **Overview**: Конфигурация, метрики производительности и счетчики +- **Assets**: Детали компиляции CSS/JS с коэффициентами сжатия +- **Variables**: Исходные и преобразованные значения с примененными фильтрами +- **Timeline**: Хронологический вид всех операций шаблонов + +### Что логируется + +- Рендеринг шаблонов (начало/конец, длительность, макеты, импорты) +- Компиляция ассетов (файлы CSS/JS, размеры, коэффициенты сжатия) +- Обработка переменных (исходные/преобразованные значения, фильтры) +- Операции с ассетами (кодирование base64, копирование файлов) +- Метрики производительности (длительность, использование памяти) + +**Примечание:** Нулевое влияние на производительность, когда Tracy не установлен или отключен. + +См. [полный рабочий пример с Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Директивы шаблонов ### Наследование макетов diff --git a/content/v3/uk/awesome-plugins/comment_template.md b/content/v3/uk/awesome-plugins/comment_template.md index 828f7cc5..ba0cddf2 100644 --- a/content/v3/uk/awesome-plugins/comment_template.md +++ b/content/v3/uk/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` копіює каталоги до: `{resolvedAssetPath}/{relativePath}` - Розумне кешування: файли копіюються лише коли джерело новіше за призначення +## Інтеграція з Tracy Debugger + +CommentTemplate включає інтеграцію з [Tracy Debugger](https://tracy.nette.org/) для логування та налагодження під час розробки. + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### Встановлення + +```bash +composer require tracy/tracy +``` + +### Використання + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### Функції панелі налагодження + +CommentTemplate додає користувацьку панель до панелі налагодження Tracy з чотирма вкладками: + +- **Overview**: Конфігурація, метрики продуктивності та лічильники +- **Assets**: Деталі компіляції CSS/JS з коефіцієнтами стиснення +- **Variables**: Оригінальні та перетворені значення з застосованими фільтрами +- **Timeline**: Хронологічний вигляд усіх операцій шаблонів + +### Що логується + +- Рендеринг шаблонів (початок/кінець, тривалість, макети, імпорти) +- Компіляція активів (файли CSS/JS, розміри, коефіцієнти стиснення) +- Обробка змінних (оригінальні/перетворені значення, фільтри) +- Операції з активами (кодування base64, копіювання файлів) +- Метрики продуктивності (тривалість, використання пам'яті) + +**Примітка:** Нульовий вплив на продуктивність, коли Tracy не встановлено або вимкнено. + +Див. [повний робочий приклад з Flight PHP](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp). + ## Директиви шаблонів ### Успадкування макетів diff --git a/content/v3/zh/awesome-plugins/comment_template.md b/content/v3/zh/awesome-plugins/comment_template.md index 37b7dc4b..f64ebb6b 100644 --- a/content/v3/zh/awesome-plugins/comment_template.md +++ b/content/v3/zh/awesome-plugins/comment_template.md @@ -151,6 +151,64 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse - `@assetDir` 将目录复制到:`{resolvedAssetPath}/{relativePath}` - 智能缓存:仅当源文件比目标文件新时才复制文件 +## Tracy 调试器集成 + +CommentTemplate 包含与 [Tracy Debugger](https://tracy.nette.org/) 的集成,用于开发日志记录和调试。 + +![Comment Template Tracy](https://raw.githubusercontent.com/KnifeLemon/CommentTemplate/refs/heads/master/tracy.jpeg) + +### 安装 + +```bash +composer require tracy/tracy +``` + +### 使用方法 + +```php +register('view', Engine::class, [], function (Engine $builder) use ($app) { + $builder->setPublicPath($app->get('flight.views.topPath')); + $builder->setAssetPath($app->get('flight.views.assetPath')); + $builder->setSkinPath($app->get('flight.views.path')); + $builder->setFileExtension($app->get('flight.views.extension')); +}); +$app->map('render', function(string $template, array $data) use ($app): void { + echo $app->view()->render($template, $data); +}); + +$app->start(); +``` + +### 调试面板功能 + +CommentTemplate 为 Tracy 的调试栏添加了一个包含四个选项卡的自定义面板: + +- **Overview**:配置、性能指标和计数 +- **Assets**:包含压缩率的 CSS/JS 编译详情 +- **Variables**:包含应用过滤器的原始值和转换值 +- **Timeline**:所有模板操作的时间顺序视图 + +### 记录的内容 + +- 模板渲染(开始/结束、持续时间、布局、导入) +- 资源编译(CSS/JS 文件、大小、压缩率) +- 变量处理(原始/转换值、过滤器) +- 资源操作(base64 编码、文件复制) +- 性能指标(持续时间、内存使用) + +**注意:** 当 Tracy 未安装或被禁用时,对性能没有任何影响。 + +请参阅 [Flight PHP 完整工作示例](https://github.com/KnifeLemon/CommentTemplate/tree/master/examples/flightphp)。 + ## 模板指令 ### 布局继承 From 6a25052a7ebb85f52395eb264e7225980f56718c Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Thu, 25 Dec 2025 14:08:58 -0700 Subject: [PATCH 24/36] Changed runway logic and how APM configs are stored. --- app/config/services.php | 8 +- app/utils/DocsLogic.php | 210 +++++++++++++-------------- composer.json | 5 +- composer.lock | 107 +++++++------- content/v3/en/awesome-plugins/apm.md | 10 ++ runway | 3 + 6 files changed, 180 insertions(+), 163 deletions(-) create mode 100644 runway diff --git a/app/config/services.php b/app/config/services.php index 1ac328ed..e50dec18 100644 --- a/app/config/services.php +++ b/app/config/services.php @@ -14,7 +14,7 @@ * @var CustomEngine $app */ - // This translates some common parts of the page, not the content +// This translates some common parts of the page, not the content $app->register('translator', Translator::class); // Templating Engine used to render the views @@ -28,7 +28,7 @@ ); $latte->addExtension($translatorExtension); - $latte->addExtension(new Latte\Bridges\Tracy\TracyExtension); + $latte->addExtension(new Latte\Bridges\Tracy\TracyExtension); }); // Cache for storing parsedown and other things @@ -40,6 +40,6 @@ $app->register('parsedown', Parsedown::class); // Register the APM -$ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); +$ApmLogger = LoggerFactory::create($config['runway']); $Apm = new Apm($ApmLogger); -$Apm->bindEventsToFlightInstance($app); \ No newline at end of file +$Apm->bindEventsToFlightInstance($app); diff --git a/app/utils/DocsLogic.php b/app/utils/DocsLogic.php index af3a4f43..bd3fde69 100644 --- a/app/utils/DocsLogic.php +++ b/app/utils/DocsLogic.php @@ -9,10 +9,10 @@ class DocsLogic { /** @var string */ - private const DS = DIRECTORY_SEPARATOR; + private const DS = DIRECTORY_SEPARATOR; /** @var string Path to the base content directory */ - public const CONTENT_DIR = __DIR__ . self::DS . '..' . self::DS . '..' . self::DS . 'content' . self::DS; + public const CONTENT_DIR = __DIR__ . self::DS . '..' . self::DS . '..' . self::DS . 'content' . self::DS; const AVAILABLE_LANGUAGES = [ 'en', @@ -35,7 +35,6 @@ class DocsLogic { * @param CustomEngine $app Flight Engine */ public function __construct(protected $app) { - } /** @@ -46,33 +45,33 @@ public function __construct(protected $app) { public function getLearnSectionNames(): array { return [ 'Core Components' => [ - [ 'url' => '/learn/routing', 'title' => 'Routing' ], - [ 'url' => '/learn/middleware', 'title' => 'Middleware' ], - [ 'url' => '/learn/autoloading', 'title' => 'Autoloading' ], - [ 'url' => '/learn/requests', 'title' => 'Requests' ], - [ 'url' => '/learn/responses', 'title' => 'Responses' ], - [ 'url' => '/learn/templates', 'title' => 'HTML Templates' ], - [ 'url' => '/learn/security', 'title' => 'Security' ], - [ 'url' => '/learn/configuration', 'title' => 'Configuration' ], - [ 'url' => '/learn/events', 'title' => 'Event Manager' ], - [ 'url' => '/learn/extending', 'title' => 'Extending Flight' ], - [ 'url' => '/learn/filtering', 'title' => 'Method Hooks and Filtering' ], - [ 'url' => '/learn/dependency-injection-container', 'title' => 'Dependency Injection' ], + ['url' => '/learn/routing', 'title' => 'Routing'], + ['url' => '/learn/middleware', 'title' => 'Middleware'], + ['url' => '/learn/autoloading', 'title' => 'Autoloading'], + ['url' => '/learn/requests', 'title' => 'Requests'], + ['url' => '/learn/responses', 'title' => 'Responses'], + ['url' => '/learn/templates', 'title' => 'HTML Templates'], + ['url' => '/learn/security', 'title' => 'Security'], + ['url' => '/learn/configuration', 'title' => 'Configuration'], + ['url' => '/learn/events', 'title' => 'Event Manager'], + ['url' => '/learn/extending', 'title' => 'Extending Flight'], + ['url' => '/learn/filtering', 'title' => 'Method Hooks and Filtering'], + ['url' => '/learn/dependency-injection-container', 'title' => 'Dependency Injection'], ], 'Utility Classes' => [ - [ 'url' => '/learn/collections', 'title' => 'Collections' ], - [ 'url' => '/learn/json', 'title' => 'JSON Wrapper' ], - [ 'url' => '/learn/pdo-wrapper', 'title' => 'PDO Wrapper' ], - [ 'url' => '/learn/uploaded-file', 'title' => 'Uploaded File Handler' ], + ['url' => '/learn/collections', 'title' => 'Collections'], + ['url' => '/learn/json', 'title' => 'JSON Wrapper'], + ['url' => '/learn/pdo-wrapper', 'title' => 'PDO Wrapper'], + ['url' => '/learn/uploaded-file', 'title' => 'Uploaded File Handler'], ], 'Important Concepts' => [ - [ 'url' => '/learn/why-frameworks', 'title' => 'Why a Framework?' ], - [ 'url' => '/learn/flight-vs-another-framework', 'title' => 'Flight vs Others' ], + ['url' => '/learn/why-frameworks', 'title' => 'Why a Framework?'], + ['url' => '/learn/flight-vs-another-framework', 'title' => 'Flight vs Others'], ], 'Other Topics' => [ - [ 'url' => '/learn/unit-testing', 'title' => 'Unit Testing' ], - [ 'url' => '/learn/ai', 'title' => 'AI & Developer Experience' ], - [ 'url' => '/learn/migrating-to-v3', 'title' => 'Migrating v2 -> v3' ], + ['url' => '/learn/unit-testing', 'title' => 'Unit Testing'], + ['url' => '/learn/ai', 'title' => 'AI & Developer Experience'], + ['url' => '/learn/migrating-to-v3', 'title' => 'Migrating v2 -> v3'], ] ]; } @@ -83,20 +82,20 @@ public function getLearnSectionNames(): array { * @param string $latte_file The path to the Latte template file to be rendered. * @param array $params An optional array of parameters to be passed to the template. */ - public function renderPage(string $latte_file, array $params = []) { - $request = $this->app->request(); - $uri = $request->url; + public function renderPage(string $latte_file, array $params = []) { + $request = $this->app->request(); + $uri = $request->url; - if (str_contains($uri, '?')) { - $uri = substr($uri, 0, strpos($uri, '?')); - } + if (str_contains($uri, '?')) { + $uri = substr($uri, 0, strpos($uri, '?')); + } $startTime = microtime(true); - if(!empty($params['raw_markdown']) && (str_contains($request->header('Accept'), 'text/plain') || str_contains($request->header('Accept'), 'text/markdown'))) { + if (!empty($params['raw_markdown']) && (str_contains($request->header('Accept'), 'text/plain') || str_contains($request->header('Accept'), 'text/markdown'))) { $this->app->response()->header('Content-Type', 'text/markdown; charset=utf-8'); $this->app->response()->write($params['raw_markdown']); } else { - + // Here we can set variables that will be available on any page $params['url'] = $request->getScheme() . '://' . $request->getHeader('Host') . $uri; $params['nonce'] = HeaderSecurityMiddleware::$nonce; @@ -104,10 +103,10 @@ public function renderPage(string $latte_file, array $params = []) { $this->app->latte()->render($latte_file, $params); } - + $executionTime = microtime(true) - $startTime; - $this->app->eventDispatcher()->trigger('flight.view.rendered', $latte_file.':'.$uri, $executionTime); - } + $this->app->eventDispatcher()->trigger('flight.view.rendered', $latte_file . ':' . $uri, $executionTime); + } /** * Sets up the translator service with the specified language and version. @@ -120,7 +119,7 @@ public function setupTranslatorService(string $language, string $version): Trans $Translator = $this->app->translator(); $Translator->setLanguage($language); $Translator->setVersion($version); - return $Translator; + return $Translator; } /** @@ -132,8 +131,8 @@ public function setupTranslatorService(string $language, string $version): Trans * * @return void */ - public function compileSinglePage(string $language, string $version, string $section) { - $app = $this->app; + public function compileSinglePage(string $language, string $version, string $section) { + $app = $this->app; // Check if the language is valid if ($this->checkValidLanguage($language) === false) { @@ -159,18 +158,18 @@ public function compileSinglePage(string $language, string $version, string $sec $app->cache()->store($cacheKey, $markdown_html, 86400); // 1 day } - $app->eventDispatcher()->trigger('flight.cache.checked', 'compile_single_page_'.$cacheKey, $cacheHit, microtime(true) - $cacheStartTime); + $app->eventDispatcher()->trigger('flight.cache.checked', 'compile_single_page_' . $cacheKey, $cacheHit, microtime(true) - $cacheStartTime); - $markdown_html = $this->wrapContentInDiv($markdown_html); + $markdown_html = $this->wrapContentInDiv($markdown_html); - $this->renderPage('single_page.latte', [ - 'page_title' => $section, - 'markdown' => $markdown_html, + $this->renderPage('single_page.latte', [ + 'page_title' => $section, + 'markdown' => $markdown_html, 'version' => $version, 'language' => $language, 'raw_markdown' => $rawMarkdown, - ]); - } + ]); + } /** * Compiles the Scrollspy page based on the provided language, version, section, and sub-section. @@ -180,7 +179,7 @@ public function compileSinglePage(string $language, string $version, string $sec * @param string $section The main section of the documentation. * @param string $sub_section The sub-section of the documentation. */ - public function compileScrollspyPage(string $language, string $version, string $section, string $sub_section) { + public function compileScrollspyPage(string $language, string $version, string $section, string $sub_section) { $app = $this->app; // Check if the language is valid @@ -209,13 +208,13 @@ public function compileScrollspyPage(string $language, string $version, string $ $markdown_html = $app->parsedown()->text($rawMarkdown); $heading_data = []; - $markdown_html = Text::generateAndConvertHeaderListFromHtml($markdown_html, $heading_data, $section_file_path.'/'.$sub_section); + $markdown_html = Text::generateAndConvertHeaderListFromHtml($markdown_html, $heading_data, $section_file_path . '/' . $sub_section); $markdown_html = Text::addClassesToElements($markdown_html); $app->cache()->store($sub_section_underscored . '_heading_data_' . $language . '_' . $version, $heading_data, 86400); // 1 day $app->cache()->store($cacheKey, $markdown_html, 86400); // 1 day } - $app->eventDispatcher()->trigger('flight.cache.checked', 'compile_scrollspy_page_'.$cacheKey, $cacheHit, microtime(true) - $cacheStartTime); + $app->eventDispatcher()->trigger('flight.cache.checked', 'compile_scrollspy_page_' . $cacheKey, $cacheHit, microtime(true) - $cacheStartTime); // pull the title out of the first h1 tag $page_title = ''; @@ -235,7 +234,7 @@ public function compileScrollspyPage(string $language, string $version, string $ 'raw_markdown' => $rawMarkdown, 'markdown' => $markdown_html, 'heading_data' => $heading_data, - 'relative_uri' => '/'.$section_file_path, + 'relative_uri' => '/' . $section_file_path, 'version' => $version, 'language' => $language, ]; @@ -247,22 +246,22 @@ public function compileScrollspyPage(string $language, string $version, string $ } $this->renderPage('single_page_scrollspy.latte', $params); - } + } /** - * This is necessary to encapsulate contents (

,

, 
    ,
      ) - * in a div which can be then styled with CSS thanks to the class name `flight-block` + * This is necessary to encapsulate contents (

      ,

      , 
        ,
          ) + * in a div which can be then styled with CSS thanks to the class name `flight-block` * * @param string $html * @return string - */ - protected function wrapContentInDiv(string $html): string { - $dom = new DOMDocument; - $dom->loadHTML('' . $html); - $xpath = new DOMXPath($dom); - $elements = $xpath->query('//body/*'); - $d = ''; - $div = null; + */ + protected function wrapContentInDiv(string $html): string { + $dom = new DOMDocument; + $dom->loadHTML('' . $html); + $xpath = new DOMXPath($dom); + $elements = $xpath->query('//body/*'); + $d = ''; + $div = null; foreach ($elements as $element) { $elt_html = $element->C14N(); @@ -296,6 +295,7 @@ protected function wrapContentInDiv(string $html): string { && $element->nodeName !== 'pre' && $element->nodeName !== 'h3' && $element->nodeName !== 'h4' + && $element->nodeName !== 'h5' && $element->nodeName !== 'ol' && $element->nodeName !== 'ul' && $element->nodeName !== 'blockquote' @@ -311,12 +311,12 @@ protected function wrapContentInDiv(string $html): string { } } - if (!is_null($div)) { - $d .= ''; - } + if (!is_null($div)) { + $d .= ''; + } - return $d; - } + return $d; + } /** * Checks if the provided language is valid. @@ -356,35 +356,35 @@ public function runSearch(string $query, string $language = 'en', string $versio } $language_directory_to_grep = self::CONTENT_DIR . $version . self::DS . $language . self::DS; - $grep_command = 'grep -r -i -n --color=never --include="*.md" '.escapeshellarg($query).' '.escapeshellarg($language_directory_to_grep); - exec($grep_command, $grep_output); - - $files_found = []; - foreach($grep_output as $line) { - $line_parts = explode(':', $line); - // Catch the windows C drive letter - if($line_parts[0] === 'C') { - array_shift($line_parts); - } - $file_path = str_replace('/', self::DS, $line_parts[0]); - $line_number = $line_parts[1]; - $line_content = $line_parts[2]; + $grep_command = 'grep -r -i -n --color=never --include="*.md" ' . escapeshellarg($query) . ' ' . escapeshellarg($language_directory_to_grep); + exec($grep_command, $grep_output); + + $files_found = []; + foreach ($grep_output as $line) { + $line_parts = explode(':', $line); + // Catch the windows C drive letter + if ($line_parts[0] === 'C') { + array_shift($line_parts); + } + $file_path = str_replace('/', self::DS, $line_parts[0]); + $line_number = $line_parts[1]; + $line_content = $line_parts[2]; // Skip test files if (substr($file_path, -9) === '__test.md') { continue; } - $file_contents = file_exists($file_path) - ? file_get_contents($file_path) - : ''; + $file_contents = file_exists($file_path) + ? file_get_contents($file_path) + : ''; - // pull the title from the first header tag in the markdown file. - preg_match('/# (.+)/', $file_contents, $matches); - if(empty($matches[1])) { - continue; - } - $title = $matches[1]; + // pull the title from the first header tag in the markdown file. + preg_match('/# (.+)/', $file_contents, $matches); + if (empty($matches[1])) { + continue; + } + $title = $matches[1]; // convert markdown to html and then strip tags to get plain text $file_contents = strip_tags($this->app->parsedown()->text($file_contents)); @@ -446,29 +446,29 @@ public function runSearch(string $query, string $language = 'en', string $versio // bold the search term in the excerpt $excerpt = preg_replace('/(' . preg_quote($query, '/') . ')/i', '$1', $excerpt); - $files_found[$file_path][] = [ - 'line_number' => $line_number, - 'line_content' => $line_content, - 'page_name' => $title, + $files_found[$file_path][] = [ + 'line_number' => $line_number, + 'line_content' => $line_content, + 'page_name' => $title, 'excerpt' => $excerpt, - ]; - } + ]; + } - $final_search = []; - foreach($files_found as $file_path => $data) { - $count = count($files_found[$file_path]); - $final_search[] = [ + $final_search = []; + foreach ($files_found as $file_path => $data) { + $count = count($files_found[$file_path]); + $final_search[] = [ 'page_name' => $data[0]['page_name'], - 'search_result' => $data[0]['page_name'].' ("'.$query.'" '.$count.'x)', - 'url' => '/'.$language.'/'.$version.'/'.str_replace([ $language_directory_to_grep, '.md', '_', '\\' ], [ '', '', '-', '/' ], $file_path), - 'hits' => $count, + 'search_result' => $data[0]['page_name'] . ' ("' . $query . '" ' . $count . 'x)', + 'url' => '/' . $language . '/' . $version . '/' . str_replace([$language_directory_to_grep, '.md', '_', '\\'], ['', '', '-', '/'], $file_path), + 'hits' => $count, 'excerpt' => $data[0]['excerpt'], - ]; - } + ]; + } - // sort by descending order by putting $b first - usort($final_search, fn($a, $b) => $b['hits'] <=> $a['hits']); + // sort by descending order by putting $b first + usort($final_search, fn($a, $b) => $b['hits'] <=> $a['hits']); return $final_search; } -} \ No newline at end of file +} diff --git a/composer.json b/composer.json index 835c1a37..019c233b 100644 --- a/composer.json +++ b/composer.json @@ -13,10 +13,11 @@ "php": "^8.2", "ext-json": "*", "erusev/parsedown": "^1.7", - "flightphp/apm": "^0.4", + "flightphp/apm": "^0.5", "flightphp/async": "^0.1.1", "flightphp/cache": "^1.0", "flightphp/core": "^3.15", + "flightphp/runway": "^1.2", "latte/latte": "^3.0", "tracy/tracy": "^2.10" }, @@ -43,4 +44,4 @@ "phpstan/phpstan": "^2.1", "rector/rector": "^2.0" } -} +} \ No newline at end of file diff --git a/composer.lock b/composer.lock index 1fe8908f..c09eb97f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "616a179db91b415e8d12bd2376edfb92", + "content-hash": "f85fed1538464e7c534f3855f7b36086", "packages": [ { "name": "adhocore/cli", @@ -131,16 +131,16 @@ }, { "name": "flightphp/apm", - "version": "v0.4.1", + "version": "v0.5.0", "source": { "type": "git", "url": "https://github.com/flightphp/apm.git", - "reference": "88f06888cae9d98baf3c64d605bcb1bc2d690306" + "reference": "f25edeba8e03e3fe70b7160ebd5ffd877d7f9f6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/flightphp/apm/zipball/88f06888cae9d98baf3c64d605bcb1bc2d690306", - "reference": "88f06888cae9d98baf3c64d605bcb1bc2d690306", + "url": "https://api.github.com/repos/flightphp/apm/zipball/f25edeba8e03e3fe70b7160ebd5ffd877d7f9f6e", + "reference": "f25edeba8e03e3fe70b7160ebd5ffd877d7f9f6e", "shasum": "" }, "require": { @@ -192,9 +192,9 @@ ], "support": { "issues": "https://github.com/flightphp/apm/issues", - "source": "https://github.com/flightphp/apm/tree/v0.4.1" + "source": "https://github.com/flightphp/apm/tree/v0.5.0" }, - "time": "2025-09-01T14:15:27+00:00" + "time": "2025-12-18T06:32:58+00:00" }, { "name": "flightphp/async", @@ -377,24 +377,24 @@ }, { "name": "flightphp/runway", - "version": "v1.1.2", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/flightphp/runway.git", - "reference": "b88c1901b77eda935ef475af772445c3108cf23f" + "reference": "6924f511b6de47e6c6da32d17c6dfc4a963f5f52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/flightphp/runway/zipball/b88c1901b77eda935ef475af772445c3108cf23f", - "reference": "b88c1901b77eda935ef475af772445c3108cf23f", + "url": "https://api.github.com/repos/flightphp/runway/zipball/6924f511b6de47e6c6da32d17c6dfc4a963f5f52", + "reference": "6924f511b6de47e6c6da32d17c6dfc4a963f5f52", "shasum": "" }, "require": { - "adhocore/cli": "^1.7", - "nette/php-generator": "^4.1", - "php": "^8.2" + "adhocore/cli": "^0.9 || ^1.7", + "nette/php-generator": "^3.1 || ^4.1" }, "require-dev": { + "flightphp/core": "^3.17", "phpstan/extension-installer": "^1.3", "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.5", @@ -423,28 +423,28 @@ "description": "Console app for the Flight PHP Framework.", "support": { "issues": "https://github.com/flightphp/runway/issues", - "source": "https://github.com/flightphp/runway/tree/v1.1.2" + "source": "https://github.com/flightphp/runway/tree/v1.2.0" }, - "time": "2025-01-11T17:52:47+00:00" + "time": "2025-11-14T14:30:07+00:00" }, { "name": "latte/latte", - "version": "v3.0.23", + "version": "v3.1.1", "source": { "type": "git", "url": "https://github.com/nette/latte.git", - "reference": "3198a4e336a2a1e535924af11d9a63fbf1650836" + "reference": "cb98e705eeb0fd18f1f1c5cfe1a5f6217f9fa8b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/latte/zipball/3198a4e336a2a1e535924af11d9a63fbf1650836", - "reference": "3198a4e336a2a1e535924af11d9a63fbf1650836", + "url": "https://api.github.com/repos/nette/latte/zipball/cb98e705eeb0fd18f1f1c5cfe1a5f6217f9fa8b3", + "reference": "cb98e705eeb0fd18f1f1c5cfe1a5f6217f9fa8b3", "shasum": "" }, "require": { "ext-json": "*", "ext-tokenizer": "*", - "php": "8.0 - 8.4" + "php": "8.2 - 8.5" }, "conflict": { "nette/application": "<3.1.7", @@ -471,7 +471,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -512,9 +512,9 @@ ], "support": { "issues": "https://github.com/nette/latte/issues", - "source": "https://github.com/nette/latte/tree/v3.0.23" + "source": "https://github.com/nette/latte/tree/v3.1.1" }, - "time": "2025-07-17T01:01:46+00:00" + "time": "2025-12-18T22:30:40+00:00" }, { "name": "nette/php-generator", @@ -590,20 +590,20 @@ }, { "name": "nette/utils", - "version": "v4.0.8", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede" + "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/c930ca4e3cf4f17dcfb03037703679d2396d2ede", - "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede", + "url": "https://api.github.com/repos/nette/utils/zipball/c99059c0315591f1a0db7ad6002000288ab8dc72", + "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72", "shasum": "" }, "require": { - "php": "8.0 - 8.5" + "php": "8.2 - 8.5" }, "conflict": { "nette/finder": "<3", @@ -626,7 +626,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -673,28 +673,28 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.0.8" + "source": "https://github.com/nette/utils/tree/v4.1.1" }, - "time": "2025-08-06T21:43:34+00:00" + "time": "2025-12-22T12:14:32+00:00" }, { "name": "tracy/tracy", - "version": "v2.10.10", + "version": "v2.11.0", "source": { "type": "git", "url": "https://github.com/nette/tracy.git", - "reference": "32303e02c222eea8571402a8310fc3fe70422c37" + "reference": "eec57bcf2ff11d79f519a19da9d7ae1e2c63c42e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/tracy/zipball/32303e02c222eea8571402a8310fc3fe70422c37", - "reference": "32303e02c222eea8571402a8310fc3fe70422c37", + "url": "https://api.github.com/repos/nette/tracy/zipball/eec57bcf2ff11d79f519a19da9d7ae1e2c63c42e", + "reference": "eec57bcf2ff11d79f519a19da9d7ae1e2c63c42e", "shasum": "" }, "require": { "ext-json": "*", "ext-session": "*", - "php": "8.0 - 8.4" + "php": "8.2 - 8.5" }, "conflict": { "nette/di": "<3.0" @@ -706,19 +706,22 @@ "nette/mail": "^3.0 || ^4.0", "nette/tester": "^2.2", "nette/utils": "^3.0 || ^4.0", - "phpstan/phpstan": "^1.0", + "phpstan/phpstan-nette": "^2.0@stable", "psr/log": "^1.0 || ^2.0 || ^3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.10-dev" + "dev-master": "2.11-dev" } }, "autoload": { "files": [ "src/Tracy/functions.php" ], + "psr-4": { + "Tracy\\": "src" + }, "classmap": [ "src" ] @@ -748,9 +751,9 @@ ], "support": { "issues": "https://github.com/nette/tracy/issues", - "source": "https://github.com/nette/tracy/tree/v2.10.10" + "source": "https://github.com/nette/tracy/tree/v2.11.0" }, - "time": "2025-04-28T14:35:15+00:00" + "time": "2025-10-31T00:12:50+00:00" } ], "packages-dev": [ @@ -849,11 +852,11 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.30", + "version": "2.1.33", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/a4a7f159927983dd4f7c8020ed227d80b7f39d7d", - "reference": "a4a7f159927983dd4f7c8020ed227d80b7f39d7d", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9e800e6bee7d5bd02784d4c6069b48032d16224f", + "reference": "9e800e6bee7d5bd02784d4c6069b48032d16224f", "shasum": "" }, "require": { @@ -898,25 +901,25 @@ "type": "github" } ], - "time": "2025-10-02T16:07:52+00:00" + "time": "2025-12-05T10:24:31+00:00" }, { "name": "rector/rector", - "version": "2.1.7", + "version": "2.2.14", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "c34cc07c4698f007a20dc5c99ff820089ae413ce" + "reference": "6d56bb0e94d4df4f57a78610550ac76ab403657d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/c34cc07c4698f007a20dc5c99ff820089ae413ce", - "reference": "c34cc07c4698f007a20dc5c99ff820089ae413ce", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/6d56bb0e94d4df4f57a78610550ac76ab403657d", + "reference": "6d56bb0e94d4df4f57a78610550ac76ab403657d", "shasum": "" }, "require": { "php": "^7.4|^8.0", - "phpstan/phpstan": "^2.1.18" + "phpstan/phpstan": "^2.1.33" }, "conflict": { "rector/rector-doctrine": "*", @@ -950,7 +953,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.1.7" + "source": "https://github.com/rectorphp/rector/tree/2.2.14" }, "funding": [ { @@ -958,7 +961,7 @@ "type": "github" } ], - "time": "2025-09-10T11:13:58+00:00" + "time": "2025-12-09T10:57:55+00:00" } ], "aliases": [], diff --git a/content/v3/en/awesome-plugins/apm.md b/content/v3/en/awesome-plugins/apm.md index b44fc88c..8717601e 100644 --- a/content/v3/en/awesome-plugins/apm.md +++ b/content/v3/en/awesome-plugins/apm.md @@ -304,6 +304,16 @@ This will run any migrations that are needed to update the database schema to th **Note:** If you're APM database is large in size, these migrations may take some time to run. You may want to run this command during off-peak hours. +### Upgrading from 0.4.3 -> 0.5.0 + +If you are upgrading from 0.4.3 to 0.5.0, you will need to run the following command: + +```bash +php vendor/bin/runway apm:config-migrate +``` + +This will migrate your config from the old format using the `.runway-config.json` file to the new format which stores the key/values in the `config.php` file. + ## Purging Old Data To keep your database tidy, you can purge old data. This is especially useful if you’re running a busy app and want to keep the database size manageable. diff --git a/runway b/runway new file mode 100644 index 00000000..e0fd5ae8 --- /dev/null +++ b/runway @@ -0,0 +1,3 @@ + Date: Thu, 25 Dec 2025 14:09:43 -0700 Subject: [PATCH 25/36] updated active record with data on eager loading. --- .../v3/en/awesome-plugins/active_record.md | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/content/v3/en/awesome-plugins/active_record.md b/content/v3/en/awesome-plugins/active_record.md index ee714786..876b1be3 100644 --- a/content/v3/en/awesome-plugins/active_record.md +++ b/content/v3/en/awesome-plugins/active_record.md @@ -598,6 +598,107 @@ echo $contact->user->name; // this is the user name Pretty cool eh? +### Eager Loading + +#### Overview +Eager loading solves the N+1 query problem by loading relationships in advance. Instead of executing a separate query for each record's relationships, eager loading fetches all related data in just one additional query per relationship. + +> **Note:** Eager loading is only available for v0.7.0 and above. + +#### Basic Usage +Use the `with()` method to specify which relationships to eager load: +```php +// Load users with their contacts in 2 queries instead of N+1 +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + foreach ($u->contacts as $contact) { + echo $contact->email; // No additional query! + } +} +``` + +#### Multiple Relations +Load multiple relationships at once: +```php +$users = $user->with(['contacts', 'profile', 'settings'])->findAll(); +``` + +#### Relationship Types + +##### HAS_MANY +```php +// Eager load all contacts for each user +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + // $u->contacts is already loaded as an array + foreach ($u->contacts as $contact) { + echo $contact->email; + } +} +``` +##### HAS_ONE +```php +// Eager load one contact for each user +$users = $user->with('contact')->findAll(); +foreach ($users as $u) { + // $u->contact is already loaded as an object + echo $u->contact->email; +} +``` + +##### BELONGS_TO +```php +// Eager load parent users for all contacts +$contacts = $contact->with('user')->findAll(); +foreach ($contacts as $c) { + // $c->user is already loaded + echo $c->user->name; +} +``` +##### With find() +Eager loading works with both +findAll() + and +find() +: + +```php +$user = $user->with('contacts')->find(1); +// User and all their contacts loaded in 2 queries +``` +#### Performance Benefits +Without eager loading (N+1 problem): +```php +$users = $user->findAll(); // 1 query +foreach ($users as $u) { + $contacts = $u->contacts; // N queries (one per user!) +} +// Total: 1 + N queries +``` + +With eager loading: + +```php +$users = $user->with('contacts')->findAll(); // 2 queries total +foreach ($users as $u) { + $contacts = $u->contacts; // 0 additional queries! +} +// Total: 2 queries (1 for users + 1 for all contacts) +``` +For 10 users, this reduces queries from 11 to 2 - an 82% reduction! + +#### Important Notes +- Eager loading is completely optional - lazy loading still works as before +- Already loaded relationships are automatically skipped +- Back references work with eager loading +- Relation callbacks are respected during eager loading + +#### Limitations +- Nested eager loading (e.g., +with(['contacts.addresses']) +) is not currently supported +- Eager load constraints via closures are not supported in this version + ## Setting Custom Data Sometimes you may need to attach something unique to your ActiveRecord such as a custom calculation that might be easier to just attach to the object that would then be passed to say a template. From 8f5d021492eb2ac078b863f6e771b5095ba5f5df Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Thu, 25 Dec 2025 14:29:08 -0700 Subject: [PATCH 26/36] retranslation --- .../v3/de/awesome-plugins/active_record.md | 374 +++++++++------ content/v3/de/awesome-plugins/apm.md | 87 ++-- .../v3/de/awesome-plugins/awesome_plugins.md | 62 +-- .../v3/de/awesome-plugins/comment_template.md | 94 ++-- content/v3/de/awesome-plugins/runway.md | 129 ++++-- content/v3/de/examples.md | 15 +- .../v3/es/awesome-plugins/active_record.md | 278 +++++++---- content/v3/es/awesome-plugins/apm.md | 109 +++-- .../v3/es/awesome-plugins/awesome_plugins.md | 42 +- .../v3/es/awesome-plugins/comment_template.md | 62 +-- content/v3/es/awesome-plugins/runway.md | 101 ++-- content/v3/es/examples.md | 11 +- .../v3/fr/awesome-plugins/active_record.md | 355 ++++++++------ content/v3/fr/awesome-plugins/apm.md | 115 ++--- .../v3/fr/awesome-plugins/awesome_plugins.md | 28 +- .../v3/fr/awesome-plugins/comment_template.md | 80 ++-- content/v3/fr/awesome-plugins/runway.md | 85 +++- content/v3/fr/examples.md | 15 +- .../v3/id/awesome-plugins/active_record.md | 357 ++++++++++----- content/v3/id/awesome-plugins/apm.md | 73 +-- .../v3/id/awesome-plugins/awesome_plugins.md | 40 +- .../v3/id/awesome-plugins/comment_template.md | 160 +++---- content/v3/id/awesome-plugins/runway.md | 86 ++-- content/v3/id/examples.md | 15 +- .../v3/ja/awesome-plugins/active_record.md | 432 +++++++++++------- content/v3/ja/awesome-plugins/apm.md | 237 +++++----- .../v3/ja/awesome-plugins/awesome_plugins.md | 56 +-- .../v3/ja/awesome-plugins/comment_template.md | 169 +++---- content/v3/ja/awesome-plugins/runway.md | 107 +++-- content/v3/ja/examples.md | 25 +- .../v3/ko/awesome-plugins/active_record.md | 388 ++++++++++------ content/v3/ko/awesome-plugins/apm.md | 147 +++--- .../v3/ko/awesome-plugins/awesome_plugins.md | 56 +-- .../v3/ko/awesome-plugins/comment_template.md | 74 +-- content/v3/ko/awesome-plugins/runway.md | 113 +++-- content/v3/ko/examples.md | 27 +- .../v3/lv/awesome-plugins/active_record.md | 357 +++++++++------ content/v3/lv/awesome-plugins/apm.md | 157 ++++--- .../v3/lv/awesome-plugins/awesome_plugins.md | 56 +-- .../v3/lv/awesome-plugins/comment_template.md | 117 ++--- content/v3/lv/awesome-plugins/runway.md | 101 ++-- content/v3/lv/examples.md | 53 +-- .../v3/pt/awesome-plugins/active_record.md | 313 ++++++++----- content/v3/pt/awesome-plugins/apm.md | 97 ++-- .../v3/pt/awesome-plugins/awesome_plugins.md | 28 +- .../v3/pt/awesome-plugins/comment_template.md | 74 +-- content/v3/pt/awesome-plugins/runway.md | 105 +++-- content/v3/pt/examples.md | 5 +- .../v3/ru/awesome-plugins/active_record.md | 338 +++++++++----- content/v3/ru/awesome-plugins/apm.md | 83 ++-- .../v3/ru/awesome-plugins/awesome_plugins.md | 75 ++- .../v3/ru/awesome-plugins/comment_template.md | 140 +++--- content/v3/ru/awesome-plugins/runway.md | 95 ++-- content/v3/ru/examples.md | 21 +- .../v3/uk/awesome-plugins/active_record.md | 363 +++++++++------ content/v3/uk/awesome-plugins/apm.md | 111 +++-- .../v3/uk/awesome-plugins/awesome_plugins.md | 56 +-- .../v3/uk/awesome-plugins/comment_template.md | 112 ++--- content/v3/uk/awesome-plugins/runway.md | 109 +++-- content/v3/uk/examples.md | 21 +- .../v3/zh/awesome-plugins/active_record.md | 360 +++++++++------ content/v3/zh/awesome-plugins/apm.md | 121 ++--- .../v3/zh/awesome-plugins/awesome_plugins.md | 48 +- .../v3/zh/awesome-plugins/comment_template.md | 87 ++-- content/v3/zh/awesome-plugins/runway.md | 115 +++-- content/v3/zh/examples.md | 15 +- 66 files changed, 4955 insertions(+), 3382 deletions(-) diff --git a/content/v3/de/awesome-plugins/active_record.md b/content/v3/de/awesome-plugins/active_record.md index d574b9c5..f0a746a6 100644 --- a/content/v3/de/awesome-plugins/active_record.md +++ b/content/v3/de/awesome-plugins/active_record.md @@ -1,12 +1,12 @@ -# Flight Aktive Datensätze +# Flight Active Record -Ein aktiver Datensatz ist die Zuordnung einer Datenbankentität zu einem PHP-Objekt. Einfach gesagt, wenn Sie eine Tabelle für Benutzer in Ihrer Datenbank haben, können Sie eine Zeile in dieser Tabelle in eine `User`-Klasse und ein `$user`-Objekt in Ihrem Code übersetzen. Siehe [ein einfaches Beispiel](#basic-example). +Ein Active Record ist eine Zuordnung einer Datenbank-Entität zu einem PHP-Objekt. Einfach gesagt: Wenn Sie eine Tabelle `users` in Ihrer Datenbank haben, können Sie eine Zeile in dieser Tabelle in eine `User`-Klasse und ein `$user`-Objekt in Ihrem Codebase "übersetzen". Siehe [einfaches Beispiel](#basic-example). Klicken Sie [hier](https://github.com/flightphp/active-record) für das Repository auf GitHub. ## Einfaches Beispiel -Angenommen, Sie haben die folgende Tabelle: +Nehmen wir an, Sie haben die folgende Tabelle: ```sql CREATE TABLE users ( @@ -16,11 +16,11 @@ CREATE TABLE users ( ); ``` -Jetzt können Sie eine neue Klasse einrichten, um diese Tabelle darzustellen: +Nun können Sie eine neue Klasse einrichten, um diese Tabelle darzustellen: ```php /** - * Eine ActiveRecord-Klasse ist normalerweise im Singular + * Eine ActiveRecord-Klasse ist normalerweise Singular * * Es wird dringend empfohlen, die Eigenschaften der Tabelle hier als Kommentare hinzuzufügen * @@ -31,64 +31,64 @@ Jetzt können Sie eine neue Klasse einrichten, um diese Tabelle darzustellen: class User extends flight\ActiveRecord { public function __construct($database_connection) { - // so können Sie es einrichten + // Sie können es auf diese Weise einstellen parent::__construct($database_connection, 'users'); - // oder so + // oder auf diese Weise parent::__construct($database_connection, null, [ 'table' => 'users']); } } ``` -Jetzt beobachten Sie, wie die Magie geschieht! +Nun beobachten Sie, wie die Magie geschieht! ```php -// für sqlite -$database_connection = new PDO('sqlite:test.db'); // dies ist nur ein Beispiel, Sie würden wahrscheinlich eine echte Datenbankverbindung verwenden +// Für SQLite +$database_connection = new PDO('sqlite:test.db'); // Dies ist nur ein Beispiel, Sie würden wahrscheinlich eine echte Datenbankverbindung verwenden -// für mysql +// Für MySQL $database_connection = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'username', 'password'); -// oder mysqli +// oder MySQLi $database_connection = new mysqli('localhost', 'username', 'password', 'test_db'); -// oder mysqli mit nicht objektbasierter Erstellung +// oder MySQLi mit nicht-objektbasierter Erstellung $database_connection = mysqli_connect('localhost', 'username', 'password', 'test_db'); $user = new User($database_connection); $user->name = 'Bobby Tables'; -$user->password = password_hash('ein cooles Passwort'); +$user->password = password_hash('some cool password'); $user->insert(); // oder $user->save(); echo $user->id; // 1 $user->name = 'Joseph Mamma'; -$user->password = password_hash('ein anderes cooles Passwort!!!'); +$user->password = password_hash('some cool password again!!!'); $user->insert(); -// $user->save() kann hier nicht verwendet werden, da es als Update betrachtet wird! +// Hier können Sie $user->save() nicht verwenden, da es sonst als Update interpretiert wird! echo $user->id; // 2 ``` -Und es war so einfach, einen neuen Benutzer hinzuzufügen! Jetzt, wo es eine Benutzerzeile in der Datenbank gibt, wie ziehen Sie sie heraus? +Und so einfach war es, einen neuen Benutzer hinzuzufügen! Nun, da eine Benutzerzeile in der Datenbank vorhanden ist, wie holen Sie sie heraus? ```php -$user->find(1); // finde id = 1 in der Datenbank und gebe sie zurück. +$user->find(1); // Findet id = 1 in der Datenbank und gibt es zurück. echo $user->name; // 'Bobby Tables' ``` -Und was ist, wenn Sie alle Benutzer finden möchten? +Und was, wenn Sie alle Benutzer finden möchten? ```php $users = $user->findAll(); ``` -Wie wäre es mit einer bestimmten Bedingung? +Was ist mit einer bestimmten Bedingung? ```php $users = $user->like('name', '%mamma%')->findAll(); ``` -Sehen Sie, wie viel Spaß das macht? Lassen Sie uns das installieren und loslegen! +Sehen Sie, wie viel Spaß das macht? Lassen Sie uns es installieren und loslegen! ## Installation @@ -100,33 +100,33 @@ composer require flightphp/active-record ## Verwendung -Dies kann als eigenständige Bibliothek oder mit dem Flight PHP Framework verwendet werden. Vollständig Ihnen überlassen. +Dies kann als eigenständige Bibliothek oder mit dem Flight PHP Framework verwendet werden. Ganz nach Ihrem Wunsch. ### Eigenständig -Stellen Sie sicher, dass Sie eine PDO-Verbindung an den Konstruktor weitergeben. +Stellen Sie sicher, dass Sie eine PDO-Verbindung an den Konstruktor übergeben. ```php -$pdo_connection = new PDO('sqlite:test.db'); // dies ist nur ein Beispiel, Sie würden wahrscheinlich eine echte Datenbankverbindung verwenden +$pdo_connection = new PDO('sqlite:test.db'); // Dies ist nur ein Beispiel, Sie würden wahrscheinlich eine echte Datenbankverbindung verwenden $User = new User($pdo_connection); ``` -> Möchten Sie nicht immer Ihre Datenbankverbindung im Konstruktor einstellen? Siehe [Datenbankverbindungsmanagement](#database-connection-management) für weitere Ideen! +> Möchten Sie nicht immer die Datenbankverbindung im Konstruktor festlegen? Sehen Sie [Datenbankverbindungsverwaltung](#database-connection-management) für andere Ideen! ### Als Methode in Flight registrieren -Wenn Sie das Flight PHP Framework verwenden, können Sie die ActiveRecord-Klasse als Dienst registrieren, aber das müssen Sie ehrlich gesagt nicht. +Wenn Sie das Flight PHP Framework verwenden, können Sie die ActiveRecord-Klasse als Service registrieren, müssen es aber ehrlich gesagt nicht tun. ```php Flight::register('user', 'User', [ $pdo_connection ]); -// Dann können Sie es so in einem Controller, einer Funktion usw. verwenden. +// Dann können Sie es in einem Controller, einer Funktion usw. so verwenden. Flight::user()->find(1); ``` ## `runway` Methoden -[runway](/awesome-plugins/runway) ist ein CLI-Tool für Flight, das einen benutzerdefinierten Befehl für diese Bibliothek hat. +[runway](/awesome-plugins/runway) ist ein CLI-Tool für Flight, das einen benutzerdefinierten Befehl für diese Bibliothek hat. ```bash # Verwendung @@ -136,7 +136,7 @@ php runway make:record database_table_name [class_name] php runway make:record users ``` -Dies wird eine neue Klasse im Verzeichnis `app/records/` als `UserRecord.php` mit folgendem Inhalt erstellen: +Dies erstellt eine neue Klasse im Verzeichnis `app/records/` als `UserRecord.php` mit folgendem Inhalt: ```php notNull('password')->orderBy('id DESC')->find(); -// finde einen Datensatz nach einer bestimmten id +// Findet einen Datensatz anhand einer spezifischen ID $id = 123; $user->find($id); ``` @@ -203,11 +203,11 @@ $user->findAll(); #### `isHydrated(): boolean` (v0.4.0) -Gibt `true` zurück, wenn der aktuelle Datensatz hydratisiert (aus der Datenbank abgerufen) wurde. +Gibt `true` zurück, wenn der aktuelle Datensatz hydriert wurde (aus der Datenbank abgerufen). ```php $user->find(1); -// wenn ein Datensatz mit Daten gefunden wird... +// Wenn ein Datensatz mit Daten gefunden wird... $user->isHydrated(); // true ``` @@ -224,7 +224,7 @@ $user->insert(); ##### Textbasierte Primärschlüssel -Wenn Sie einen textbasierten Primärschlüssel (wie eine UUID) haben, können Sie den Primärschlüsselwert vor dem Einfügen auf eine von zwei Arten festlegen. +Wenn Sie einen textbasierten Primärschlüssel haben (wie eine UUID), können Sie den Primärschlüsselwert vor dem Einfügen auf eine von zwei Arten festlegen. ```php $user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]); @@ -234,24 +234,24 @@ $user->password = md5('demo'); $user->insert(); // oder $user->save(); ``` -oder Sie können den Primärschlüssel automatisch durch Ereignisse generieren lassen. +Oder Sie lassen den Primärschlüssel automatisch durch Ereignisse generieren. ```php class User extends flight\ActiveRecord { public function __construct($database_connection) { parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]); - // Sie können auch so anstelle des obigen Arrays den Primärschlüssel festlegen. + // Sie können den primaryKey auch auf diese Weise statt im Array oben festlegen. $this->primaryKey = 'uuid'; } protected function beforeInsert(self $self) { - $self->uuid = uniqid(); // oder wie auch immer Sie Ihre einzigartigen IDs generieren müssen + $self->uuid = uniqid(); // oder wie auch immer Sie Ihre eindeutigen IDs generieren müssen } } ``` -Wenn Sie den Primärschlüssel vor dem Einfügen nicht festlegen, wird er auf den `rowid` gesetzt und die Datenbank wird ihn für Sie generieren, aber es wird nicht gespeichert, da dieses Feld möglicherweise nicht in Ihrer Tabelle vorhanden ist. Aus diesem Grund wird empfohlen, das Ereignis zu verwenden, um dies automatisch für Sie zu verwalten. +Wenn Sie den Primärschlüssel vor dem Einfügen nicht festlegen, wird er auf `rowid` gesetzt und die Datenbank generiert ihn für Sie, aber er wird nicht persistiert, da dieses Feld möglicherweise nicht in Ihrer Tabelle existiert. Deshalb wird empfohlen, das Ereignis zu verwenden, um dies automatisch für Sie zu handhaben. #### `update(): boolean|ActiveRecord` @@ -265,7 +265,7 @@ $user->update(); #### `save(): 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. +Fügt den aktuellen Datensatz in die Datenbank ein oder aktualisiert ihn. Wenn der Datensatz eine ID hat, wird er aktualisiert, andernfalls eingefügt. ```php $user = new User($pdo_connection); @@ -274,7 +274,7 @@ $user->password = md5('demo'); $user->save(); ``` -**Hinweis:** Wenn Sie Beziehungen, die in der Klasse definiert sind, haben, werden diese ebenfalls rekursiv gespeichert, wenn sie definiert, instanziiert und überarbeitete Daten zum Aktualisieren aufweisen. (v0.4.0 und höher) +**Hinweis:** Wenn Sie Beziehungen in der Klasse definiert haben, speichert er rekursiv auch diese Beziehungen, wenn sie definiert, instanziiert und schmutzige Daten zum Aktualisieren haben. (v0.4.0 und höher) #### `delete(): boolean` @@ -285,7 +285,7 @@ $user->gt('id', 0)->orderBy('id desc')->find(); $user->delete(); ``` -Sie können auch mehrere Datensätze löschen, indem Sie zuvor eine Suche durchführen. +Sie können auch mehrere Datensätze löschen, indem Sie vorher eine Suche ausführen. ```php $user->like('name', 'Bob%')->delete(); @@ -293,32 +293,32 @@ $user->like('name', 'Bob%')->delete(); #### `dirty(array $dirty = []): ActiveRecord` -"Schmutzige" Daten bezieht sich auf die Daten, die in einem Datensatz geändert wurden. +Schmutzige Daten beziehen sich auf die Daten, die in einem Datensatz geändert wurden. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); -// zu diesem Zeitpunkt ist nichts "schmutzig". +// Bis zu diesem Punkt ist nichts "schmutzig". -$user->email = 'test@example.com'; // jetzt wird die E-Mail als "schmutzig" betrachtet, da sie geändert wurde. +$user->email = 'test@example.com'; // Nun gilt email als "schmutzig", da es geändert wurde. $user->update(); -// jetzt gibt es keine Daten, die schmutzig sind, da sie aktualisiert und in der Datenbank gespeichert wurden +// Nun gibt es keine schmutzigen Daten mehr, da sie aktualisiert und in der Datenbank persistiert wurden -$user->password = password_hash('newpassword'); // jetzt ist dies schmutzig -$user->dirty(); // Nichts zu übergebendes löscht alle schmutzigen Einträge. -$user->update(); // nichts wird aktualisiert, da nichts als schmutzig erfasst wurde. +$user->password = password_hash()'newpassword'); // Nun ist das schmutzig +$user->dirty(); // Ohne Parameter löscht es alle schmutzigen Einträge. +$user->update(); // Nichts wird aktualisiert, da nichts als schmutzig erfasst wurde. -$user->dirty([ 'name' => 'etwas', 'password' => password_hash('ein anderes Passwort') ]); -$user->update(); // sowohl Name als auch Passwort werden aktualisiert. +$user->dirty([ 'name' => 'something', 'password' => password_hash('a different password') ]); +$user->update(); // Sowohl name als auch password werden aktualisiert. ``` #### `copyFrom(array $data): ActiveRecord` (v0.4.0) -Dies ist ein Alias für die Methode `dirty()`. Es ist etwas klarer, was Sie tun. +Dies ist ein Alias für die `dirty()`-Methode. Es ist etwas klarer, was Sie tun. ```php -$user->copyFrom([ 'name' => 'etwas', 'password' => password_hash('ein anderes Passwort') ]); -$user->update(); // sowohl Name als auch Passwort werden aktualisiert. +$user->copyFrom([ 'name' => 'something', 'password' => password_hash('a different password') ]); +$user->update(); // Sowohl name als auch password werden aktualisiert. ``` #### `isDirty(): boolean` (v0.4.0) @@ -333,15 +333,14 @@ $user->isDirty(); // true #### `reset(bool $include_query_data = true): ActiveRecord` -Setzt den aktuellen Datensatz auf seinen ursprünglichen Zustand zurück. Dies ist wirklich gut in Schleifenverhalten zu verwenden. -Wenn Sie `true` übergeben, werden auch die Abfragedaten zurückgesetzt, die verwendet wurden, um das aktuelle Objekt zu finden (Standardverhalten). +Setzt den aktuellen Datensatz auf seinen anfänglichen Zustand zurück. Das ist wirklich gut für Schleifenverhalten zu verwenden. Wenn Sie `true` übergeben, setzt es auch die Abfragedaten zurück, die verwendet wurden, um das aktuelle Objekt zu finden (Standardverhalten). ```php $users = $user->greaterThan('id', 0)->orderBy('id desc')->find(); $user_company = new UserCompany($pdo_connection); foreach($users as $user) { - $user_company->reset(); // beginne mit einem sauberen Zustand + $user_company->reset(); // Mit einer sauberen Tafel beginnen $user_company->user_id = $user->id; $user_company->company_id = $some_company_id; $user_company->insert(); @@ -350,12 +349,12 @@ foreach($users as $user) { #### `getBuiltSql(): string` (v0.4.1) -Nachdem Sie eine `find()`, `findAll()`, `insert()`, `update()` oder `save()`-Methode ausgeführt haben, können Sie das SQL abrufen, das erstellt wurde und für Debugging-Zwecke verwenden. +Nachdem Sie eine `find()`, `findAll()`, `insert()`, `update()` oder `save()`-Methode ausgeführt haben, können Sie den generierten SQL-Code abrufen und für Debugging-Zwecke verwenden. ## SQL-Abfragemethoden #### `select(string $field1 [, string $field2 ... ])` -Sie können nur einige der Spalten in einer Tabelle auswählen, wenn Sie möchten (es ist leistungsfähiger bei wirklich breiten Tabellen mit vielen Spalten) +Sie können nur einige Spalten in einer Tabelle auswählen, wenn Sie möchten (es ist performanter bei wirklich breiten Tabellen mit vielen Spalten) ```php $user->select('id', 'name')->find(); @@ -363,7 +362,7 @@ $user->select('id', 'name')->find(); #### `from(string $table)` -Technisch können Sie auch eine andere Tabelle wählen! Warum nicht?! +Sie können technisch eine andere Tabelle wählen! Warum nicht?! ```php $user->select('id', 'name')->from('user')->find(); @@ -371,7 +370,7 @@ $user->select('id', 'name')->from('user')->find(); #### `join(string $table_name, string $join_condition)` -Sie können sogar eine andere Tabelle in der Datenbank verknüpfen. +Sie können sogar zu einer anderen Tabelle in der Datenbank joinen. ```php $user->join('contacts', 'contacts.user_id = users.id')->find(); @@ -379,13 +378,13 @@ $user->join('contacts', 'contacts.user_id = users.id')->find(); #### `where(string $where_conditions)` -Sie können einige benutzerdefinierte WHERE-Argumente festlegen (Sie können keine Parameter in dieser WHERE-Anweisung festlegen) +Sie können einige benutzerdefinierte where-Argumente setzen (Sie können in dieser where-Anweisung keine Parameter setzen) ```php $user->where('id=1 AND name="demo"')->find(); ``` -**Sicherheitsnotiz** - Sie könnten versucht sein, etwas wie `$user->where("id = '{$id}' AND name = '{$name}'")->find();` zu tun. BITTE MACHEN SIE DAS NICHT!!! Dies ist anfällig für das, was als SQL-Injection-Angriffe bekannt ist. Es gibt viele Artikel online, bitte googeln Sie "sql injection attacks php" und Sie werden viele Artikel zu diesem Thema finden. Der richtige Weg, dies mit dieser Bibliothek zu behandeln, besteht darin, anstelle dieser `where()`-Methode etwas mehr wie `$user->eq('id', $id)->eq('name', $name)->find();` zu tun. Wenn Sie dies absolut tun müssen, hat die `PDO`-Bibliothek `$pdo->quote($var)`, um es für Sie zu escapen. Erst nachdem Sie `quote()` verwenden, können Sie es in einer `where()`-Anweisung verwenden. +**Sicherheitshinweis** - Sie könnten versucht sein, etwas wie `$user->where("id = '{$id}' AND name = '{$name}'")->find();` zu tun. Bitte TUN SIE DAS NICHT!!! Das ist anfällig für SQL-Injection-Angriffe. Es gibt viele Artikel online, suchen Sie bitte nach "sql injection attacks php" und Sie finden viele Artikel zu diesem Thema. Der richtige Weg, das mit dieser Bibliothek zu handhaben, ist, anstelle dieser `where()`-Methode etwas wie `$user->eq('id', $id)->eq('name', $name)->find();` zu tun. Wenn Sie es absolut tun müssen, hat die `PDO`-Bibliothek `$pdo->quote($var)`, um es für Sie zu escapen. Nur nach der Verwendung von `quote()` können Sie es in einer `where()`-Anweisung verwenden. #### `group(string $group_by_statement)/groupBy(string $group_by_statement)` @@ -405,7 +404,7 @@ $user->orderBy('name DESC')->find(); #### `limit(string $limit)/limit(int $offset, int $limit)` -Begrenzen Sie die Anzahl der zurückgegebenen Datensätze. Wenn eine zweite ganze Zahl angegeben wird, wird sie wie in SQL offset und limit. +Begrenzen Sie die Anzahl der zurückgegebenen Datensätze. Wenn eine zweite Ganzzahl gegeben ist, wird sie als offset, limit genau wie in SQL verwendet. ```php $user->orderby('name DESC')->limit(0, 10)->findAll(); @@ -414,7 +413,7 @@ $user->orderby('name DESC')->limit(0, 10)->findAll(); ## WHERE-Bedingungen #### `equal(string $field, mixed $value) / eq(string $field, mixed $value)` -Wo `field = $value` +Where `field = $value` ```php $user->eq('id', 1)->find(); @@ -422,7 +421,7 @@ $user->eq('id', 1)->find(); #### `notEqual(string $field, mixed $value) / ne(string $field, mixed $value)` -Wo `field <> $value` +Where `field <> $value` ```php $user->ne('id', 1)->find(); @@ -430,14 +429,14 @@ $user->ne('id', 1)->find(); #### `isNull(string $field)` -Wo `field IS NULL` +Where `field IS NULL` ```php $user->isNull('id')->find(); ``` #### `isNotNull(string $field) / notNull(string $field)` -Wo `field IS NOT NULL` +Where `field IS NOT NULL` ```php $user->isNotNull('id')->find(); @@ -445,7 +444,7 @@ $user->isNotNull('id')->find(); #### `greaterThan(string $field, mixed $value) / gt(string $field, mixed $value)` -Wo `field > $value` +Where `field > $value` ```php $user->gt('id', 1)->find(); @@ -453,21 +452,21 @@ $user->gt('id', 1)->find(); #### `lessThan(string $field, mixed $value) / lt(string $field, mixed $value)` -Wo `field < $value` +Where `field < $value` ```php $user->lt('id', 1)->find(); ``` #### `greaterThanOrEqual(string $field, mixed $value) / ge(string $field, mixed $value) / gte(string $field, mixed $value)` -Wo `field >= $value` +Where `field >= $value` ```php $user->ge('id', 1)->find(); ``` #### `lessThanOrEqual(string $field, mixed $value) / le(string $field, mixed $value) / lte(string $field, mixed $value)` -Wo `field <= $value` +Where `field <= $value` ```php $user->le('id', 1)->find(); @@ -475,7 +474,7 @@ $user->le('id', 1)->find(); #### `like(string $field, mixed $value) / notLike(string $field, mixed $value)` -Wo `field LIKE $value` oder `field NOT LIKE $value` +Where `field LIKE $value` oder `field NOT LIKE $value` ```php $user->like('name', 'de')->find(); @@ -483,7 +482,7 @@ $user->like('name', 'de')->find(); #### `in(string $field, array $values) / notIn(string $field, array $values)` -Wo `field IN($value)` oder `field NOT IN($value)` +Where `field IN($value)` oder `field NOT IN($value)` ```php $user->in('id', [1, 2])->find(); @@ -491,38 +490,38 @@ $user->in('id', [1, 2])->find(); #### `between(string $field, array $values)` -Wo `field BETWEEN $value AND $value1` +Where `field BETWEEN $value AND $value1` ```php $user->between('id', [1, 2])->find(); ``` -### ODER-Bedingungen +### OR-Bedingungen -Es ist möglich, Ihre Bedingungen in einer ODER-Anweisung einzuwickeln. Dies erfolgt entweder durch die Methoden `startWrap()` und `endWrap()` oder indem Sie den 3. Parameter der Bedingung nach dem Feld und dem Wert ausfüllen. +Es ist möglich, Ihre Bedingungen in einer OR-Anweisung zu umschließen. Dies geschieht entweder mit den Methoden `startWrap()` und `endWrap()` oder indem Sie den 3. Parameter der Bedingung nach Feld und Wert ausfüllen. ```php // Methode 1 $user->eq('id', 1)->startWrap()->eq('name', 'demo')->or()->eq('name', 'test')->endWrap('OR')->find(); -// Dies wird ausgewertet zu `id = 1 AND (name = 'demo' OR name = 'test')` +// Dies wird zu `id = 1 AND (name = 'demo' OR name = 'test')` ausgewertet // Methode 2 $user->eq('id', 1)->eq('name', 'demo', 'OR')->find(); -// Dies wird ausgewertet zu `id = 1 OR name = 'demo'` +// Dies wird zu `id = 1 OR name = 'demo'` ausgewertet ``` ## Beziehungen -Sie können mit dieser Bibliothek mehrere Arten von Beziehungen 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. +Mit dieser Bibliothek können Sie mehrere Arten von Beziehungen festlegen. Sie können one-to-many- und one-to-one-Beziehungen zwischen Tabellen festlegen. Dies erfordert eine etwas zusätzliche Einrichtung in der Klasse im Voraus. -Das Festlegen des `$relations`-Arrays ist nicht schwer, aber die richtige Syntax zu erraten, kann verwirrend sein. +Das Festlegen des `$relations`-Arrays ist nicht schwer, aber das Erraten der korrekten Syntax kann verwirrend sein. ```php protected array $relations = [ - // Sie können den Schlüssel benennen, wie Sie möchten. Der Name des ActiveRecord ist wahrscheinlich gut. Beispiel: user, contact, client + // Sie können den Schlüssel beliebig benennen. Der Name des ActiveRecord ist wahrscheinlich gut. Beispiel: user, contact, client 'user' => [ // erforderlich // self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO - self::HAS_ONE, // dies ist der Beziehungstyp + self::HAS_ONE, // dies ist der Typ der Beziehung // erforderlich 'Some_Class', // dies ist die "andere" ActiveRecord-Klasse, auf die verwiesen wird @@ -533,14 +532,14 @@ protected array $relations = [ // self::HAS_MANY = der Fremdschlüssel, der auf den Join verweist // self::BELONGS_TO = der lokale Schlüssel, der auf den Join verweist 'local_or_foreign_key', - // nur zur Info, dies verbindet sich ebenfalls nur mit dem Primärschlüssel des "anderen" Modells + // Nur so nebenbei, dies joinet auch nur zum Primärschlüssel des "anderen" Modells // optional - [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // zusätzliche Bedingungen, die Sie beim Verknüpfen der Beziehung möchten + [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // zusätzliche Bedingungen, die Sie beim Joinen der Beziehung wollen // $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5)) // optional - 'back_reference_name' // dies ist, wenn Sie diese Beziehung wieder auf sich selbst zurückverweisen möchten, z. B.: $user->contact->user; + 'back_reference_name' // dies ist, wenn Sie diese Beziehung zurück auf sich selbst referenzieren möchten, z. B. $user->contact->user; ]; ] ``` @@ -570,41 +569,142 @@ class Contact extends ActiveRecord{ } ``` -Jetzt haben wir die Referenzen eingerichtet, sodass wir sie sehr einfach verwenden können! +Nun haben wir die Referenzen eingerichtet, sodass wir sie sehr einfach verwenden können! ```php $user = new User($pdo_connection); -// finde den aktuellsten Benutzer. +// Finden Sie den neuesten Benutzer. $user->notNull('id')->orderBy('id desc')->find(); -// hole Kontakte mithilfe der Beziehung: +// Kontakte mit der Beziehung abrufen: foreach($user->contacts as $contact) { echo $contact->id; } -// oder wir können es andersherum machen. +// Oder wir können es umgekehrt tun. $contact = new Contact(); -// finde einen Kontakt +// Einen Kontakt finden $contact->find(); -// hole Benutzer mithilfe der Beziehung: -echo $contact->user->name; // dies ist der Benutzername +// Benutzer mit der Beziehung abrufen: +echo $contact->user->name; // Dies ist der Benutzername ``` -Ganz schön cool, oder? +Ziemlich cool, oder? + +### Eager Loading + +#### Überblick +Eager Loading löst das N+1-Abfrageproblem, indem Beziehungen im Voraus geladen werden. Anstatt für jede Beziehung eines Datensatzes eine separate Abfrage auszuführen, holt Eager Loading alle verwandten Daten in nur einer zusätzlichen Abfrage pro Beziehung. + +> **Hinweis:** Eager Loading ist nur ab v0.7.0 verfügbar. + +#### Grundlegende Verwendung +Verwenden Sie die `with()`-Methode, um anzugeben, welche Beziehungen eager geladen werden sollen: +```php +// Benutzer mit ihren Kontakten in 2 Abfragen laden statt N+1 +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + foreach ($u->contacts as $contact) { + echo $contact->email; // Keine zusätzliche Abfrage! + } +} +``` + +#### Mehrere Beziehungen +Mehrere Beziehungen auf einmal laden: +```php +$users = $user->with(['contacts', 'profile', 'settings'])->findAll(); +``` + +#### Beziehungstypen + +##### HAS_MANY +```php +// Alle Kontakte für jeden Benutzer eager laden +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + // $u->contacts ist bereits als Array geladen + foreach ($u->contacts as $contact) { + echo $contact->email; + } +} +``` +##### HAS_ONE +```php +// Einen Kontakt für jeden Benutzer eager laden +$users = $user->with('contact')->findAll(); +foreach ($users as $u) { + // $u->contact ist bereits als Objekt geladen + echo $u->contact->email; +} +``` + +##### BELONGS_TO +```php +// Elternbenutzer für alle Kontakte eager laden +$contacts = $contact->with('user')->findAll(); +foreach ($contacts as $c) { + // $c->user ist bereits geladen + echo $c->user->name; +} +``` +##### Mit find() +Eager Loading funktioniert sowohl mit +findAll() + als auch +find() +: + +```php +$user = $user->with('contacts')->find(1); +// Benutzer und alle ihre Kontakte in 2 Abfragen geladen +``` +#### Leistungsverbesserungen +Ohne Eager Loading (N+1-Problem): +```php +$users = $user->findAll(); // 1 Abfrage +foreach ($users as $u) { + $contacts = $u->contacts; // N Abfragen (eine pro Benutzer!) +} +// Gesamt: 1 + N Abfragen +``` + +Mit Eager Loading: + +```php +$users = $user->with('contacts')->findAll(); // 2 Abfragen gesamt +foreach ($users as $u) { + $contacts = $u->contacts; // 0 zusätzliche Abfragen! +} +// Gesamt: 2 Abfragen (1 für Benutzer + 1 für alle Kontakte) +``` +Für 10 Benutzer reduziert das die Abfragen von 11 auf 2 - eine Reduktion um 82%! + +#### Wichtige Hinweise +- Eager Loading ist vollständig optional - Lazy Loading funktioniert weiterhin wie zuvor +- Bereits geladene Beziehungen werden automatisch übersprungen +- Back-Referenzen funktionieren mit Eager Loading +- Beziehungs-Callbacks werden während des Eager Loadings berücksichtigt + +#### Einschränkungen +- Verschachteltes Eager Loading (z. B. +with(['contacts.addresses']) +) wird derzeit nicht unterstützt +- Eager-Load-Einschränkungen über Closures werden in dieser Version nicht unterstützt ## Benutzerdefinierte Daten festlegen -Manchmal müssen Sie etwas Einzigartiges an Ihrem ActiveRecord anhängen, z. B. eine benutzerdefinierte Berechnung, die es einfacher machen könnte, einfach an das Objekt anzuhängen, das dann an beispielsweise eine Vorlage übergeben wird. +Manchmal müssen Sie etwas Einzigartiges an Ihr ActiveRecord anhängen, wie eine benutzerdefinierte Berechnung, die einfacher sein könnte, einfach an das Objekt angehängt zu werden, das dann z. B. an eine Vorlage übergeben wird. #### `setCustomData(string $field, mixed $value)` -Sie hängen die benutzerdefinierten Daten mit der Methode `setCustomData()` an. +Sie hängen die benutzerdefinierten Daten mit der `setCustomData()`-Methode an. ```php $user->setCustomData('page_view_count', $page_view_count); ``` -Und dann können Sie einfach auf sie zugreifen wie auf eine normale Objekt-Eigenschaft. +Und dann referenzieren Sie es einfach wie eine normale Objekteigenschaft. ```php echo $user->page_view_count; @@ -612,11 +712,11 @@ echo $user->page_view_count; ## Ereignisse -Eine weitere großartige Funktion dieser Bibliothek sind die Ereignisse. Ereignisse werden zu bestimmten Zeiten ausgelöst, basierend auf bestimmten Methoden, die Sie aufrufen. Sie sind sehr hilfreich, um automatisch Daten für Sie einzurichten. +Eine weitere super coole Funktion dieser Bibliothek sind Ereignisse. Ereignisse werden zu bestimmten Zeiten ausgelöst, basierend auf bestimmten Methoden, die Sie aufrufen. Sie sind 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 festlegen müssen. +Das ist wirklich hilfreich, wenn Sie eine Standardverbindung oder Ähnliches festlegen müssen. ```php // index.php oder bootstrap.php @@ -629,10 +729,10 @@ Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php class User extends flight\ActiveRecord { - protected function onConstruct(self $self, array &$config) { // vergessen Sie nicht, die &-Referenz - // Sie könnten dies tun, um die Verbindung automatisch festzulegen + protected function onConstruct(self $self, array &$config) { // Vergessen Sie nicht die & Referenz + // Sie könnten das tun, um die Verbindung automatisch zu setzen $config['connection'] = Flight::db(); - // oder dies + // oder das $self->transformAndPersistConnection(Flight::db()); // Sie können auch den Tabellennamen auf diese Weise festlegen. @@ -643,7 +743,7 @@ class User extends flight\ActiveRecord { #### `beforeFind(ActiveRecord $ActiveRecord)` -Dies ist wahrscheinlich nur nützlich, wenn Sie jede Abfrage bei Bedarf manipulieren müssen. +Das ist wahrscheinlich nur nützlich, wenn Sie jede Abfrage manipulieren müssen. ```php class User extends flight\ActiveRecord { @@ -654,7 +754,7 @@ class User extends flight\ActiveRecord { } protected function beforeFind(self $self) { - // immer id >= 0 ausführen, wenn das Ihre Vorliebe ist + // Immer id >= 0 ausführen, wenn das Ihr Ding ist $self->gte('id', 0); } } @@ -662,7 +762,7 @@ class User extends flight\ActiveRecord { #### `afterFind(ActiveRecord $ActiveRecord)` -Dies ist wahrscheinlich nützlicher, wenn Sie immer eine Logik ausführen müssen, jedes Mal, wenn dieser Datensatz abgerufen wird. Müssen Sie etwas entschlüsseln? Müssen Sie jedes Mal eine benutzerdefinierte Zählabfrage ausführen (nicht leistungsfähig, aber was soll's)? +Diese ist wahrscheinlich nützlicher, wenn Sie immer etwas Logik ausführen müssen, jedes Mal, wenn dieser Datensatz abgerufen wird. Müssen Sie etwas entschlüsseln? Müssen Sie eine benutzerdefinierte Zählabfrage ausführen (nicht performant, aber egal)? ```php class User extends flight\ActiveRecord { @@ -673,18 +773,18 @@ class User extends flight\ActiveRecord { } protected function afterFind(self $self) { - // etwas entschlüsseln + // Etwas entschlüsseln $self->secret = yourDecryptFunction($self->secret, $some_key); - // vielleicht etwas Benutzerdefiniertes speichern wie eine Abfrage??? - $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']); + // Vielleicht etwas Benutzerdefiniertes speichern wie eine Abfrage??? + $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']; } } ``` #### `beforeFindAll(ActiveRecord $ActiveRecord)` -Dies ist wahrscheinlich nur nützlich, wenn Sie jede Abfrage bei Bedarf manipulieren müssen. +Das ist wahrscheinlich nur nützlich, wenn Sie jede Abfrage manipulieren müssen. ```php class User extends flight\ActiveRecord { @@ -695,7 +795,7 @@ class User extends flight\ActiveRecord { } protected function beforeFindAll(self $self) { - // immer id >= 0 ausführen, wenn das Ihre Vorliebe ist + // Immer id >= 0 ausführen, wenn das Ihr Ding ist $self->gte('id', 0); } } @@ -703,7 +803,7 @@ class User extends flight\ActiveRecord { #### `afterFindAll(array $results)` -Ähnlich wie `afterFind()`, aber Sie können es auf alle Datensätze anwenden! +Ähnlich wie `afterFind()`, aber Sie können es für alle Datensätze tun! ```php class User extends flight\ActiveRecord { @@ -716,7 +816,7 @@ class User extends flight\ActiveRecord { protected function afterFindAll(array $results) { foreach($results as $self) { - // etwas Cooles tun wie bei afterFind() + // Etwas Cooles tun wie afterFind() } } } @@ -724,7 +824,7 @@ class User extends flight\ActiveRecord { #### `beforeInsert(ActiveRecord $ActiveRecord)` -Sehr hilfreich, wenn Sie jedes Mal Standardwerte festlegen müssen. +Wirklich hilfreich, wenn Sie einige Standardwerte jedes Mal festlegen müssen. ```php class User extends flight\ActiveRecord { @@ -735,7 +835,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // einige sinnvolle Standardwerte festlegen + // Einige vernünftige Standardwerte setzen if(!$self->created_date) { $self->created_date = gmdate('Y-m-d'); } @@ -749,7 +849,7 @@ class User extends flight\ActiveRecord { #### `afterInsert(ActiveRecord $ActiveRecord)` -Vielleicht haben Sie einen Benutzerfall, um Daten nach dem Einfügen zu ändern? +Vielleicht haben Sie einen Anwendungsfall, um Daten nach dem Einfügen zu ändern? ```php class User extends flight\ActiveRecord { @@ -760,7 +860,7 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // machen Sie, was Sie möchten + // Machen Sie, was Sie wollen Flight::cache()->set('most_recent_insert_id', $self->id); // oder was auch immer.... } @@ -769,7 +869,7 @@ class User extends flight\ActiveRecord { #### `beforeUpdate(ActiveRecord $ActiveRecord)` -Sehr hilfreich, wenn Sie jedes Mal Standardwerte festlegen müssen, wenn eine Aktualisierung erfolgt. +Wirklich hilfreich, wenn Sie einige Standardwerte jedes Mal bei einer Aktualisierung festlegen müssen. ```php class User extends flight\ActiveRecord { @@ -780,7 +880,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // einige sinnvolle Standardwerte festlegen + // Einige vernünftige Standardwerte setzen if(!$self->updated_date) { $self->updated_date = gmdate('Y-m-d'); } @@ -790,7 +890,7 @@ class User extends flight\ActiveRecord { #### `afterUpdate(ActiveRecord $ActiveRecord)` -Vielleicht haben Sie einen Benutzerfall, um Daten nach der Aktualisierung zu ändern? +Vielleicht haben Sie einen Anwendungsfall, um Daten nach der Aktualisierung zu ändern? ```php class User extends flight\ActiveRecord { @@ -801,7 +901,7 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // machen Sie, was Sie möchten + // Machen Sie, was Sie wollen Flight::cache()->set('most_recently_updated_user_id', $self->id); // oder was auch immer.... } @@ -810,7 +910,7 @@ class User extends flight\ActiveRecord { #### `beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)` -Dies ist nützlich, wenn Sie Ereignisse auslösen möchten, sowohl wenn Einfügungen als auch Aktualisierungen erfolgen. Ich spare Ihnen die lange Erklärung, aber ich bin mir sicher, dass Sie erraten können, was es ist. +Das ist nützlich, wenn Sie Ereignisse haben möchten, die sowohl bei Einfügungen als auch bei Aktualisierungen auftreten. Ich spare mir die lange Erklärung, aber ich bin sicher, Sie können erraten, was es ist. ```php class User extends flight\ActiveRecord { @@ -828,7 +928,7 @@ class User extends flight\ActiveRecord { #### `beforeDelete(ActiveRecord $ActiveRecord)/afterDelete(ActiveRecord $ActiveRecord)` -Ich bin mir nicht sicher, was Sie hier tun möchten, aber hier wird nicht geurteilt! Legen Sie los! +Nicht sicher, was Sie hier tun möchten, aber keine Urteile hier! Legen Sie los! ```php class User extends flight\ActiveRecord { @@ -839,17 +939,17 @@ class User extends flight\ActiveRecord { } protected function beforeDelete(self $self) { - echo 'Er war ein tapferer Soldat... :cry-face:'; + echo 'He was a brave soldier... :cry-face:'; } } ``` -## Verwaltung der Datenbankverbindung +## Datenbankverbindungsverwaltung -Wenn Sie diese Bibliothek verwenden, können Sie die Datenbankverbindung auf mehrere Arten festlegen. Sie können die Verbindung im Konstruktor festlegen, Sie können sie über eine Konfigurationsvariable `$config['connection']` festlegen oder Sie können sie über `setDatabaseConnection()` (v0.4.1) festlegen. +Wenn Sie diese Bibliothek verwenden, können Sie die Datenbankverbindung auf einige verschiedene Weisen festlegen. Sie können die Verbindung im Konstruktor festlegen, über eine Konfigurationsvariable `$config['connection']` oder über `setDatabaseConnection()` (v0.4.1). ```php -$pdo_connection = new PDO('sqlite:test.db'); // zum Beispiel +$pdo_connection = new PDO('sqlite:test.db'); // als Beispiel $user = new User($pdo_connection); // oder $user = new User(null, [ 'connection' => $pdo_connection ]); @@ -858,11 +958,11 @@ $user = new User(); $user->setDatabaseConnection($pdo_connection); ``` -Wenn Sie vermeiden möchten, jedes Mal eine `$database_connection` festzulegen, wenn Sie einen aktiven Datensatz aufrufen, gibt es Möglichkeiten, dies zu umgehen! +Wenn Sie vermeiden möchten, immer eine `$database_connection` jedes Mal festzulegen, wenn Sie ein Active Record aufrufen, gibt es Wege darum! ```php // index.php oder bootstrap.php -// Setzen Sie dies als registrierte Klasse in Flight +// Dies als registrierte Klasse in Flight festlegen Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php @@ -875,23 +975,23 @@ class User extends flight\ActiveRecord { } } -// Und jetzt, keine Argumente erforderlich! +// Und nun keine Argumente erforderlich! $user = new User(); ``` -> **Hinweis:** Wenn Sie planen, Unit-Tests durchzuführen, kann es einige Herausforderungen beim Testen mit dieser Methode geben, aber insgesamt ist es nicht zu schlecht, da Sie Ihre Verbindung mit `setDatabaseConnection()` oder `$config['connection']` injizieren können. +> **Hinweis:** Wenn Sie Unit-Tests planen, kann das auf diese Weise einige Herausforderungen für Unit-Tests hinzufügen, aber insgesamt, da Sie Ihre Verbindung mit `setDatabaseConnection()` oder `$config['connection']` injizieren können, ist es nicht zu schlecht. -Wenn Sie die Datenbankverbindung aktualisieren müssen, z. B. wenn Sie ein lang laufendes CLI-Skript ausführen und die Verbindung von Zeit zu Zeit aktualisieren müssen, können Sie die Verbindung mit `$your_record->setDatabaseConnection($pdo_connection)` erneut festlegen. +Wenn Sie die Datenbankverbindung aktualisieren müssen, z. B. wenn Sie ein langes CLI-Skript ausführen und die Verbindung alle paar Mal aktualisieren müssen, können Sie die Verbindung mit `$your_record->setDatabaseConnection($pdo_connection)` neu setzen. -## Beitragen +## Mitwirkung Bitte tun Sie das. :D ### Einrichtung -Wenn Sie einen Beitrag leisten, stellen Sie sicher, dass Sie `composer test-coverage` ausführen, um 100 % Testabdeckung aufrechtzuerhalten (das ist keine echte Unit-Testabdeckung, mehr wie Integrationstests). +Wenn Sie beitragen, stellen Sie sicher, dass Sie `composer test-coverage` ausführen, um 100% Testabdeckung zu wahren (das ist keine echte Unit-Test-Abdeckung, eher wie Integrationstests). -Stellen Sie auch sicher, dass Sie `composer beautify` und `composer phpcs` ausführen, um alle Linting-Fehler zu beheben. +Stellen Sie auch sicher, dass Sie `composer beautify` und `composer phpcs` ausführen, um Linting-Fehler zu beheben. ## Lizenz diff --git a/content/v3/de/awesome-plugins/apm.md b/content/v3/de/awesome-plugins/apm.md index 27c51e73..7fb9d74c 100644 --- a/content/v3/de/awesome-plugins/apm.md +++ b/content/v3/de/awesome-plugins/apm.md @@ -1,18 +1,18 @@ # FlightPHP APM Dokumentation -Willkommen bei FlightPHP APM – dem persönlichen Performance-Coach für Ihre App! Dieser Leitfaden ist Ihre Roadmap zur Einrichtung, Nutzung und Beherrschung der Application Performance Monitoring (APM) mit FlightPHP. Ob Sie langsame Anfragen aufspüren oder einfach nur Latency-Diagramme analysieren möchten, wir haben Sie abgedeckt. Lassen Sie uns Ihre App schneller machen, Ihre Nutzer glücklicher und Ihre Debugging-Sitzungen zu einem Kinderspiel! +Willkommen bei FlightPHP APM – dem persönlichen Performance-Coach Ihrer App! Dieser Leitfaden ist Ihre Roadmap zur Einrichtung, Nutzung und Beherrschung der Application Performance Monitoring (APM) mit FlightPHP. Ob Sie langsame Anfragen aufspüren oder einfach nur über Latenzdiagramme schwärmen möchten, wir haben Sie abgedeckt. Lassen Sie uns Ihre App schneller machen, Ihre Nutzer glücklicher und Ihre Debugging-Sitzungen zu einem Kinderspiel! -Sehen Sie sich eine [Demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) des Dashboards für die Flight Docs Site an. +Sehen Sie sich eine [Demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) des Dashboards für die Flight Docs-Seite an. ![FlightPHP APM](/images/apm.png) ## Warum APM wichtig ist -Stellen Sie sich vor: Ihre App ist ein volles Restaurant. Ohne eine Möglichkeit, zu verfolgen, wie lange Bestellungen dauern oder wo die Küche stockt, raten Sie, warum Kunden unzufrieden gehen. APM ist Ihr Sous-Chef – es beobachtet jeden Schritt, von eingehenden Anfragen bis zu Datenbankabfragen, und markiert alles, was Sie verlangsamt. Langsame Seiten verlieren Nutzer (Studien sagen, 53 % verlassen die Seite, wenn sie mehr als 3 Sekunden zum Laden braucht!), und APM hilft Ihnen, diese Probleme *bevor* sie schmerzen zu erkennen. Es ist proaktive Seelenruhe – weniger „Warum ist das kaputt?“-Momente, mehr „Schau, wie reibungslos das läuft!“-Erfolge. +Stellen Sie sich vor: Ihre App ist ein volles Restaurant. Ohne eine Möglichkeit, zu verfolgen, wie lange Bestellungen dauern oder wo die Küche ins Stocken gerät, raten Sie nur, warum die Kunden verärgert gehen. APM ist Ihr Sous-Chef – es überwacht jeden Schritt, von eingehenden Anfragen bis zu Datenbankabfragen, und markiert alles, was Sie verlangsamt. Langsame Seiten verlieren Nutzer (Studien sagen, 53 % verlassen die Seite, wenn sie mehr als 3 Sekunden zum Laden braucht!), und APM hilft Ihnen, diese Probleme *bevor* sie schmerzen, zu erkennen. Es ist proaktive Seelenfrieden – weniger „Warum ist das kaputt?“-Momente, mehr „Schaut, wie geschmeidig das läuft!“-Erfolge. ## Installation -Beginnen Sie mit Composer: +Legen Sie mit Composer los: ```bash composer require flightphp/apm @@ -24,16 +24,16 @@ Sie benötigen: ## Unterstützte Datenbanken -FlightPHP APM unterstützt derzeit die folgenden Datenbanken zur Speicherung von Metriken: +FlightPHP APM unterstützt derzeit die folgenden Datenbanken zum Speichern von Metriken: - **SQLite3**: Einfach, dateibasiert und ideal für lokale Entwicklung oder kleine Apps. Standardoption in den meisten Setups. -- **MySQL/MariaDB**: Ideal für größere Projekte oder Produktionsumgebungen, in denen Sie robuste, skalierbare Speicherung benötigen. +- **MySQL/MariaDB**: Ideal für größere Projekte oder Produktionsumgebungen, in denen Sie robusten, skalierbaren Speicher benötigen. Sie können Ihren Datenbanktyp während des Konfigurationsschritts wählen (siehe unten). Stellen Sie sicher, dass Ihre PHP-Umgebung die notwendigen Erweiterungen installiert hat (z. B. `pdo_sqlite` oder `pdo_mysql`). ## Erste Schritte -Hier ist Ihr Schritt-für-Schritt zu APM-Großartigkeit: +Hier ist Ihr Schritt-für-Schritt-Weg zur APM-Größe: ### 1. Registrieren Sie die APM @@ -41,6 +41,7 @@ Fügen Sie das in Ihre `index.php` oder eine `services.php`-Datei ein, um mit de ```php use flight\apm\logger\LoggerFactory; +use flight\database\PdoWrapper; use flight\Apm; $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); @@ -54,18 +55,18 @@ $Apm->addPdoConnection($pdo); ``` **Was passiert hier?** -- `LoggerFactory::create()` greift auf Ihre Konfiguration zu (mehr dazu bald) und richtet einen Logger ein – standardmäßig SQLite. -- `Apm` ist der Star – es hört auf Flights Events (Anfragen, Routen, Fehler usw.) und sammelt Metriken. +- `LoggerFactory::create()` greift auf Ihre Konfiguration zu (mehr dazu bald) und richtet einen Logger ein – SQLite standardmäßig. +- `Apm` ist der Star – es hört auf Flight-Events (Anfragen, Routen, Fehler usw.) und sammelt Metriken. - `bindEventsToFlightInstance($app)` verbindet alles mit Ihrer Flight-App. **Pro-Tipp: Sampling** -Wenn Ihre App beschäftigt ist, könnte das Loggen *jeder* Anfrage die Dinge überlasten. Verwenden Sie eine Sample-Rate (0.0 bis 1.0): +Wenn Ihre App beschäftigt ist, könnte das Logging *jeder* Anfrage Dinge überlasten. Verwenden Sie eine Sample-Rate (0.0 bis 1.0): ```php $Apm = new Apm($ApmLogger, 0.1); // Protokolliert 10 % der Anfragen ``` -Das hält die Performance knackig, während es Ihnen dennoch solide Daten liefert. +Das hält die Performance knackig, während es Ihnen immer noch solide Daten liefert. ### 2. Konfigurieren Sie es @@ -76,7 +77,7 @@ php vendor/bin/runway apm:init ``` **Was macht das?** -- Startet einen Wizard, der fragt, wo rohe Metriken herkommen (Quelle) und wo verarbeitete Daten hingehen (Ziel). +- Startet einen Wizard, der fragt, wo rohe Metriken herkommen (Quelle) und wohin verarbeitete Daten gehen (Ziel). - Standard ist SQLite – z. B. `sqlite:/tmp/apm_metrics.sqlite` für die Quelle, eine andere für das Ziel. - Sie erhalten eine Konfiguration wie: ```json @@ -97,13 +98,13 @@ Rohe Metriken häufen sich schnell an (denken Sie an ungefilterte Logs). Der Wor ### 3. Metriken mit dem Worker verarbeiten -Der Worker verwandelt rohe Metriken in dashboard-bereite Daten. Führen Sie ihn einmal aus: +Der Worker verwandelt rohe Metriken in dashboard-bereite Daten. Führen Sie es einmal aus: ```bash php vendor/bin/runway apm:worker ``` -**Was macht er?** +**Was macht es?** - Liest aus Ihrer Quelle (z. B. `apm_metrics.sqlite`). - Verarbeitet bis zu 100 Metriken (Standard-Batch-Größe) in Ihr Ziel. - Stoppt, wenn fertig oder keine Metriken mehr da sind. @@ -125,7 +126,7 @@ Für Live-Apps möchten Sie kontinuierliche Verarbeitung. Hier sind Ihre Optione Feuert jede Minute – perfekt für Produktion. - **Tmux/Screen**: - Starten Sie eine abtrennbare Sitzung: + Starten Sie eine abtrennbare Session: ```bash tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon @@ -142,7 +143,7 @@ Für Live-Apps möchten Sie kontinuierliche Verarbeitung. Hier sind Ihre Optione - `--timeout 300`: Beendet nach 5 Minuten. **Warum die Mühe?** -Ohne den Worker ist Ihr Dashboard leer. Es ist die Brücke zwischen rohen Logs und handlungsrelevanten Erkenntnissen. +Ohne den Worker ist Ihr Dashboard leer. Es ist die Brücke zwischen rohen Logs und handlungsrelevanten Einblicken. ### 4. Dashboard starten @@ -154,7 +155,7 @@ php vendor/bin/runway apm:dashboard **Was ist das?** - Startet einen PHP-Server unter `http://localhost:8001/apm/dashboard`. -- Zeigt Anfragen-Logs, langsame Routen, Fehlerquoten und mehr. +- Zeigt Anfrage-Logs, langsame Routen, Fehlerquoten und mehr. **Anpassen**: ```bash @@ -173,20 +174,20 @@ Für die Produktion müssen Sie möglicherweise einige Techniken ausprobieren, u - **Reverse Proxy verwenden**: Richten Sie Nginx oder Apache ein, um Anfragen an das Dashboard weiterzuleiten. - **SSH-Tunnel**: Wenn Sie per SSH auf den Server zugreifen können, verwenden Sie `ssh -L 8080:localhost:8001 youruser@yourserver`, um das Dashboard zu Ihrem lokalen Rechner zu tunneln. - **VPN**: Wenn Ihr Server hinter einem VPN ist, verbinden Sie sich damit und greifen Sie direkt auf das Dashboard zu. -- **Firewall konfigurieren**: Öffnen Sie Port 8001 für Ihre IP oder das Netzwerk des Servers. (Oder welchen Port Sie auch eingestellt haben). -- **Apache/Nginx konfigurieren**: Wenn Sie einen Webserver vor Ihrer Anwendung haben, können Sie ihn für eine Domain oder Subdomain konfigurieren. Wenn Sie das tun, setzen Sie das Document Root auf `/path/to/your/project/vendor/flightphp/apm/dashboard`. +- **Firewall konfigurieren**: Öffnen Sie Port 8001 für Ihre IP oder das Netzwerk des Servers (oder welchen Port Sie auch gesetzt haben). +- **Apache/Nginx konfigurieren**: Wenn Sie einen Webserver vor Ihrer Anwendung haben, können Sie ihn auf eine Domain oder Subdomain konfigurieren. Wenn Sie das tun, setzen Sie das Dokumenten-Root auf `/path/to/your/project/vendor/flightphp/apm/dashboard`. -#### Wollen Sie ein anderes Dashboard? +#### Ein anderes Dashboard gewünscht? -Sie können Ihr eigenes Dashboard bauen, wenn Sie möchten! Schauen Sie in das Verzeichnis `vendor/flightphp/apm/src/apm/presenter` für Ideen, wie Sie die Daten für Ihr eigenes Dashboard präsentieren können! +Sie können Ihr eigenes Dashboard bauen, wenn Sie möchten! Schauen Sie im Verzeichnis `vendor/flightphp/apm/src/apm/presenter` nach Ideen, wie Sie die Daten für Ihr eigenes Dashboard präsentieren können! ## Dashboard-Funktionen Das Dashboard ist Ihr APM-Hauptquartier – hier ist, was Sie sehen werden: -- **Anfragen-Log**: Jede Anfrage mit Zeitstempel, URL, Response-Code und Gesamtzeit. Klicken Sie auf „Details“ für Middleware, Abfragen und Fehler. +- **Anfrage-Log**: Jede Anfrage mit Zeitstempel, URL, Response-Code und Gesamtzeit. Klicken Sie auf „Details“ für Middleware, Abfragen und Fehler. - **Langsamste Anfragen**: Top 5 Anfragen, die Zeit fressen (z. B. „/api/heavy“ bei 2,5 s). -- **Langsamste Routen**: Top 5 Routen nach durchschnittlicher Zeit – super zum Erkennen von Mustern. +- **Langsamste Routen**: Top 5 Routen nach durchschnittlicher Zeit – toll zum Erkennen von Mustern. - **Fehlerquote**: Prozentsatz fehlgeschlagener Anfragen (z. B. 2,3 % 500er). - **Latenz-Percentile**: 95. (p95) und 99. (p99) Response-Zeiten – kennen Sie Ihre Worst-Case-Szenarien. - **Response-Code-Diagramm**: Visualisieren Sie 200er, 404er, 500er über die Zeit. @@ -195,7 +196,7 @@ Das Dashboard ist Ihr APM-Hauptquartier – hier ist, was Sie sehen werden: **Extras**: - Filtern nach „Letzte Stunde“, „Letzter Tag“ oder „Letzte Woche“. -- Umschalten auf Dark Mode für nächtliche Sessions. +- Umschalten auf Dark Mode für diese späten Nachte-Sitzungen. **Beispiel**: Eine Anfrage an `/users` könnte zeigen: @@ -219,7 +220,7 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ``` **Wo erscheint es?** -In den Anfragen-Details des Dashboards unter „Custom Events“ – erweiterbar mit hübscher JSON-Formatierung. +Im Dashboard unter „Details der Anfrage“ bei „Benutzerdefinierte Events“ – erweiterbar mit hübscher JSON-Formatierung. **Anwendungsfall**: ```php @@ -233,7 +234,7 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ ``` Jetzt sehen Sie, ob diese API Ihre App herunterzieht! -## Datenbank-Monitoring +## Datenbank-Überwachung Verfolgen Sie PDO-Abfragen so: @@ -252,7 +253,7 @@ $Apm->addPdoConnection($pdo); **Achtung**: - **Optional**: Überspringen Sie das, wenn Sie kein DB-Tracking brauchen. - **Nur PdoWrapper**: Core PDO ist noch nicht integriert – bleiben Sie dran! -- **Performance-Warnung**: Das Loggen jeder Abfrage auf einer DB-lastigen Site kann Dinge verlangsamen. Verwenden Sie Sampling (`$Apm = new Apm($ApmLogger, 0.1)`), um die Last zu reduzieren. +- **Performance-Warnung**: Das Logging jeder Abfrage auf einer DB-lastigen Site kann Dinge verlangsamen. Verwenden Sie Sampling (`$Apm = new Apm($ApmLogger, 0.1)`), um die Last zu verringern. **Beispiel-Ausgabe**: - Abfrage: `SELECT name FROM products WHERE price > 100` @@ -266,7 +267,7 @@ Passen Sie den Worker nach Ihrem Geschmack an: - `--timeout 300`: Stoppt nach 5 Minuten – gut für Tests. - `--max_messages 500`: Begrenzt auf 500 Metriken – hält es endlich. - `--batch_size 200`: Verarbeitet 200 auf einmal – balanciert Geschwindigkeit und Speicher. -- `--daemon`: Läuft non-stop – ideal für Live-Monitoring. +- `--daemon`: Läuft non-stop – ideal für Live-Überwachung. **Beispiel**: ```bash @@ -274,26 +275,26 @@ php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ``` Läuft eine Stunde, verarbeitet 100 Metriken auf einmal. -## Request ID in der App +## Request-ID in der App -Jede Anfrage hat eine eindeutige Request ID für das Tracking. Sie können diese ID in Ihrer App verwenden, um Logs und Metriken zu korrelieren. Zum Beispiel können Sie die Request ID auf einer Fehlerseite hinzufügen: +Jede Anfrage hat eine eindeutige Request-ID zum Tracking. Sie können diese ID in Ihrer App verwenden, um Logs und Metriken zu korrelieren. Zum Beispiel können Sie die Request-ID auf einer Fehlerseite hinzufügen: ```php Flight::map('error', function($message) { - // Holen Sie die Request ID aus dem Response-Header X-Flight-Request-Id + // Holen Sie die Request-ID aus dem Response-Header X-Flight-Request-Id $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); // Zusätzlich könnten Sie sie aus der Flight-Variable holen // Diese Methode funktioniert nicht gut in Swoole oder anderen asynchronen Plattformen. // $requestId = Flight::get('apm.request_id'); - echo "Fehler: $message (Request ID: $requestId)"; + echo "Fehler: $message (Request-ID: $requestId)"; }); ``` ## Upgrade -Wenn Sie auf eine neuere Version der APM upgraden, besteht die Möglichkeit, dass Datenbank-Migrationen ausgeführt werden müssen. Sie können das tun, indem Sie den folgenden Befehl ausführen: +Wenn Sie auf eine neuere Version der APM upgraden, besteht die Chance, dass Datenbank-Migrationen ausgeführt werden müssen. Sie können das tun, indem Sie den folgenden Befehl ausführen: ```bash php vendor/bin/runway apm:migrate @@ -302,7 +303,17 @@ Das führt alle benötigten Migrationen aus, um das Datenbankschema auf die neue **Hinweis:** Wenn Ihre APM-Datenbank groß ist, können diese Migrationen einige Zeit in Anspruch nehmen. Sie möchten diesen Befehl vielleicht während der Nebenzeiten ausführen. -## Alte Daten bereinigen +### Upgrade von 0.4.3 -> 0.5.0 + +Wenn Sie von 0.4.3 auf 0.5.0 upgraden, müssen Sie den folgenden Befehl ausführen: + +```bash +php vendor/bin/runway apm:config-migrate +``` + +Das migriert Ihre Konfiguration vom alten Format mit der `.runway-config.json`-Datei ins neue Format, das Schlüssel/Werte in der `config.php`-Datei speichert. + +## Bereinigen alter Daten Um Ihre Datenbank ordentlich zu halten, können Sie alte Daten bereinigen. Das ist besonders nützlich, wenn Sie eine beschäftigte App betreiben und die Datenbankgröße handhabbar halten möchten. Sie können das tun, indem Sie den folgenden Befehl ausführen: @@ -321,7 +332,7 @@ Das entfernt alle Daten, die älter als 7 Tage sind, aus der Datenbank. Feststecken? Probieren Sie diese aus: -- **Kein Dashboard-Daten?** +- **Keine Dashboard-Daten?** - Läuft der Worker? Überprüfen Sie `ps aux | grep apm:worker`. - Stimmen die Konfigurationspfade? Überprüfen Sie, ob die DSNs in `.runway-config.json` auf echte Dateien zeigen. - Führen Sie `php vendor/bin/runway apm:worker` manuell aus, um ausstehende Metriken zu verarbeiten. @@ -340,8 +351,8 @@ Feststecken? Probieren Sie diese aus: - Reduzieren Sie die Batch-Größe: `--batch_size 20`. - **Keine Ausnahmen/Fehler getrackt?** - - Wenn Sie [Tracy](https://tracy.nette.org/) für Ihr Projekt aktiviert haben, überschreibt es die Fehlerbehandlung von Flight. Sie müssen Tracy deaktivieren und sicherstellen, dass `Flight::set('flight.handle_errors', true);` gesetzt ist. + - Wenn Sie [Tracy](https://tracy.nette.org/) für Ihr Projekt aktiviert haben, überschreibt es die Fehlerbehandlung von Flight. Sie müssen Tracy deaktivieren und dann sicherstellen, dass `Flight::set('flight.handle_errors', true);` gesetzt ist. -- **Datenbankabfragen nicht getrackt?** +- **Keine Datenbankabfragen getrackt?** - Stellen Sie sicher, dass Sie `PdoWrapper` für Ihre Datenbankverbindungen verwenden. - - Vergewissern Sie sich, dass Sie das letzte Argument im Konstruktor auf `true` setzen. \ No newline at end of file + - Machen Sie sicher, dass das letzte Argument im Konstruktor `true` ist. \ No newline at end of file diff --git a/content/v3/de/awesome-plugins/awesome_plugins.md b/content/v3/de/awesome-plugins/awesome_plugins.md index 97f32378..993587b4 100644 --- a/content/v3/de/awesome-plugins/awesome_plugins.md +++ b/content/v3/de/awesome-plugins/awesome_plugins.md @@ -1,28 +1,28 @@ -# Tolle Plugins +# Awesome 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 und andere sind Micro/Lite-Bibliotheken, um Ihnen den Einstieg zu erleichtern. +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, und andere sind Micro/Lite-Bibliotheken, um Ihnen den Einstieg zu erleichtern. ## API-Dokumentation -API-Dokumentation ist entscheidend für jede API. Sie hilft Entwicklern zu verstehen, wie sie mit Ihrer API interagieren können und was sie als Rückgabe erwarten können. Es gibt ein paar Tools, die Ihnen helfen können, API-Dokumentation für Ihre Flight-Projekte zu generieren. +API-Dokumentation ist entscheidend für jede API. Sie hilft Entwicklern zu verstehen, wie sie mit Ihrer API interagieren können und was sie als Rückgabe erwarten können. Es gibt ein paar Tools, die Ihnen helfen, API-Dokumentation für Ihre Flight-Projekte zu generieren. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Blog-Beitrag von Daniel Schreiber darüber, wie man die OpenAPI-Spezifikation mit FlightPHP verwendet, um Ihre API mit einem API-First-Ansatz aufzubauen. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ist ein großartiges Tool, um API-Dokumentation für Ihre Flight-Projekte zu generieren. Es ist sehr einfach zu verwenden und kann an Ihre Bedürfnisse angepasst werden. Dies ist die PHP-Bibliothek, die Ihnen hilft, die Swagger-Dokumentation zu generieren. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Blogbeitrag von Daniel Schreiber darüber, wie man die OpenAPI-Spezifikation mit FlightPHP verwendet, um Ihre API mit einem API-First-Ansatz aufzubauen. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ist ein großartiges Tool, um API-Dokumentation für Ihre Flight-Projekte zu generieren. Es ist sehr einfach zu bedienen und kann an Ihre Bedürfnisse angepasst werden. Dies ist die PHP-Bibliothek, die Ihnen hilft, die Swagger-Dokumentation zu generieren. -## Anwendungsleistungsüberwachung (APM) +## Application Performance Monitoring (APM) -Anwendungsleistungsüberwachung (APM) ist entscheidend für jede Anwendung. Sie hilft Ihnen zu verstehen, wie Ihre Anwendung performt und wo die Engpässe liegen. Es gibt eine Reihe von APM-Tools, die mit Flight verwendet werden können. +Application Performance Monitoring (APM) ist entscheidend für jede Anwendung. Es hilft Ihnen zu verstehen, wie Ihre Anwendung performt und wo die Engpässe liegen. Es gibt eine Reihe von APM-Tools, die mit Flight verwendet werden können. - offiziell [flightphp/apm](/awesome-plugins/apm) - Flight APM ist eine einfache APM-Bibliothek, die verwendet werden kann, um Ihre Flight-Anwendungen zu überwachen. Sie kann verwendet werden, um die Leistung Ihrer Anwendung zu überwachen und Ihnen zu helfen, Engpässe zu identifizieren. -## Asynchron +## Async -Flight ist bereits ein schnelles Framework, aber wenn man es mit einem Turbo-Motor ausstattet, wird alles noch unterhaltsamer (und herausfordernder)! +Flight ist bereits ein schnelles Framework, aber es mit einem Turbolader auszustatten macht alles noch spaßiger (und herausfordernder)! - [flightphp/async](/awesome-plugins/async) - Offizielle Flight Async-Bibliothek. Diese Bibliothek ist eine einfache Möglichkeit, asynchrone Verarbeitung zu Ihrer Anwendung hinzuzufügen. Sie verwendet Swoole/Openswoole im Hintergrund, um eine einfache und effektive Möglichkeit zu bieten, Aufgaben asynchron auszuführen. -## Autorisierung/Berechtigungen +## Authorization/Permissions -Autorisierung und Berechtigungen sind entscheidend für jede Anwendung, die Steuerelemente benötigt, um zu definieren, wer auf was zugreifen kann. +Autorisierung und Berechtigungen sind entscheidend für jede Anwendung, die Steuerelemente für den Zugriff auf bestimmte Inhalte erfordert. - offiziell [flightphp/permissions](/awesome-plugins/permissions) - Offizielle Flight Permissions-Bibliothek. Diese Bibliothek ist eine einfache Möglichkeit, Benutzer- und Anwendungsebene-Berechtigungen zu Ihrer Anwendung hinzuzufügen. @@ -30,7 +30,7 @@ Autorisierung und Berechtigungen sind entscheidend für jede Anwendung, die Steu Caching ist eine großartige Möglichkeit, Ihre Anwendung zu beschleunigen. Es gibt eine Reihe von Caching-Bibliotheken, die mit Flight verwendet werden können. -- offiziell [flightphp/cache](/awesome-plugins/php-file-cache) - Leichte, einfache und eigenständige PHP In-File-Caching-Klasse +- offiziell [flightphp/cache](/awesome-plugins/php-file-cache) - Leichte, einfache und eigenständige PHP-in-File-Caching-Klasse ## CLI @@ -40,7 +40,7 @@ CLI-Anwendungen sind eine großartige Möglichkeit, mit Ihrer Anwendung zu inter ## Cookies -Cookies sind eine großartige Möglichkeit, kleine Datenmengen auf der Client-Seite zu speichern. Sie können verwendet werden, um Benutzereinstellungen, Anwendungseinstellungen und mehr zu speichern. +Cookies sind eine großartige Möglichkeit, kleine Datenmengen auf der Client-Seite zu speichern. Sie können verwendet werden, um Benutzerpräferenzen, Anwendungseinstellungen und mehr zu speichern. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie ist eine PHP-Bibliothek, die eine einfache und effektive Möglichkeit bietet, Cookies zu verwalten. @@ -48,50 +48,50 @@ Cookies sind eine großartige Möglichkeit, kleine Datenmengen auf der Client-Se Debugging ist entscheidend, wenn Sie in Ihrer lokalen Umgebung entwickeln. Es gibt ein paar Plugins, die Ihr Debugging-Erlebnis verbessern können. -- [tracy/tracy](/awesome-plugins/tracy) - Dies ist ein vollständiges Fehlerbehandlungs-Tool, das mit Flight verwendet werden kann. Es hat eine Reihe von Panels, die Ihnen helfen können, Ihre Anwendung zu debuggen. Es ist auch sehr einfach zu erweitern und eigene Panels hinzuzufügen. -- offiziell [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - In Verbindung mit dem [Tracy](/awesome-plugins/tracy) Fehlerbehandlungs-Tool fügt dieses Plugin ein paar zusätzliche Panels hinzu, die speziell für das Debugging von Flight-Projekten helfen. +- [tracy/tracy](/awesome-plugins/tracy) - Dies ist ein vollständiges Fehlerbehandlungstool, das mit Flight verwendet werden kann. Es verfügt über eine Reihe von Panels, die Ihnen helfen können, Ihre Anwendung zu debuggen. Es ist auch sehr einfach zu erweitern und eigene Panels hinzuzufügen. +- offiziell [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - In Verbindung mit dem [Tracy](/awesome-plugins/tracy) Fehlerbehandlungstool fügt dieses Plugin ein paar zusätzliche Panels hinzu, um das Debugging speziell für Flight-Projekte zu erleichtern. -## Datenbanken +## Databases Datenbanken sind der Kern der meisten Anwendungen. So speichern und rufen Sie Daten ab. Einige Datenbank-Bibliotheken sind einfach Wrapper, um Abfragen zu schreiben, und einige sind vollwertige ORMs. -- offiziell [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Offizieller Flight PDO Wrapper, der zum Kern gehört. Dies ist ein einfacher Wrapper, der den Prozess des Schreibens und Ausführens von Abfragen vereinfacht. Es handelt sich nicht um ein ORM. +- offiziell [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Offizieller Flight PDO-Wrapper, der zum Kern gehört. Dies ist ein einfacher Wrapper, der den Prozess des Schreibens und Ausführens von Abfragen vereinfacht. Es handelt sich nicht um ein ORM. - offiziell [flightphp/active-record](/awesome-plugins/active-record) - Offizielles Flight ActiveRecord ORM/Mapper. Tolle kleine Bibliothek, um Daten einfach in Ihrer Datenbank abzurufen und zu speichern. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin, um alle Datenbankänderungen für Ihr Projekt zu verfolgen. -## Verschlüsselung +## Encryption -Verschlüsselung ist entscheidend für jede Anwendung, die sensible Daten speichert. Das Verschlüsseln und Entschlüsseln von Daten ist nicht allzu schwer, aber das ordnungsgemäße Speichern des Verschlüsselungsschlüssels [kann](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [sein](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [schwierig](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Das Wichtigste ist, Ihren Verschlüsselungsschlüssel niemals in einem öffentlichen Verzeichnis zu speichern oder ihn in Ihr Code-Repository zu committen. +Verschlüsselung ist entscheidend für jede Anwendung, die sensible Daten speichert. Das Verschlüsseln und Entschlüsseln der Daten ist nicht allzu schwer, aber das ordnungsgemäße Speichern des Verschlüsselungsschlüssels [kann](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [sein](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [schwierig](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Das Wichtigste ist, Ihren Verschlüsselungsschlüssel niemals in einem öffentlichen Verzeichnis zu speichern oder ihn in Ihr Code-Repository zu committen. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Dies ist eine Bibliothek, die verwendet werden kann, um Daten zu verschlüsseln und zu entschlüsseln. Der Einstieg ist ziemlich einfach, um mit dem Verschlüsseln und Entschlüsseln von Daten zu beginnen. -## Job-Warteschlange +## Job Queue -Job-Warteschlangen sind wirklich hilfreich, um Aufgaben asynchron zu verarbeiten. Das kann das Versenden von E-Mails, die Verarbeitung von Bildern oder alles sein, was nicht in Echtzeit erledigt werden muss. +Job-Warteschlangen sind wirklich hilfreich, um Aufgaben asynchron zu verarbeiten. Dies kann das Senden von E-Mails, das Verarbeiten von Bildern oder alles sein, was nicht in Echtzeit erledigt werden muss. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue ist eine Bibliothek, die verwendet werden kann, um Jobs asynchron zu verarbeiten. Sie kann mit beanstalkd, MySQL/MariaDB, SQLite und PostgreSQL verwendet werden. ## Session -Sitzungen sind für APIs nicht wirklich nützlich, aber beim Aufbau einer Web-Anwendung können Sitzungen entscheidend für die Aufrechterhaltung von Zuständen und Anmeldeinformationen sein. +Sitzungen sind für APIs nicht wirklich nützlich, aber beim Aufbau einer Web-Anwendung können Sitzungen entscheidend für die Aufrechterhaltung des Zustands und Login-Informationen sein. - offiziell [flightphp/session](/awesome-plugins/session) - Offizielle Flight Session-Bibliothek. Dies ist eine einfache Session-Bibliothek, die verwendet werden kann, um Session-Daten zu speichern und abzurufen. Sie verwendet die integrierte Session-Behandlung von PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (nicht-blockierend, Flash, Segment, Session-Verschlüsselung). Verwendet PHP open_ssl für optionale Verschlüsselung/Entschlüsselung von Session-Daten. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session-Manager (nicht-blockierend, Flash, Segment, Session-Verschlüsselung). Verwendet PHP open_ssl für optionale Verschlüsselung/Entschlüsselung von Session-Daten. -## Vorlagen +## Templating -Vorlagen sind der Kern jeder Web-Anwendung mit einer Benutzeroberfläche. Es gibt eine Reihe von Vorlagen-Engines, die mit Flight verwendet werden können. +Templating ist der Kern jeder Web-Anwendung mit einer Benutzeroberfläche. Es gibt eine Reihe von Templating-Engines, die mit Flight verwendet werden können. -- veraltet [flightphp/core View](/learn#views) - Dies ist ein sehr grundlegendes Vorlagen-Engine, das zum Kern gehört. Es wird nicht empfohlen, es zu verwenden, wenn Ihr Projekt mehr als ein paar Seiten hat. -- [latte/latte](/awesome-plugins/latte) - Latte ist eine vollständige Vorlagen-Engine, die sehr einfach zu verwenden ist und sich näher an der PHP-Syntax anfühlt als Twig oder Smarty. Sie ist auch sehr einfach zu erweitern und eigene Filter und Funktionen hinzuzufügen. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate ist eine leistungsstarke PHP-Vorlagen-Engine mit Asset-Kompilierung, Vorlagen-Vererbung und Variablenverarbeitung. Features automatische CSS/JS-Minifizierung, Caching, Base64-Kodierung und optionale Integration des Flight PHP-Frameworks. +- deprecated [flightphp/core View](/learn#views) - Dies ist eine sehr grundlegende Templating-Engine, die zum Kern gehört. Es wird nicht empfohlen, sie zu verwenden, wenn Ihr Projekt mehr als ein paar Seiten hat. +- [latte/latte](/awesome-plugins/latte) - Latte ist eine vollständige Templating-Engine, die sehr einfach zu bedienen ist und sich näher an der PHP-Syntax anfühlt als Twig oder Smarty. Sie ist auch sehr einfach zu erweitern und eigene Filter und Funktionen hinzuzufügen. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate ist eine leistungsstarke PHP-Template-Engine mit Asset-Kompilierung, Template-Vererbung und Variablenverarbeitung. Bietet automatische CSS/JS-Minifizierung, Caching, Base64-Codierung und optionale Integration mit dem Flight PHP-Framework. -## WordPress-Integration +## WordPress Integration -Möchten Sie Flight in Ihrem WordPress-Projekt verwenden? Es gibt ein handliches Plugin dafür! +Möchten Sie Flight in Ihrem WordPress-Projekt verwenden? Es gibt ein praktisches Plugin dafür! - [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Dieses WordPress-Plugin ermöglicht es Ihnen, Flight direkt neben WordPress auszuführen. Es ist perfekt, um benutzerdefinierte APIs, Microservices oder sogar vollständige Apps zu Ihrer WordPress-Site mit dem Flight-Framework hinzuzufügen. Super nützlich, wenn Sie das Beste aus beiden Welten wollen! -## Beitrag +## Contributing Haben Sie ein Plugin, das Sie teilen möchten? Reichen Sie einen Pull Request ein, um es zur Liste hinzuzufügen! \ No newline at end of file diff --git a/content/v3/de/awesome-plugins/comment_template.md b/content/v3/de/awesome-plugins/comment_template.md index 86457b5e..04523127 100644 --- a/content/v3/de/awesome-plugins/comment_template.md +++ b/content/v3/de/awesome-plugins/comment_template.md @@ -1,6 +1,6 @@ # CommentTemplate -[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) ist ein leistungsstarkes PHP-Template-Engine mit Asset-Kompilierung, Template-Vererbung und Variablenverarbeitung. Es bietet eine einfache, aber flexible Möglichkeit, Templates zu verwalten, mit integrierter CSS/JS-Minifizierung und Caching. +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) ist ein leistungsstarker PHP-Template-Engine mit Asset-Kompilierung, Template-Vererbung und Variablenverarbeitung. Es bietet eine einfache, aber flexible Möglichkeit, Templates zu verwalten, mit integrierter CSS/JS-Minifizierung und Caching. ## Features @@ -8,7 +8,7 @@ - **Asset-Kompilierung**: Automatische CSS/JS-Minifizierung und Caching - **Variablenverarbeitung**: Template-Variablen mit Filtern und Befehlen - **Base64-Kodierung**: Inline-Assets als Data-URIs -- **Flight-Framework-Integration**: Optionale Integration mit dem Flight-PHP-Framework +- **Flight Framework Integration**: Optionale Integration mit dem Flight PHP Framework ## Installation @@ -20,7 +20,7 @@ composer require knifelemon/comment-template ## Grundlegende Konfiguration -Es gibt einige grundlegende Konfigurationsoptionen, um zu starten. Sie können mehr darüber in der [CommentTemplate-Repo](https://github.com/KnifeLemon/CommentTemplate) lesen. +Es gibt einige grundlegende Konfigurationsoptionen, um zu starten. Sie können mehr darüber in der [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate) lesen. ### Methode 1: Verwendung einer Callback-Funktion @@ -33,16 +33,16 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Wurzelverzeichnis (wo sich index.php befindet) - das Document Root Ihrer Webanwendung + // Root-Verzeichnis (wo index.php liegt) - das Dokument-Root Ihrer Web-Anwendung $engine->setPublicPath(__DIR__); - // Template-Dateiverzeichnis - unterstützt relative und absolute Pfade - $engine->setSkinPath('views'); // Relativ zum öffentlichen Pfad + // Verzeichnis für Template-Dateien - unterstützt sowohl relative als auch absolute Pfade + $engine->setSkinPath('views'); // Relativ zum Public Path - // Wo kompilierte Assets gespeichert werden - unterstützt relative und absolute Pfade - $engine->setAssetPath('assets'); // Relativ zum öffentlichen Pfad + // Wo kompilierte Assets gespeichert werden - unterstützt sowohl relative als auch absolute Pfade + $engine->setAssetPath('assets'); // Relativ zum Public Path - // Template-Dateierweiterung + // Dateierweiterung für Templates $engine->setFileExtension('.php'); }); @@ -63,10 +63,10 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__, // publicPath - Wurzelverzeichnis (wo index.php ist) + __DIR__, // publicPath - Root-Verzeichnis (wo index.php liegt) 'views', // skinPath - Template-Pfad (unterstützt relativ/absolut) - 'assets', // assetPath - kompilierter Asset-Pfad (unterstützt relativ/absolut) - '.php' // fileExtension - Template-Dateierweiterung + 'assets', // assetPath - Pfad für kompilierte Assets (unterstützt relativ/absolut) + '.php' // fileExtension - Dateierweiterung für Templates ]); $app->map('render', function(string $template, array $data) use ($app): void { @@ -74,35 +74,35 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` -## Pfad-Konfiguration +## Pfadkonfiguration -CommentTemplate bietet intelligente Pfad-Behandlung für relative und absolute Pfade: +CommentTemplate bietet intelligente Pfadbehandlung für sowohl relative als auch absolute Pfade: -### Öffentlicher Pfad +### Public Path -Der **Öffentliche Pfad** ist das Wurzelverzeichnis Ihrer Webanwendung, typischerweise wo sich `index.php` befindet. Dies ist das Document Root, von dem Webserver Dateien bereitstellen. +Der **Public Path** ist das Root-Verzeichnis Ihrer Web-Anwendung, typischerweise wo `index.php` liegt. Dies ist das Dokument-Root, aus dem Webserver Dateien ausliefern. ```php -// Beispiel: wenn Ihre index.php bei /var/www/html/myapp/index.php liegt -$template->setPublicPath('/var/www/html/myapp'); // Wurzelverzeichnis +// Beispiel: Wenn Ihre index.php bei /var/www/html/myapp/index.php liegt +$template->setPublicPath('/var/www/html/myapp'); // Root-Verzeichnis -// Windows-Beispiel: wenn Ihre index.php bei C:\xampp\htdocs\myapp\index.php liegt +// Windows-Beispiel: Wenn Ihre index.php bei C:\xampp\htdocs\myapp\index.php liegt $template->setPublicPath('C:\\xampp\\htdocs\\myapp'); ``` -### Template-Pfad-Konfiguration +### Konfiguration des Templates-Pfads -Template-Pfad unterstützt sowohl relative als auch absolute Pfade: +Der Templates-Pfad unterstützt sowohl relative als auch absolute Pfade: ```php $template = new Engine(); -$template->setPublicPath('/var/www/html/myapp'); // Wurzelverzeichnis (wo index.php ist) +$template->setPublicPath('/var/www/html/myapp'); // Root-Verzeichnis (wo index.php liegt) -// Relative Pfade - automatisch mit öffentlichem Pfad kombiniert +// Relative Pfade - werden automatisch mit dem Public Path kombiniert $template->setSkinPath('views'); // → /var/www/html/myapp/views/ $template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ -// Absolute Pfade - wie sie sind verwendet (Unix/Linux) +// Absolute Pfade - werden so verwendet (Unix/Linux) $template->setSkinPath('/var/www/templates'); // → /var/www/templates/ $template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ @@ -114,16 +114,16 @@ $template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ $template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ ``` -### Asset-Pfad-Konfiguration +### Konfiguration des Asset-Pfads -Asset-Pfad unterstützt auch sowohl relative als auch absolute Pfade: +Der Asset-Pfad unterstützt ebenfalls sowohl relative als auch absolute Pfade: ```php -// Relative Pfade - automatisch mit öffentlichem Pfad kombiniert +// Relative Pfade - werden automatisch mit dem Public Path kombiniert $template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ $template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ -// Absolute Pfade - wie sie sind verwendet (Unix/Linux) +// Absolute Pfade - werden so verwendet (Unix/Linux) $template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ $template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ @@ -135,21 +135,21 @@ $template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ ``` -**Intelligente Pfad-Erkennung:** +**Intelligente Pfaderkennung:** - **Relative Pfade**: Keine führenden Trennzeichen (`/`, `\`) oder Laufwerksbuchstaben -- **Unix Absolut**: Beginnt mit `/` (z.B. `/var/www/assets`) -- **Windows Absolut**: Beginnt mit Laufwerksbuchstabe (z.B. `C:\www`, `D:/assets`) -- **UNC-Pfade**: Beginnt mit `\\` (z.B. `\\server\share`) +- **Unix Absolut**: Beginnt mit `/` (z. B. `/var/www/assets`) +- **Windows Absolut**: Beginnt mit Laufwerksbuchstabe (z. B. `C:\www`, `D:/assets`) +- **UNC-Pfade**: Beginnt mit `\\` (z. B. `\\server\share`) -**Wie es funktioniert:** +**So funktioniert es:** -- Alle Pfade werden automatisch basierend auf dem Typ aufgelöst (relativ vs absolut) -- Relative Pfade werden mit dem öffentlichen Pfad kombiniert -- `@css` und `@js` erstellen minifizierte Dateien in: `{resolvedAssetPath}/css/` oder `{resolvedAssetPath}/js/` +- Alle Pfade werden automatisch basierend auf dem Typ (relativ vs. absolut) aufgelöst +- Relative Pfade werden mit dem Public Path kombiniert +- `@css` und `@js` erstellen minimierte Dateien in: `{resolvedAssetPath}/css/` oder `{resolvedAssetPath}/js/` - `@asset` kopiert einzelne Dateien nach: `{resolvedAssetPath}/{relativePath}` - `@assetDir` kopiert Verzeichnisse nach: `{resolvedAssetPath}/{relativePath}` -- Intelligente Zwischenspeicherung: Dateien werden nur kopiert, wenn die Quelle neuer ist als das Ziel +- Intelligentes Caching: Dateien werden nur kopiert, wenn die Quelle neuer als das Ziel ist ## Template-Direktiven @@ -243,8 +243,8 @@ const imageData = ''; #### Asset-Kopieren ```html - - + + ``` **Beispiel:** ```html @@ -252,7 +252,7 @@ const imageData = ''; Hero Banner Download Brochure - + ``` @@ -301,29 +301,29 @@ const imageData = ''; #### Variablenbefehle ```html {$title|default=Default Title} -{$name|concat= (Admin)} +{$name|concat= (Admin)} ``` -#### Mehrere Filter verketten +#### Variablenbefehle ```html -{$content|striptag|trim|escape} +{$content|striptag|trim|escape} ``` ### Kommentare -Template-Kommentare werden vollständig aus der Ausgabe entfernt und erscheinen nicht im finalen HTML: +Template-Kommentare werden vollständig aus dem Output entfernt und erscheinen nicht im finalen HTML: ```html {* Dies ist ein einzeiliger Template-Kommentar *} {* - Dies ist ein mehrzeiliger + Dies ist ein mehrzeiliger Template-Kommentar - über mehrere Zeilen + der mehrere Zeilen umfasst *}

          {$title}

          -{* Debug-Kommentar: Prüfen ob title-Variable funktioniert *} +{* Debug-Kommentar: Überprüfen, ob die Title-Variable funktioniert *}

          {$content}

          ``` diff --git a/content/v3/de/awesome-plugins/runway.md b/content/v3/de/awesome-plugins/runway.md index 38d9fcc4..e3dca270 100644 --- a/content/v3/de/awesome-plugins/runway.md +++ b/content/v3/de/awesome-plugins/runway.md @@ -1,53 +1,53 @@ -# Startbahn +# Runway -Startbahn ist eine CLI-Anwendung, die Ihnen dabei hilft, Ihre Flight-Anwendungen zu verwalten. Sie kann Controller generieren, alle Routen anzeigen und mehr. Sie basiert auf der ausgezeichneten [adhocore/php-cli](https://github.com/adhocore/php-cli) Bibliothek. +Runway ist eine CLI-Anwendung, die Ihnen hilft, Ihre Flight-Anwendungen zu verwalten. Sie kann Controller generieren, alle Routen anzeigen und mehr. Sie basiert auf der hervorragenden [adhocore/php-cli](https://github.com/adhocore/php-cli)-Bibliothek. Klicken Sie [hier](https://github.com/flightphp/runway), um den Code anzusehen. ## Installation -Mit Composer installieren. +Installieren Sie mit Composer. ```bash -composer require flightphp/startbahn +composer require flightphp/runway ``` -## Grundkonfiguration +## Grundlegende Konfiguration -Das erste Mal, wenn Sie Startbahn ausführen, wird es Sie durch einen Einrichtungsprozess führen und eine .runway.json-Konfigurationsdatei im Stammverzeichnis Ihres Projekts erstellen. Diese Datei wird einige notwendige Konfigurationen enthalten, damit Startbahn ordnungsgemäß funktioniert. +Beim ersten Ausführen von Runway durchläuft es einen Einrichtungsprozess und erstellt eine `.runway.json`-Konfigurationsdatei im Stammverzeichnis Ihres Projekts. Diese Datei enthält einige notwendige Konfigurationen, damit Runway ordnungsgemäß funktioniert. ## Verwendung -Startbahn hat mehrere Befehle, die Sie verwenden können, um Ihre Flight-Anwendung zu verwalten. Es gibt zwei einfache Möglichkeiten, Startbahn zu verwenden. +Runway verfügt über eine Reihe von Befehlen, die Sie verwenden können, um Ihre Flight-Anwendung zu verwalten. Es gibt zwei einfache Wege, Runway zu verwenden. -1. Wenn Sie das Grundgerüstprojekt verwenden, können Sie `php startbahn [Befehl]` im Stammverzeichnis Ihres Projekts ausführen. -1. Wenn Sie Startbahn als über Composer installiertes Paket verwenden, können Sie `vendor/bin/startbahn [Befehl]` im Stammverzeichnis Ihres Projekts ausführen. +1. Wenn Sie das Skeleton-Projekt verwenden, können Sie `php runway [command]` vom Stammverzeichnis Ihres Projekts ausführen. +1. Wenn Sie Runway als über Composer installiertes Paket verwenden, können Sie `vendor/bin/runway [command]` vom Stammverzeichnis Ihres Projekts ausführen. Für jeden Befehl können Sie die `--help`-Flagge übergeben, um weitere Informationen zur Verwendung des Befehls zu erhalten. ```bash -php startbahn routes --help +php runway routes --help ``` -Hier sind ein paar Beispiele: +Hier sind einige Beispiele: ### Einen Controller generieren -Basierend auf der Konfiguration in Ihrer .runway.json-Datei wird der Standardort einen Controller für Sie im `app/controllers/` Verzeichnis generieren. +Basierend auf der Konfiguration in Ihrer `.runway.json`-Datei wird der Standardort einen Controller für Sie im `app/controllers/`-Verzeichnis generieren. ```bash -php startbahn make:controller MeinController +php runway make:controller MyController ``` -### Einen Aktiven Datensatz-Model generieren +### Ein Active Record-Modell generieren -Basierend auf der Konfiguration in Ihrer .runway.json-Datei wird der Standardort einen Controller für Sie im `app/records/` Verzeichnis generieren. +Basierend auf der Konfiguration in Ihrer `.runway.json`-Datei wird der Standardort einen Controller für Sie im `app/records/`-Verzeichnis generieren. ```bash -php startbahn make:record benutzer +php runway make:record users ``` -Wenn Sie zum Beispiel die `benutzer` Tabelle mit dem folgenden Schema haben: `id`, `name`, `email`, `created_at`, `updated_at`, wird eine Datei ähnlich der folgenden in der `app/records/BenutzerDatensatz.php` erstellt: +Falls Sie beispielsweise die `users`-Tabelle mit dem folgenden Schema haben: `id`, `name`, `email`, `created_at`, `updated_at`, wird eine Datei ähnlich der folgenden in der Datei `app/records/UserRecord.php` erstellt: ```php $konfig JSON-Konfiguration aus .runway-config.json + * @param array $config JSON-Konfiguration aus .runway-config.json */ - public function __construct(array $konfig) + public function __construct(array $config) { - parent::__construct('make:beispiel', 'Erstellt ein Beispiel für die Dokumentation', $konfig); - $this->argument('', 'Der Name des lustigen Gifs'); + parent::__construct('make:example', 'Erstellt ein Beispiel für die Dokumentation', $config); + $this->argument('', 'Der Name des lustigen GIFs'); } /** * Führt die Funktion aus * - * @return Leer + * @return void */ - public function execute(string $controller) + public function execute() { $io = $this->app()->io(); - $io->info('Beispiel wird erstellt...'); + $io->info('Erstelle Beispiel...'); - // Hier etwas machen + // Etwas hier tun $io->ok('Beispiel erstellt!'); } } ``` -Siehe die [adhocore/php-cli Dokumentation](https://github.com/adhocore/php-cli) für weitere Informationen, wie Sie Ihre eigenen benutzerdefinierten Befehle in Ihre Flight-Anwendung integrieren können! \ No newline at end of file +Siehe die [adhocore/php-cli-Dokumentation](https://github.com/adhocore/php-cli) für weitere Informationen darüber, wie Sie eigene benutzerdefinierte Befehle in Ihre Flight-Anwendung einbauen! + +### Konfiguration + +Wenn Sie die Konfiguration für Runway anpassen müssen, können Sie eine `.runway-config.json`-Datei im Stammverzeichnis Ihres Projekts erstellen. Nachfolgend sind einige zusätzliche Konfigurationen aufgeführt, die Sie setzen können: + +```js +{ + + // Hier befindet sich das Verzeichnis Ihrer Anwendung + "app_root": "app/", + + // Dies ist das Verzeichnis, in dem sich Ihre root index-Datei befindet + "index_root": "public/", + + // Dies sind die Pfade zu den Roots anderer Projekte + "root_paths": [ + "/home/user/different-project", + "/var/www/another-project" + ], + + // Base-Pfade müssen wahrscheinlich nicht konfiguriert werden, aber es ist hier, falls Sie es wollen + "base_paths": { + "/includes/libs/vendor", // falls Sie einen wirklich einzigartigen Pfad für Ihr Vendor-Verzeichnis oder Ähnliches haben + }, + + // Final-Pfade sind Orte innerhalb eines Projekts, um nach den Befehlsdateien zu suchen + "final_paths": { + "src/diff-path/commands", + "app/module/admin/commands", + }, + + // Wenn Sie einfach den vollständigen Pfad hinzufügen möchten, tun Sie es ruhig (absolut oder relativ zum Projekt-Root) + "paths": [ + "/home/user/different-project/src/diff-path/commands", + "/var/www/another-project/app/module/admin/commands", + "app/my-unique-commands" + ] +} +``` \ No newline at end of file diff --git a/content/v3/de/examples.md b/content/v3/de/examples.md index 00f1b014..a146c8fd 100644 --- a/content/v3/de/examples.md +++ b/content/v3/de/examples.md @@ -1,11 +1,11 @@ # Brauchen Sie einen schnellen Einstieg? -Sie haben zwei Optionen, um mit einem neuen Flight-Projekt zu beginnen: +Sie haben zwei Optionen, um mit einem neuen Flight-Projekt zu starten: - [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Ein umfassenderes Beispiel mit Controllern und Views. - [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Eine einzelne Datei, die alles enthält, was Sie benötigen, um Ihre App in einer einzigen einfachen Datei auszuführen. -Von der Community beigetragene Beispiele: +Community-beigetragene Beispiele: - [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP mit Laravel-Verzeichnissen, mit PHP-Tools + GH Actions - [fleact](https://github.com/flightphp/fleact) - Ein FlightPHP-Starter-Kit mit ReactJS-Integration. @@ -14,13 +14,14 @@ Von der Community beigetragene Beispiele: ## Brauchen Sie etwas Inspiration? -Obwohl diese nicht offiziell von dem Flight-Team gesponsert werden, könnten sie Ihnen Ideen geben, wie Sie Ihre eigenen mit Flight gebauten Projekte strukturieren! +Obwohl diese nicht offiziell vom Flight-Team gesponsert werden, könnten sie Ihnen Ideen geben, wie Sie Ihre eigenen Projekte mit Flight strukturieren! -- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify ist eine Single-Page-App, die Veranstaltungsorganisatoren mit Teilnehmern verbindet. Gebaut mit PHP (FlightPHP), JavaScript und MySQL, bietet es JWT-Authentifizierung, Veranstaltungsmanagement und RESTful-API-Dokumentation mit OpenAPI. -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental ist eine Single-Page, mobilfreundliche Autovermietungs-Web-Anwendung, gebaut mit PHP (FlightPHP), JavaScript und MySQL. Es unterstützt Benutzerregistrierung, Durchsuchen und Buchen von Autos, während Admins Autos, Benutzer und Buchungen verwalten können. Die App verfügt über eine REST-API, JWT-Authentifizierung und ein responsives Design für ein modernes Vermietungserlebnis. +- [ASC REST API Spell Checker](https://github.com/AlMosahih-ASC/asc-api-sample) - Eine leichte REST-API für die arabische Rechtschreibprüfung, aufgebaut mit FlightPHP und ArPHP-Bibliothek. Diese API bietet Funktionen zur arabischen Text-Rechtschreibprüfung, einschließlich Erkennung von Fehlern und Korrekturvorschlägen. +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify ist eine Single-Page-App, die Veranstaltungsorganisatoren mit Teilnehmern verbindet. Aufgebaut mit PHP (FlightPHP), JavaScript und MySQL, verfügt sie über JWT-Authentifizierung, Veranstaltungsmanagement und RESTful-API-Dokumentation mit OpenAPI. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental ist eine Single-Page, mobilfreundliche Autovermietungs-Web-Anwendung, aufgebaut mit PHP (FlightPHP), JavaScript und MySQL. Sie unterstützt Benutzerregistrierung, Durchsuchen und Buchen von Autos, während Admins Autos, Benutzer und Buchungen verwalten können. Die App verfügt über eine REST-API, JWT-Authentifizierung und ein responsives Design für ein modernes Miet-Erlebnis. - [Decay](https://github.com/boxybird/decay) - Flight v3 mit HTMX und SleekDB, alles über Zombies! ([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 mit Middleware, Controllern, Active Record und Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Ein einfaches CRUD-API-Projekt mit dem Flight-Framework, das eine grundlegende Struktur für neue Benutzer bietet, um schnell eine PHP-Anwendung mit CRUD-Operationen und Datenbankverbindung einzurichten. Das Projekt demonstriert, wie man Flight für die RESTful-API-Entwicklung verwendet, was es zu einem idealen Lernwerkzeug für Anfänger und einem nützlichen Starter-Kit für erfahrene Entwickler macht. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Ein einfaches CRUD-API-Projekt mit dem Flight-Framework, das eine grundlegende Struktur für neue Benutzer bietet, um schnell eine PHP-Anwendung mit CRUD-Operationen und Datenbankverbindung einzurichten. Das Projekt demonstriert, wie man Flight für die RESTful-API-Entwicklung verwendet, und ist somit ein ideales Lernwerkzeug für Anfänger und ein nützliches Starter-Kit für erfahrene Entwickler. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -31,7 +32,7 @@ Obwohl diese nicht offiziell von dem Flight-Team gesponsert werden, könnten sie - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Ein produktionsreifes Authentifizierungs-Framework, das Ihnen Wochen der Entwicklung erspart. Es bietet enterprise-grade Sicherheit: 2FA/TOTP, LDAP-Integration, Azure SSO, intelligente Rate-Limiting, Session-Fingerprinting, Brute-Force-Schutz, Security-Analytics-Dashboard, umfassende Audit-Logging und granulare rollenbasierte Zugriffssteuerung. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Ein produktionsreifes Authentifizierungs-Framework, das Ihnen Wochen der Entwicklung erspart. Features enterprise-grade Sicherheit: 2FA/TOTP, LDAP-Integration, Azure SSO, intelligente Ratenbegrenzung, Sitzungsfingerabdruck, Schutz vor Brute-Force-Angriffen, Sicherheits-Analytics-Dashboard, umfassende Audit-Protokollierung und granulare rollenbasierte Zugriffssteuerung. ## Möchten Sie Ihr eigenes Beispiel teilen? diff --git a/content/v3/es/awesome-plugins/active_record.md b/content/v3/es/awesome-plugins/active_record.md index fa9d90b0..ad3ece11 100644 --- a/content/v3/es/awesome-plugins/active_record.md +++ b/content/v3/es/awesome-plugins/active_record.md @@ -1,6 +1,6 @@ # Flight Active Record -Un registro activo es el mapeo de una entidad de base de datos a un objeto PHP. Hablando claramente, si tienes una tabla de usuarios en tu base de datos, puedes "traducir" una fila en esa tabla a una clase `User` y un objeto `$user` en tu base de código. Consulta [ejemplo básico](#basic-example). +Un active record es un mapeo de una entidad de base de datos a un objeto PHP. En términos simples, si tienes una tabla de usuarios en tu base de datos, puedes "traducir" una fila en esa tabla a una clase `User` y un objeto `$user` en tu código. Ver [ejemplo básico](#basic-example). Haz clic [aquí](https://github.com/flightphp/active-record) para el repositorio en GitHub. @@ -39,11 +39,11 @@ class User extends flight\ActiveRecord { } ``` -¡Ahora mira cómo sucede la magia! +¡Ahora observa la magia suceder! ```php // para sqlite -$database_connection = new PDO('sqlite:test.db'); // esto es solo un ejemplo, probablemente uses una conexión a base de datos real +$database_connection = new PDO('sqlite:test.db'); // esto es solo un ejemplo, probablemente usarías una conexión de base de datos real // para mysql $database_connection = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'username', 'password'); @@ -64,15 +64,15 @@ echo $user->id; // 1 $user->name = 'Joseph Mamma'; $user->password = password_hash('some cool password again!!!'); $user->insert(); -// ¡no se puede usar $user->save() aquí o pensará que es una actualización! +// ¡no puedes usar $user->save() aquí o pensará que es una actualización! echo $user->id; // 2 ``` -¡Y así de fácil fue agregar un nuevo usuario! Ahora que hay una fila de usuario en la base de datos, ¿cómo la extraes? +¡Y fue tan fácil agregar un nuevo usuario! Ahora que hay una fila de usuario en la base de datos, ¿cómo la extraes? ```php -$user->find(1); // encuentra id = 1 en la base de datos y lo retorna. +$user->find(1); // busca id = 1 en la base de datos y la devuelve. echo $user->name; // 'Bobby Tables' ``` @@ -82,13 +82,13 @@ echo $user->name; // 'Bobby Tables' $users = $user->findAll(); ``` -¿Qué tal con una cierta condición? +¿Qué pasa con una condición específica? ```php $users = $user->like('name', '%mamma%')->findAll(); ``` -¿Ves cuánto puede ser divertido esto? ¡Instalémoslo y comencemos! +¿Ves lo divertido que es? ¡Instálalo y comencemos! ## Instalación @@ -100,21 +100,21 @@ composer require flightphp/active-record ## Uso -Esto puede ser utilizado como una biblioteca independiente o junto con el Flight PHP Framework. Depende completamente de ti. +Esto se puede usar como una biblioteca independiente o con el Flight PHP Framework. Completamente a tu elección. ### Independiente Solo asegúrate de pasar una conexión PDO al constructor. ```php -$pdo_connection = new PDO('sqlite:test.db'); // esto es solo un ejemplo, probablemente uses una conexión a base de datos real +$pdo_connection = new PDO('sqlite:test.db'); // esto es solo un ejemplo, probablemente usarías una conexión de base de datos real $User = new User($pdo_connection); ``` -> ¿No quieres siempre establecer tu conexión a la base de datos en el constructor? Consulta [Gestión de Conexiones a la Base de Datos](#database-connection-management) para más ideas. +> ¿No quieres configurar siempre tu conexión de base de datos en el constructor? Ver [Gestión de Conexión de Base de Datos](#database-connection-management) para otras ideas! ### Registrar como un método en Flight -Si estás utilizando el Flight PHP Framework, puedes registrar la clase ActiveRecord como un servicio, pero honestamente no tienes que hacerlo. +Si estás usando el Flight PHP Framework, puedes registrar la clase ActiveRecord como un servicio, pero honestamente no tienes que hacerlo. ```php Flight::register('user', 'User', [ $pdo_connection ]); @@ -126,7 +126,7 @@ Flight::user()->find(1); ## Métodos `runway` -[runway](/awesome-plugins/runway) es una herramienta CLI para Flight que tiene un comando personalizado para esta biblioteca. +[runway](/awesome-plugins/runway) es una herramienta CLI para Flight que tiene un comando personalizado para esta biblioteca. ```bash # Uso @@ -158,7 +158,7 @@ namespace app\records; class UserRecord extends \flight\ActiveRecord { /** - * @var array $relations Establece las relaciones para el modelo + * @var array $relations Configura las relaciones para el modelo * https://docs.flightphp.com/awesome-plugins/active-record#relationships */ protected array $relations = [ @@ -180,12 +180,12 @@ class UserRecord extends \flight\ActiveRecord #### `find($id = null) : boolean|ActiveRecord` -Encuentra un registro y asígnalo al objeto actual. Si pasas un `$id` de algún tipo, realizará una búsqueda en la clave primaria con ese valor. Si no se pasa nada, simplemente encontrará el primer registro en la tabla. +Encuentra un registro y lo asigna al objeto actual. Si pasas un `$id` de algún tipo, realizará una búsqueda en la clave primaria con ese valor. Si no se pasa nada, simplemente encontrará el primer registro en la tabla. -Además, puedes pasarlo otros métodos auxiliares para consultar tu tabla. +Además, puedes pasarle otros métodos auxiliares para consultar tu tabla. ```php -// encontrar un registro con algunas condiciones previamente +// encontrar un registro con algunas condiciones previas $user->notNull('password')->orderBy('id DESC')->find(); // encontrar un registro por un id específico @@ -203,7 +203,7 @@ $user->findAll(); #### `isHydrated(): boolean` (v0.4.0) -Retorna `true` si el registro actual ha sido hidratado (obtenido de la base de datos). +Devuelve `true` si el registro actual ha sido hidratado (recuperado de la base de datos). ```php $user->find(1); @@ -224,7 +224,7 @@ $user->insert(); ##### Claves Primarias Basadas en Texto -Si tienes una clave primaria basada en texto (como un UUID), puedes establecer el valor de la clave primaria antes de insertar de dos maneras. +Si tienes una clave primaria basada en texto (como un UUID), puedes establecer el valor de la clave primaria antes de insertar de una de dos maneras. ```php $user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]); @@ -234,24 +234,24 @@ $user->password = md5('demo'); $user->insert(); // o $user->save(); ``` -o puedes hacer que la clave primaria se genere automáticamente para ti a través de eventos. +o puedes tener la clave primaria generada automáticamente para ti a través de eventos. ```php class User extends flight\ActiveRecord { public function __construct($database_connection) { parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]); - // también puedes establecer la primaryKey de esta manera en lugar de la matriz anterior. + // también puedes establecer la primaryKey de esta manera en lugar del array anterior. $this->primaryKey = 'uuid'; } protected function beforeInsert(self $self) { - $self->uuid = uniqid(); // o como sea necesario para generar tus ids únicos + $self->uuid = uniqid(); // o como necesites generar tus ids únicos } } ``` -Si no estableces la clave primaria antes de insertar, se establecerá en `rowid` y la base de datos la generará para ti, pero no persistirá porque ese campo puede no existir en tu tabla. Por eso se recomienda utilizar el evento para manejar esto automáticamente. +Si no estableces la clave primaria antes de insertar, se establecerá en `rowid` y la base de datos la generará para ti, pero no persistirá porque ese campo puede no existir en tu tabla. Por eso se recomienda usar el evento para manejar esto automáticamente. #### `update(): boolean|ActiveRecord` @@ -265,7 +265,7 @@ $user->update(); #### `save(): boolean|ActiveRecord` -Inserta o actualiza el registro actual en la base de datos. Si el registro tiene un id, actualizará, de lo contrario, insertará. +Inserta o actualiza el registro actual en la base de datos. Si el registro tiene un id, actualizará, de lo contrario insertará. ```php $user = new User($pdo_connection); @@ -274,7 +274,7 @@ $user->password = md5('demo'); $user->save(); ``` -**Nota:** Si tienes relaciones definidas en la clase, también se guardarán recursivamente esas relaciones si han sido definidas, instanciadas y tienen datos modificados para actualizar. (v0.4.0 y superiores) +**Nota:** Si tienes relaciones definidas en la clase, también guardará recursivamente esas relaciones si han sido definidas, instanciadas y tienen datos sucios para actualizar. (v0.4.0 y superior) #### `delete(): boolean` @@ -293,23 +293,23 @@ $user->like('name', 'Bob%')->delete(); #### `dirty(array $dirty = []): ActiveRecord` -Los datos "sucios" se refieren a los datos que han sido cambiados en un registro. +Los datos sucios se refieren a los datos que han cambiado en un registro. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); -// nada está "sucio" hasta este punto. +// nada es "sucio" hasta este punto. -$user->email = 'test@example.com'; // ahora el email se considera "sucio" ya que ha cambiado. +$user->email = 'test@example.com'; // ahora email se considera "sucio" ya que ha cambiado. $user->update(); -// ahora no hay datos sucios porque han sido actualizados y persistidos en la base de datos +// ahora no hay datos sucios porque se han actualizado y persistido en la base de datos -$user->password = password_hash('newpassword'); // ahora esto está sucio +$user->password = password_hash()'newpassword'); // ahora esto es sucio $user->dirty(); // pasar nada limpiará todas las entradas sucias. -$user->update(); // no se actualizará nada porque nada fue capturado como sucio. +$user->update(); // nada se actualizará porque nada fue capturado como sucio. $user->dirty([ 'name' => 'something', 'password' => password_hash('a different password') ]); -$user->update(); // tanto el nombre como la contraseña son actualizados. +$user->update(); // tanto name como password se actualizan. ``` #### `copyFrom(array $data): ActiveRecord` (v0.4.0) @@ -318,12 +318,12 @@ Este es un alias para el método `dirty()`. Es un poco más claro lo que estás ```php $user->copyFrom([ 'name' => 'something', 'password' => password_hash('a different password') ]); -$user->update(); // tanto el nombre como la contraseña son actualizados. +$user->update(); // tanto name como password se actualizan. ``` #### `isDirty(): boolean` (v0.4.0) -Retorna `true` si el registro actual ha sido cambiado. +Devuelve `true` si el registro actual ha sido cambiado. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); @@ -333,14 +333,14 @@ $user->isDirty(); // true #### `reset(bool $include_query_data = true): ActiveRecord` -Restablece el registro actual a su estado inicial. Esto es realmente bueno para usar en comportamientos de tipo bucle. Si pasas `true`, también restablecerá los datos de consulta que se utilizaron para encontrar el objeto actual (comportamiento predeterminado). +Reinicia el registro actual a su estado inicial. Esto es realmente bueno para usar en comportamientos de tipo bucle. Si pasas `true`, también reiniciará los datos de consulta que se usaron para encontrar el objeto actual (comportamiento predeterminado). ```php $users = $user->greaterThan('id', 0)->orderBy('id desc')->find(); $user_company = new UserCompany($pdo_connection); foreach($users as $user) { - $user_company->reset(); // empezar con un lienzo limpio + $user_company->reset(); // comenzar con una pizarra limpia $user_company->user_id = $user->id; $user_company->company_id = $some_company_id; $user_company->insert(); @@ -349,12 +349,12 @@ foreach($users as $user) { #### `getBuiltSql(): string` (v0.4.1) -Después de ejecutar un método `find()`, `findAll()`, `insert()`, `update()` o `save()`, puedes obtener el SQL que se construyó y usarlo para fines de depuración. +Después de ejecutar un método `find()`, `findAll()`, `insert()`, `update()`, o `save()` puedes obtener el SQL que se construyó y usarlo para fines de depuración. ## Métodos de Consulta SQL #### `select(string $field1 [, string $field2 ... ])` -Puedes seleccionar solo unas pocas de las columnas en una tabla si lo deseas (es más eficiente en tablas muy amplias con muchas columnas). +Puedes seleccionar solo algunas de las columnas en una tabla si lo deseas (es más performant en tablas realmente anchas con muchas columnas) ```php $user->select('id', 'name')->find(); @@ -362,7 +362,7 @@ $user->select('id', 'name')->find(); #### `from(string $table)` -¡Técnicamente puedes elegir otra tabla también! ¿Por qué no hacerlo?! +¡Técnicamente puedes elegir otra tabla también! ¿Por qué no?! ```php $user->select('id', 'name')->from('user')->find(); @@ -378,13 +378,13 @@ $user->join('contacts', 'contacts.user_id = users.id')->find(); #### `where(string $where_conditions)` -Puedes establecer algunos argumentos where personalizados (no puedes establecer parámetros en esta declaración where). +Puedes establecer algunos argumentos where personalizados (no puedes establecer params en esta declaración where) ```php $user->where('id=1 AND name="demo"')->find(); ``` -**Nota de Seguridad** - Podrías sentirte tentado a hacer algo como `$user->where("id = '{$id}' AND name = '{$name}'")->find();`. ¡Por favor, NO HAGAS ESTO! Esto es susceptible a lo que se conoce como ataques de inyección SQL. Hay muchos artículos en línea, por favor busca "sql injection attacks php" y encontrarás muchos artículos sobre este tema. La manera correcta de manejar esto con esta biblioteca es en lugar de este método `where()`, harías algo más como `$user->eq('id', $id)->eq('name', $name)->find();` Si absolutamente tienes que hacer esto, la biblioteca `PDO` tiene `$pdo->quote($var)` para escapar de ello por ti. Solo después de usar `quote()`, puedes usarlo en una declaración `where()`. +**Nota de Seguridad** - Podrías sentirte tentado a hacer algo como `$user->where("id = '{$id}' AND name = '{$name}'")->find();`. ¡POR FAVOR NO HAGAS ESTO!!! Esto es susceptible a lo que se conoce como ataques de inyección SQL. Hay muchos artículos en línea, por favor busca "sql injection attacks php" y encontrarás muchos artículos sobre este tema. La forma adecuada de manejar esto con esta biblioteca es, en lugar de este método `where()`, harías algo más como `$user->eq('id', $id)->eq('name', $name)->find();` Si absolutamente tienes que hacer esto, la biblioteca `PDO` tiene `$pdo->quote($var)` para escaparlo por ti. Solo después de usar `quote()` puedes usarlo en una declaración `where()`. #### `group(string $group_by_statement)/groupBy(string $group_by_statement)` @@ -404,7 +404,7 @@ $user->orderBy('name DESC')->find(); #### `limit(string $limit)/limit(int $offset, int $limit)` -Limita la cantidad de registros devueltos. Si se da un segundo int, se desplazará, limitará justo como en SQL. +Limita la cantidad de registros devueltos. Si se da un segundo int, será offset, limit justo como en SQL. ```php $user->orderby('name DESC')->limit(0, 10)->findAll(); @@ -498,7 +498,7 @@ $user->between('id', [1, 2])->find(); ### Condiciones OR -Es posible envolver tus condiciones en una declaración OR. Esto se realiza con el método `startWrap()` y `endWrap()` o completando el tercer parámetro de la condición después del campo y el valor. +Es posible envolver tus condiciones en una declaración OR. Esto se hace con cualquiera de los métodos `startWrap()` y `endWrap()` o rellenando el tercer parámetro de la condición después del campo y valor. ```php // Método 1 @@ -511,35 +511,35 @@ $user->eq('id', 1)->eq('name', 'demo', 'OR')->find(); ``` ## Relaciones -Puedes establecer varios tipos de relaciones utilizando esta biblioteca. Puedes establecer relaciones uno->muchos y uno->uno entre tablas. Esto requiere un poco de configuración adicional en la clase de antemano. +Puedes establecer varios tipos de relaciones usando esta biblioteca. Puedes establecer relaciones uno-a-muchos y uno-a-uno entre tablas. Esto requiere un poco de configuración extra en la clase previamente. -Establecer la matriz `$relations` no es difícil, pero adivinar la sintaxis correcta puede ser confuso. +Establecer el array `$relations` no es difícil, pero adivinar la sintaxis correcta puede ser confuso. ```php protected array $relations = [ - // puedes nombrar la clave como desees. El nombre del ActiveRecord es probablemente bueno. Ej: user, contact, client + // puedes nombrar la clave como quieras. El nombre del ActiveRecord probablemente sea bueno. Ej: user, contact, client 'user' => [ // requerido // self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO self::HAS_ONE, // este es el tipo de relación // requerido - 'Some_Class', // esta es la clase ActiveRecord "otra" a la que hará referencia + 'Some_Class', // esta es la clase ActiveRecord "otra" a la que se referenciará // requerido // dependiendo del tipo de relación - // self::HAS_ONE = la clave externa que referencia la unión - // self::HAS_MANY = la clave externa que referencia la unión + // self::HAS_ONE = la clave foránea que referencia la unión + // self::HAS_MANY = la clave foránea que referencia la unión // self::BELONGS_TO = la clave local que referencia la unión 'local_or_foreign_key', - // solo FYI, esto también se une solo a la clave primaria del "otro" modelo + // solo FYI, esto también solo se une a la clave primaria del modelo "otro" // opcional - [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // condiciones adicionales que deseas al unir la relación + [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // condiciones adicionales que quieres al unir la relación // $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5)) // opcional - 'back_reference_name' // esto es si deseas referenciar esta relación de vuelta a sí misma Ej: $user->contact->user; + 'back_reference_name' // esto es si quieres referenciar de vuelta esta relación a sí misma Ej: $user->contact->user; ]; ] ``` @@ -569,7 +569,7 @@ class Contact extends ActiveRecord{ } ``` -¡Ahora tenemos las referencias configuradas para que podamos usarlas muy fácilmente! +Ahora tenemos las referencias configuradas para poder usarlas muy fácilmente! ```php $user = new User($pdo_connection); @@ -577,7 +577,7 @@ $user = new User($pdo_connection); // encuentra el usuario más reciente. $user->notNull('id')->orderBy('id desc')->find(); -// obtener contactos usando la relación: +// obtén contactos usando la relación: foreach($user->contacts as $contact) { echo $contact->id; } @@ -588,14 +588,115 @@ $contact = new Contact(); // encuentra un contacto $contact->find(); -// obtener usuario usando la relación: +// obtén usuario usando la relación: echo $contact->user->name; // este es el nombre del usuario ``` ¿Bastante genial, eh? +### Carga Ansiosa + +#### Resumen +La carga ansiosa resuelve el problema de la consulta N+1 cargando relaciones de antemano. En lugar de ejecutar una consulta separada para las relaciones de cada registro, la carga ansiosa obtiene todos los datos relacionados en solo una consulta adicional por relación. + +> **Nota:** La carga ansiosa solo está disponible para v0.7.0 y superior. + +#### Uso Básico +Usa el método `with()` para especificar qué relaciones cargar ansiosamente: +```php +// Carga usuarios con sus contactos en 2 consultas en lugar de N+1 +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + foreach ($u->contacts as $contact) { + echo $contact->email; // ¡Sin consulta adicional! + } +} +``` + +#### Múltiples Relaciones +Carga múltiples relaciones a la vez: +```php +$users = $user->with(['contacts', 'profile', 'settings'])->findAll(); +``` + +#### Tipos de Relación + +##### HAS_MANY +```php +// Carga ansiosamente todos los contactos para cada usuario +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + // $u->contacts ya está cargado como un array + foreach ($u->contacts as $contact) { + echo $contact->email; + } +} +``` +##### HAS_ONE +```php +// Carga ansiosamente un contacto para cada usuario +$users = $user->with('contact')->findAll(); +foreach ($users as $u) { + // $u->contact ya está cargado como un objeto + echo $u->contact->email; +} +``` + +##### BELONGS_TO +```php +// Carga ansiosamente usuarios padre para todos los contactos +$contacts = $contact->with('user')->findAll(); +foreach ($contacts as $c) { + // $c->user ya está cargado + echo $c->user->name; +} +``` +##### Con find() +La carga ansiosa funciona con tanto +findAll() + como +find() +: + +```php +$user = $user->with('contacts')->find(1); +// Usuario y todos sus contactos cargados en 2 consultas +``` +#### Beneficios de Rendimiento +Sin carga ansiosa (problema N+1): +```php +$users = $user->findAll(); // 1 consulta +foreach ($users as $u) { + $contacts = $u->contacts; // N consultas (una por usuario!) +} +// Total: 1 + N consultas +``` + +Con carga ansiosa: + +```php +$users = $user->with('contacts')->findAll(); // 2 consultas totales +foreach ($users as $u) { + $contacts = $u->contacts; // 0 consultas adicionales! +} +// Total: 2 consultas (1 para usuarios + 1 para todos los contactos) +``` +Para 10 usuarios, esto reduce las consultas de 11 a 2 - una reducción del 82%! + +#### Notas Importantes +- La carga ansiosa es completamente opcional - la carga perezosa aún funciona como antes +- Las relaciones ya cargadas se omiten automáticamente +- Las referencias de vuelta funcionan con carga ansiosa +- Los callbacks de relación se respetan durante la carga ansiosa + +#### Limitaciones +- La carga ansiosa anidada (ej., +with(['contacts.addresses']) +) no está soportada actualmente +- Las restricciones de carga ansiosa vía closures no están soportadas en esta versión + ## Estableciendo Datos Personalizados -A veces puedes necesitar adjuntar algo único a tu ActiveRecord, como un cálculo personalizado que podría ser más fácil simplemente adjuntar al objeto que luego se pasaría a decir un template. +A veces puedes necesitar adjuntar algo único a tu ActiveRecord como un cálculo personalizado que podría ser más fácil de adjuntar al objeto que luego se pasaría a, digamos, una plantilla. #### `setCustomData(string $field, mixed $value)` Adjuntas los datos personalizados con el método `setCustomData()`. @@ -603,7 +704,7 @@ Adjuntas los datos personalizados con el método `setCustomData()`. $user->setCustomData('page_view_count', $page_view_count); ``` -Y luego simplemente lo referencias como una propiedad normal del objeto. +Y luego simplemente lo referencias como una propiedad de objeto normal. ```php echo $user->page_view_count; @@ -611,7 +712,7 @@ echo $user->page_view_count; ## Eventos -Una característica más super increíble de esta biblioteca es sobre los eventos. Los eventos se activan en ciertos momentos basados en ciertos métodos que llamas. Son muy útiles para configurar datos automáticamente para ti. +Una característica súper genial más sobre esta biblioteca es sobre eventos. Los eventos se activan en ciertos momentos basados en ciertos métodos que llamas. Son muy muy útiles para configurar datos automáticamente para ti. #### `onConstruct(ActiveRecord $ActiveRecord, array &config)` @@ -642,7 +743,7 @@ class User extends flight\ActiveRecord { #### `beforeFind(ActiveRecord $ActiveRecord)` -Esto probablemente solo sea útil si necesitas manipular la consulta cada vez. +Esto probablemente solo es útil si necesitas una manipulación de consulta cada vez. ```php class User extends flight\ActiveRecord { @@ -653,7 +754,7 @@ class User extends flight\ActiveRecord { } protected function beforeFind(self $self) { - // siempre ejecutar id >= 0 si eso es lo que prefieres + // siempre ejecuta id >= 0 si eso es lo tuyo $self->gte('id', 0); } } @@ -661,7 +762,7 @@ class User extends flight\ActiveRecord { #### `afterFind(ActiveRecord $ActiveRecord)` -Este probablemente sea más útil si siempre necesitas ejecutar alguna lógica cada vez que se recoge este registro. ¿Necesitas desencriptar algo? ¿Necesitas ejecutar una consulta personalizada cada vez (no muy eficiente, pero bueno)? +Este probablemente es más útil si siempre necesitas ejecutar alguna lógica cada vez que se recupera este registro. ¿Necesitas descifrar algo? ¿Necesitas ejecutar una consulta de conteo personalizada cada vez (no performant pero whatever)? ```php class User extends flight\ActiveRecord { @@ -672,18 +773,18 @@ class User extends flight\ActiveRecord { } protected function afterFind(self $self) { - // desencriptando algo + // descifrando algo $self->secret = yourDecryptFunction($self->secret, $some_key); // tal vez almacenando algo personalizado como una consulta??? - $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']); + $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']; } } ``` #### `beforeFindAll(ActiveRecord $ActiveRecord)` -Esto probablemente solo sea útil si necesitas manipular la consulta cada vez. +Esto probablemente solo es útil si necesitas una manipulación de consulta cada vez. ```php class User extends flight\ActiveRecord { @@ -694,7 +795,7 @@ class User extends flight\ActiveRecord { } protected function beforeFindAll(self $self) { - // siempre ejecutar id >= 0 si eso es lo que prefieres + // siempre ejecuta id >= 0 si eso es lo tuyo $self->gte('id', 0); } } @@ -702,7 +803,7 @@ class User extends flight\ActiveRecord { #### `afterFindAll(array $results)` -Similar a `afterFind()`, pero ¡puedes hacerlo a todos los registros en su lugar! +Similar a `afterFind()` pero puedes hacerlo a todos los registros en lugar de uno! ```php class User extends flight\ActiveRecord { @@ -715,7 +816,7 @@ class User extends flight\ActiveRecord { protected function afterFindAll(array $results) { foreach($results as $self) { - // hacer algo genial como afterFind() + // haz algo genial como afterFind() } } } @@ -723,7 +824,7 @@ class User extends flight\ActiveRecord { #### `beforeInsert(ActiveRecord $ActiveRecord)` -Realmente útil si necesitas establecer algunos valores predeterminados cada vez. +Realmente útil si necesitas algunos valores predeterminados establecidos cada vez. ```php class User extends flight\ActiveRecord { @@ -734,7 +835,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // establecer algunos valores predeterminados + // establece algunos valores predeterminados sólidos if(!$self->created_date) { $self->created_date = gmdate('Y-m-d'); } @@ -748,7 +849,7 @@ class User extends flight\ActiveRecord { #### `afterInsert(ActiveRecord $ActiveRecord)` -Tal vez tengas un caso de uso para cambiar datos después de que se inserte. +¿Tal vez tienes un caso de uso para cambiar datos después de insertarlos? ```php class User extends flight\ActiveRecord { @@ -759,7 +860,7 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // tú decides + // haz lo que quieras Flight::cache()->set('most_recent_insert_id', $self->id); // o lo que sea.... } @@ -768,7 +869,7 @@ class User extends flight\ActiveRecord { #### `beforeUpdate(ActiveRecord $ActiveRecord)` -Realmente útil si necesitas establecer algunos valores predeterminados cada vez en una actualización. +Realmente útil si necesitas algunos valores predeterminados establecidos cada vez en una actualización. ```php class User extends flight\ActiveRecord { @@ -779,7 +880,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // establecer algunos valores predeterminados + // establece algunos valores predeterminados sólidos if(!$self->updated_date) { $self->updated_date = gmdate('Y-m-d'); } @@ -789,7 +890,7 @@ class User extends flight\ActiveRecord { #### `afterUpdate(ActiveRecord $ActiveRecord)` -Tal vez tengas un caso de uso para cambiar datos después de que se actualice. +¿Tal vez tienes un caso de uso para cambiar datos después de que se actualicen? ```php class User extends flight\ActiveRecord { @@ -800,7 +901,7 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // tú decides + // haz lo que quieras Flight::cache()->set('most_recently_updated_user_id', $self->id); // o lo que sea.... } @@ -809,7 +910,7 @@ class User extends flight\ActiveRecord { #### `beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)` -Esto es útil si deseas que se produzcan eventos tanto cuando se inserten como cuando se actualicen. Te ahorraré la larga explicación, pero estoy seguro de que puedes adivinar qué es. +Esto es útil si quieres que los eventos ocurran tanto en inserts como en updates. Te ahorraré la larga explicación, pero estoy seguro de que puedes adivinar qué es. ```php class User extends flight\ActiveRecord { @@ -827,7 +928,7 @@ class User extends flight\ActiveRecord { #### `beforeDelete(ActiveRecord $ActiveRecord)/afterDelete(ActiveRecord $ActiveRecord)` -¡No estoy seguro de lo que querrías hacer aquí, pero no hago juicios! ¡Adelante! +No estoy seguro de qué querrías hacer aquí, ¡pero sin juicios! ¡Adelante! ```php class User extends flight\ActiveRecord { @@ -838,14 +939,14 @@ class User extends flight\ActiveRecord { } protected function beforeDelete(self $self) { - echo 'Él fue un valiente soldado... :cry-face:'; + echo 'He was a brave soldier... :cry-face:'; } } ``` -## Gestión de Conexiones a la Base de Datos +## Gestión de Conexión de Base de Datos -Al utilizar esta biblioteca, puedes establecer la conexión a la base de datos de varias maneras. Puedes establecer la conexión en el constructor, puedes configurarla a través de una variable de configuración `$config['connection']` o puedes establecerla a través de `setDatabaseConnection()` (v0.4.1). +Cuando usas esta biblioteca, puedes establecer la conexión de base de datos de varias maneras diferentes. Puedes establecer la conexión en el constructor, puedes establecerla a través de una variable de configuración `$config['connection']` o puedes establecerla a través de `setDatabaseConnection()` (v0.4.1). ```php $pdo_connection = new PDO('sqlite:test.db'); // por ejemplo @@ -857,11 +958,11 @@ $user = new User(); $user->setDatabaseConnection($pdo_connection); ``` -Si deseas evitar establecer siempre una `$database_connection` cada vez que llamas a un registro activo, ¡hay formas de hacerlo! +Si quieres evitar siempre establecer un `$database_connection` cada vez que llamas a un active record, ¡hay formas de evitarlo! ```php // index.php o bootstrap.php -// Establecer esto como una clase registrada en Flight +// Establece esto como una clase registrada en Flight Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php @@ -874,24 +975,23 @@ class User extends flight\ActiveRecord { } } -// ¡Y ahora, no se requieren argumentos! +// ¡Y ahora, sin argumentos requeridos! $user = new User(); ``` -> **Nota:** Si planeas hacer pruebas unitarias, hacerlo de esta manera puede agregar algunos desafíos a las pruebas unitarias, pero en general debido a que puedes inyectar tu -conexión con `setDatabaseConnection()` o `$config['connection']`, no es tan malo. +> **Nota:** Si planeas hacer pruebas unitarias, hacerlo de esta manera puede agregar algunos desafíos a las pruebas unitarias, pero en general, porque puedes inyectar tu conexión con `setDatabaseConnection()` o `$config['connection']` no es tan malo. -Si necesitas refrescar la conexión a la base de datos, por ejemplo, si estás ejecutando un script CLI de larga duración y necesitas refrescar la conexión de vez en cuando, puedes restablecer la conexión con `$your_record->setDatabaseConnection($pdo_connection)`. +Si necesitas actualizar la conexión de base de datos, por ejemplo, si estás ejecutando un script CLI de larga duración y necesitas actualizar la conexión de vez en cuando, puedes reestablecer la conexión con `$your_record->setDatabaseConnection($pdo_connection)`. ## Contribuyendo -Por favor, hazlo. :D +Por favor hazlo. :D ### Configuración -Cuando contribuyas, asegúrate de ejecutar `composer test-coverage` para mantener un 100% de cobertura de pruebas (esto no es una cobertura de pruebas unitarias verdadera, más bien pruebas de integración). +Cuando contribuyas, asegúrate de ejecutar `composer test-coverage` para mantener una cobertura de pruebas del 100% (esto no es cobertura de pruebas unitarias real, más como pruebas de integración). -Además, asegúrate de ejecutar `composer beautify` y `composer phpcs` para corregir cualquier error de sintaxis. +También asegúrate de ejecutar `composer beautify` y `composer phpcs` para corregir cualquier error de linting. ## Licencia diff --git a/content/v3/es/awesome-plugins/apm.md b/content/v3/es/awesome-plugins/apm.md index 8da0326e..5362f85c 100644 --- a/content/v3/es/awesome-plugins/apm.md +++ b/content/v3/es/awesome-plugins/apm.md @@ -1,6 +1,6 @@ # Documentación de APM de FlightPHP -¡Bienvenido a FlightPHP APM—el entrenador personal de rendimiento de tu aplicación! Esta guía es tu mapa de ruta para configurar, usar y dominar el Monitoreo de Rendimiento de Aplicaciones (APM) con FlightPHP. Ya sea que estés cazando solicitudes lentas o solo quieras geekearte con gráficos de latencia, te tenemos cubierto. ¡Hagamos que tu app sea más rápida, tus usuarios más felices y tus sesiones de depuración una brisa! +¡Bienvenido a FlightPHP APM—tu entrenador personal de rendimiento para aplicaciones! Esta guía es tu mapa de ruta para configurar, usar y dominar el Monitoreo de Rendimiento de Aplicaciones (APM) con FlightPHP. Ya sea que estés cazando solicitudes lentas o solo quieras geekearte con gráficos de latencia, te cubrimos. ¡Hagamos que tu app sea más rápida, tus usuarios más felices y tus sesiones de depuración un paseo! Mira una [demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) del dashboard para el sitio de Flight Docs. @@ -8,7 +8,7 @@ Mira una [demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) del dashboar ## Por qué APM importa -Imagina esto: tu app es un restaurante concurrido. Sin una forma de rastrear cuánto tiempo tardan los pedidos o dónde se atasca la cocina, estás adivinando por qué los clientes se van gruñendo. APM es tu sous-chef—vigila cada paso, desde las solicitudes entrantes hasta las consultas de base de datos, y marca cualquier cosa que te esté ralentizando. Las páginas lentas pierden usuarios (¡los estudios dicen que el 53% rebota si un sitio tarda más de 3 segundos en cargar!), y APM te ayuda a capturar esos problemas *antes* de que duelan. Es una paz de mente proactiva—menos momentos de “¿por qué esto está roto?”, más victorias de “¡mira qué fluido corre esto!”. +Imagina esto: tu app es un restaurante concurrido. Sin una forma de rastrear cuánto tiempo tardan los pedidos o dónde se atasca la cocina, estás adivinando por qué los clientes se van gruñendo. APM es tu sous-chef—vigila cada paso, desde las solicitudes entrantes hasta las consultas de base de datos, y marca cualquier cosa que te esté ralentizando. Las páginas lentas pierden usuarios (¡los estudios dicen que el 53% rebota si un sitio tarda más de 3 segundos en cargar!), y APM te ayuda a capturar esos problemas *antes* de que duelan. Es una paz mental proactiva—menos momentos de “¿por qué esto está roto?”, más victorias de “¡mira qué suave corre esto!”. ## Instalación @@ -19,28 +19,29 @@ composer require flightphp/apm ``` Necesitarás: -- **PHP 7.4+**: Nos mantiene compatibles con distribuciones Linux LTS mientras soporta PHP moderno. +- **PHP 7.4+**: Nos mantiene compatibles con distribuciones LTS de Linux mientras soporta PHP moderno. - **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: El framework ligero que estamos impulsando. ## Bases de datos compatibles FlightPHP APM actualmente soporta las siguientes bases de datos para almacenar métricas: -- **SQLite3**: Simple, basada en archivos, y genial para desarrollo local o apps pequeñas. Opción predeterminada en la mayoría de las configuraciones. +- **SQLite3**: Simple, basada en archivos y genial para desarrollo local o apps pequeñas. Opción predeterminada en la mayoría de las configuraciones. - **MySQL/MariaDB**: Ideal para proyectos más grandes o entornos de producción donde necesitas almacenamiento robusto y escalable. -Puedes elegir el tipo de base de datos durante el paso de configuración (ver abajo). Asegúrate de que tu entorno PHP tenga las extensiones necesarias instaladas (p.ej., `pdo_sqlite` o `pdo_mysql`). +Puedes elegir el tipo de base de datos durante el paso de configuración (ver abajo). Asegúrate de que tu entorno PHP tenga las extensiones necesarias instaladas (por ejemplo, `pdo_sqlite` o `pdo_mysql`). -## Comenzando +## Primeros pasos -Aquí tienes tu guía paso a paso hacia la genialidad de APM: +Aquí tienes tu paso a paso hacia la genialidad de APM: ### 1. Registrar el APM -Coloca esto en tu `index.php` o un archivo `services.php` para comenzar el rastreo: +Inserta esto en tu `index.php` o un archivo `services.php` para comenzar el rastreo: ```php use flight\apm\logger\LoggerFactory; +use flight\database\PdoWrapper; use flight\Apm; $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); @@ -54,8 +55,8 @@ $Apm->addPdoConnection($pdo); ``` **¿Qué está pasando aquí?** -- `LoggerFactory::create()` agarra tu configuración (más sobre eso pronto) y configura un logger—SQLite por defecto. -- `Apm` es la estrella—escucha los eventos de Flight (solicitudes, rutas, errores, etc.) y recolecta métricas. +- `LoggerFactory::create()` toma tu configuración (más sobre eso pronto) y configura un logger—SQLite por defecto. +- `Apm` es la estrella—escucha los eventos de Flight (solicitudes, rutas, errores, etc.) y recopila métricas. - `bindEventsToFlightInstance($app)` lo une todo a tu app de Flight. **Consejo Pro: Muestreo** @@ -65,9 +66,9 @@ Si tu app está ocupada, registrar *cada* solicitud podría sobrecargar las cosa $Apm = new Apm($ApmLogger, 0.1); // Registra el 10% de las solicitudes ``` -Esto mantiene el rendimiento ágil mientras aún te da datos sólidos. +Esto mantiene el rendimiento ágil mientras te da datos sólidos. -### 2. Configurarlo +### 2. Configúralo Ejecuta esto para crear tu `.runway-config.json`: @@ -77,8 +78,8 @@ php vendor/bin/runway apm:init **¿Qué hace esto?** - Lanza un asistente que pregunta de dónde vienen las métricas crudas (fuente) y dónde va la data procesada (destino). -- Predeterminado es SQLite—p.ej., `sqlite:/tmp/apm_metrics.sqlite` para la fuente, otra para el destino. -- Terminarás con una config como: +- Por defecto es SQLite—por ejemplo, `sqlite:/tmp/apm_metrics.sqlite` para la fuente, otra para el destino. +- Terminarás con una configuración como: ```json { "apm": { @@ -90,10 +91,10 @@ php vendor/bin/runway apm:init } ``` -> Este proceso también preguntará si quieres ejecutar las migraciones para esta configuración. Si estás configurándolo por primera vez, la respuesta es sí. +> Este proceso también preguntará si quieres ejecutar las migraciones para esta configuración. Si es la primera vez que lo configuras, la respuesta es sí. **¿Por qué dos ubicaciones?** -Las métricas crudas se acumulan rápido (piensa en logs sin filtrar). El worker las procesa en un destino estructurado para el dashboard. ¡Mantiene las cosas ordenadas! +Las métricas crudas se acumulan rápido (piensa en logs sin filtrar). El worker las procesa en un destino estructurado para el dashboard. ¡Mantiene todo ordenado! ### 3. Procesar métricas con el Worker @@ -104,11 +105,11 @@ php vendor/bin/runway apm:worker ``` **¿Qué está haciendo?** -- Lee de tu fuente (p.ej., `apm_metrics.sqlite`). +- Lee de tu fuente (por ejemplo, `apm_metrics.sqlite`). - Procesa hasta 100 métricas (tamaño de lote predeterminado) en tu destino. - Se detiene cuando termina o si no quedan métricas. -**Mantenerlo ejecutándose** +**Manténlo ejecutándose** Para apps en vivo, querrás procesamiento continuo. Aquí tienes tus opciones: - **Modo Daemon**: @@ -122,7 +123,7 @@ Para apps en vivo, querrás procesamiento continuo. Aquí tienes tus opciones: ```bash * * * * * php /path/to/project/vendor/bin/runway apm:worker ``` - Se dispara cada minuto—perfecto para producción. + Se ejecuta cada minuto—perfecto para producción. - **Tmux/Screen**: Inicia una sesión desmontable: @@ -168,30 +169,30 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l #### Modo Producción -Para producción, podrías tener que probar unas técnicas para hacer que el dashboard funcione, ya que probablemente hay firewalls y otras medidas de seguridad en su lugar. Aquí hay unas opciones: +Para producción, podrías tener que probar algunas técnicas para que el dashboard se ejecute, ya que probablemente hay firewalls y otras medidas de seguridad en su lugar. Aquí hay algunas opciones: - **Usa un Proxy Inverso**: Configura Nginx o Apache para reenviar solicitudes al dashboard. - **Túnel SSH**: Si puedes SSH al servidor, usa `ssh -L 8080:localhost:8001 youruser@yourserver` para tunelizar el dashboard a tu máquina local. - **VPN**: Si tu servidor está detrás de una VPN, conéctate a ella y accede al dashboard directamente. - **Configura Firewall**: Abre el puerto 8001 para tu IP o la red del servidor. (o el puerto que hayas configurado). -- **Configura Apache/Nginx**: Si tienes un servidor web frente a tu aplicación, puedes configurarlo para un dominio o subdominio. Si haces esto, configurarás el document root a `/path/to/your/project/vendor/flightphp/apm/dashboard`. +- **Configura Apache/Nginx**: Si tienes un servidor web frente a tu aplicación, puedes configurarlo para un dominio o subdominio. Si haces esto, configurarás el document root a `/path/to/your/project/vendor/flightphp/apm/dashboard` #### ¿Quieres un dashboard diferente? -¡Puedes construir tu propio dashboard si quieres! Mira el directorio vendor/flightphp/apm/src/apm/presenter para ideas sobre cómo presentar la data para tu propio dashboard. +¡Puedes construir tu propio dashboard si quieres! Mira el directorio vendor/flightphp/apm/src/apm/presenter para ideas sobre cómo presentar los datos para tu propio dashboard! ## Características del Dashboard El dashboard es tu HQ de APM—aquí está lo que verás: -- **Log de Solicitudes**: Cada solicitud con timestamp, URL, código de respuesta y tiempo total. Haz clic en “Detalles” para middleware, consultas y errores. -- **Solicitudes Más Lentas**: Top 5 solicitudes que consumen tiempo (p.ej., “/api/heavy” en 2.5s). +- **Registro de Solicitudes**: Cada solicitud con timestamp, URL, código de respuesta y tiempo total. Haz clic en “Detalles” para middleware, consultas y errores. +- **Solicitudes Más Lentas**: Top 5 solicitudes que consumen tiempo (por ejemplo, “/api/heavy” en 2.5s). - **Rutas Más Lentas**: Top 5 rutas por tiempo promedio—genial para detectar patrones. -- **Tasa de Error**: Porcentaje de solicitudes que fallan (p.ej., 2.3% 500s). +- **Tasa de Error**: Porcentaje de solicitudes fallidas (por ejemplo, 2.3% de 500s). - **Percentiles de Latencia**: 95th (p95) y 99th (p99) tiempos de respuesta—conoce tus escenarios de peor caso. - **Gráfico de Código de Respuesta**: Visualiza 200s, 404s, 500s a lo largo del tiempo. -- **Consultas/Middleware Largas**: Top 5 llamadas de base de datos lentas y capas de middleware. -- **Cache Hit/Miss**: Cuánto salva tu cache el día. +- **Consultas Largas/Middleware**: Top 5 llamadas lentas a base de datos y capas de middleware. +- **Acierto/Fallo de Caché**: Cuánto salva tu caché el día. **Extras**: - Filtra por “Última Hora”, “Último Día” o “Última Semana”. @@ -202,9 +203,9 @@ Una solicitud a `/users` podría mostrar: - Tiempo Total: 150ms - Middleware: `AuthMiddleware->handle` (50ms) - Consulta: `SELECT * FROM users` (80ms) -- Cache: Hit en `user_list` (5ms) +- Caché: Acierto en `user_list` (5ms) -## Agregando Eventos Personalizados +## Agregar Eventos Personalizados Rastrea cualquier cosa—como una llamada API o proceso de pago: @@ -245,14 +246,14 @@ $Apm->addPdoConnection($pdo); ``` **Lo que Obtienes**: -- Texto de consulta (p.ej., `SELECT * FROM users WHERE id = ?`) -- Tiempo de ejecución (p.ej., 0.015s) -- Conteo de filas (p.ej., 42) +- Texto de consulta (por ejemplo, `SELECT * FROM users WHERE id = ?`) +- Tiempo de ejecución (por ejemplo, 0.015s) +- Conteo de filas (por ejemplo, 42) -**Atención**: -- **Opcional**: Sáltate esto si no necesitas rastreo de DB. +**Advertencia**: +- **Opcional**: Sáltate esto si no necesitas rastreo de BD. - **Solo PdoWrapper**: PDO core no está enganchado aún—¡mantente atento! -- **Advertencia de Rendimiento**: Registrar cada consulta en un sitio pesado en DB puede ralentizar las cosas. Usa muestreo (`$Apm = new Apm($ApmLogger, 0.1)`) para aligerar la carga. +- **Advertencia de Rendimiento**: Registrar cada consulta en un sitio pesado en BD puede ralentizar las cosas. Usa muestreo (`$Apm = new Apm($ApmLogger, 0.1)`) para aligerar la carga. **Salida de Ejemplo**: - Consulta: `SELECT name FROM products WHERE price > 100` @@ -276,11 +277,11 @@ Se ejecuta por una hora, procesando 100 métricas a la vez. ## ID de Solicitud en la App -Cada solicitud tiene un ID de solicitud único para rastreo. Puedes usar este ID en tu app para correlacionar logs y métricas. Por instancia, puedes agregar el ID de solicitud a una página de error: +Cada solicitud tiene un ID de solicitud único para rastreo. Puedes usar este ID en tu app para correlacionar logs y métricas. Por ejemplo, puedes agregar el ID de solicitud a una página de error: ```php Flight::map('error', function($message) { - // Obtén el ID de solicitud del header de respuesta X-Flight-Request-Id + // Obtén el ID de solicitud del encabezado de respuesta X-Flight-Request-Id $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); // Adicionalmente podrías obtenerlo de la variable de Flight @@ -291,18 +292,28 @@ Flight::map('error', function($message) { }); ``` -## Actualizando +## Actualización Si estás actualizando a una versión más nueva del APM, hay una posibilidad de que haya migraciones de base de datos que necesiten ejecutarse. Puedes hacerlo ejecutando el siguiente comando: ```bash php vendor/bin/runway apm:migrate ``` -Esto ejecutará cualquier migración que sea necesaria para actualizar el esquema de la base de datos a la versión más reciente. +Esto ejecutará cualquier migración necesaria para actualizar el esquema de la base de datos a la versión más reciente. **Nota:** Si tu base de datos de APM es grande en tamaño, estas migraciones pueden tardar algo de tiempo en ejecutarse. Podrías querer ejecutar este comando durante horas de bajo pico. -## Purgando Datos Antiguos +### Actualizando de 0.4.3 -> 0.5.0 + +Si estás actualizando de 0.4.3 a 0.5.0, necesitarás ejecutar el siguiente comando: + +```bash +php vendor/bin/runway apm:config-migrate +``` + +Esto migrará tu configuración del formato antiguo usando el archivo `.runway-config.json` al nuevo formato que almacena las claves/valores en el archivo `config.php`. + +## Purgar Datos Antiguos Para mantener tu base de datos ordenada, puedes purgar datos antiguos. Esto es especialmente útil si estás ejecutando una app ocupada y quieres mantener el tamaño de la base de datos manejable. Puedes hacerlo ejecutando el siguiente comando: @@ -322,26 +333,26 @@ Esto eliminará todos los datos más antiguos que 7 días de la base de datos. ¿Atascado? Prueba estos: - **¿No hay datos en el Dashboard?** - - ¿Está el worker ejecutándose? Verifica `ps aux | grep apm:worker`. - - ¿Las rutas de config coinciden? Verifica que los DSNs en `.runway-config.json` apunten a archivos reales. + - ¿Está ejecutándose el worker? Verifica `ps aux | grep apm:worker`. + - ¿Las rutas de configuración coinciden? Verifica que los DSNs en `.runway-config.json` apunten a archivos reales. - Ejecuta `php vendor/bin/runway apm:worker` manualmente para procesar métricas pendientes. - **¿Errores en el Worker?** - - Mira tus archivos SQLite (p.ej., `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Verifica los logs de PHP para stack traces. + - Mira tus archivos SQLite (por ejemplo, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). + - Verifica los logs de PHP para trazas de pila. -- **¿El Dashboard no Inicia?** +- **¿El Dashboard no inicia?** - ¿Puerto 8001 en uso? Usa `--port 8080`. - ¿PHP no encontrado? Usa `--php-path /usr/bin/php`. - ¿Firewall bloqueando? Abre el puerto o usa `--host localhost`. -- **¿Demasiado Lento?** +- **¿Demasiado lento?** - Baja la tasa de muestreo: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - Reduce el tamaño de lote: `--batch_size 20`. -- **¿No Rastrea Excepciones/Errores?** +- **¿No rastrea Excepciones/Errores?** - Si tienes [Tracy](https://tracy.nette.org/) habilitado para tu proyecto, sobrescribirá el manejo de errores de Flight. Necesitarás deshabilitar Tracy y luego asegurarte de que `Flight::set('flight.handle_errors', true);` esté configurado. -- **¿No Rastrea Consultas de Base de Datos?** +- **¿No rastrea Consultas de Base de Datos?** - Asegúrate de estar usando `PdoWrapper` para tus conexiones de base de datos. - - Asegúrate de hacer el último argumento en el constructor `true`. \ No newline at end of file + - Asegúrate de que el último argumento en el constructor sea `true`. \ No newline at end of file diff --git a/content/v3/es/awesome-plugins/awesome_plugins.md b/content/v3/es/awesome-plugins/awesome_plugins.md index deb861c8..415ab10f 100644 --- a/content/v3/es/awesome-plugins/awesome_plugins.md +++ b/content/v3/es/awesome-plugins/awesome_plugins.md @@ -1,6 +1,6 @@ # Plugins Geniales -Flight es increíblemente extensible. Hay una serie de plugins que se pueden usar para agregar funcionalidad a tu aplicación Flight. Algunos son soportados oficialmente por el Equipo de Flight y otros son bibliotecas micro/lite para ayudarte a comenzar. +Flight es increíblemente extensible. Hay una serie de plugins que se pueden usar para agregar funcionalidad a tu aplicación Flight. Algunos son oficialmente soportados por el Equipo de Flight y otros son bibliotecas micro/lite para ayudarte a comenzar. ## Documentación de API @@ -12,31 +12,31 @@ La documentación de API es crucial para cualquier API. Ayuda a los desarrollado ## Monitoreo de Rendimiento de Aplicaciones (APM) El Monitoreo de Rendimiento de Aplicaciones (APM) es crucial para cualquier aplicación. Te ayuda a entender cómo está funcionando tu aplicación y dónde están los cuellos de botella. Hay una serie de herramientas APM que se pueden usar con Flight. -- oficial [flightphp/apm](/awesome-plugins/apm) - Flight APM es una biblioteca APM simple que se puede usar para monitorear tus aplicaciones Flight. Se puede usar para monitorear el rendimiento de tu aplicación y ayudarte a identificar cuellos de botella. +- oficial [flightphp/apm](/awesome-plugins/apm) - Flight APM es una biblioteca APM simple que se puede usar para monitorear tus aplicaciones de Flight. Se puede usar para monitorear el rendimiento de tu aplicación y ayudarte a identificar cuellos de botella. ## Async Flight ya es un framework rápido, pero agregarle un motor turbo lo hace todo más divertido (¡y desafiante)! -- [flightphp/async](/awesome-plugins/async) - Biblioteca oficial de Flight Async. Esta biblioteca es una forma simple de agregar procesamiento asíncrono a tu aplicación. Usa Swoole/Openswoole bajo el capó para proporcionar una forma simple y efectiva de ejecutar tareas de manera asíncrona. +- [flightphp/async](/awesome-plugins/async) - Biblioteca Async oficial de Flight. Esta biblioteca es una forma simple de agregar procesamiento asíncrono a tu aplicación. Usa Swoole/Openswoole bajo el capó para proporcionar una forma simple y efectiva de ejecutar tareas de manera asíncrona. ## Autorización/Permisos -La autorización y los permisos son cruciales para cualquier aplicación que requiera controles en su lugar para quién puede acceder a qué. +La Autorización y Permisos son cruciales para cualquier aplicación que requiera controles en su lugar para quién puede acceder a qué. -- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca oficial de Permisos de Flight. Esta biblioteca es una forma simple de agregar permisos a nivel de usuario y aplicación a tu aplicación. +- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca de Permisos oficial de Flight. Esta biblioteca es una forma simple de agregar permisos a nivel de usuario y aplicación a tu aplicación. ## Caché El caché es una gran manera de acelerar tu aplicación. Hay una serie de bibliotecas de caché que se pueden usar con Flight. -- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Clase ligera, simple y independiente de caché en archivo PHP +- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Clase de caché en archivo PHP ligera, simple y independiente ## CLI Las aplicaciones CLI son una gran manera de interactuar con tu aplicación. Puedes usarlas para generar controladores, mostrar todas las rutas y más. -- oficial [flightphp/runway](/awesome-plugins/runway) - Runway es una aplicación CLI que te ayuda a gestionar tus aplicaciones Flight. +- oficial [flightphp/runway](/awesome-plugins/runway) - Runway es una aplicación CLI que te ayuda a gestionar tus aplicaciones de Flight. ## Cookies @@ -46,17 +46,17 @@ Las cookies son una gran manera de almacenar pequeños fragmentos de datos en el ## Depuración -La depuración es crucial cuando estás desarrollando en tu entorno local. Hay algunos plugins que pueden elevar tu experiencia de depuración. +La depuración es crucial cuando estás desarrollando en tu entorno local. Hay unos pocos plugins que pueden elevar tu experiencia de depuración. -- [tracy/tracy](/awesome-plugins/tracy) - Esta es un manejador de errores completo que se puede usar con Flight. Tiene una serie de paneles que pueden ayudarte a depurar tu aplicación. También es muy fácil de extender y agregar tus propios paneles. -- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado con el manejador de errores [Tracy](/awesome-plugins/tracy), este plugin agrega algunos paneles extra para ayudar con la depuración específicamente para proyectos de Flight. +- [tracy/tracy](/awesome-plugins/tracy) - Este es un manejador de errores completo que se puede usar con Flight. Tiene una serie de paneles que pueden ayudarte a depurar tu aplicación. También es muy fácil de extender y agregar tus propios paneles. +- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado con el manejador de errores [Tracy](/awesome-plugins/tracy), este plugin agrega unos pocos paneles extra para ayudar con la depuración específicamente para proyectos de Flight. ## Bases de Datos -Las bases de datos son el núcleo de la mayoría de las aplicaciones. Así es como almacenas y recuperas datos. Algunas bibliotecas de bases de datos son simplemente envolturas para escribir consultas y algunas son ORMs completos. +Las bases de datos son el núcleo de la mayoría de las aplicaciones. Así es como almacenas y recuperas datos. Algunas bibliotecas de bases de datos son simplemente envolturas para escribir consultas y otras son ORMs completos. -- oficial [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Envoltura oficial de PDO de Flight que forma parte del núcleo. Esta es una envoltura simple para ayudar a simplificar el proceso de escribir consultas y ejecutarlas. No es un ORM. -- oficial [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper oficial de ActiveRecord de Flight. Gran biblioteca pequeña para recuperar y almacenar datos fácilmente en tu base de datos. +- oficial [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Envoltura PDO oficial de Flight que forma parte del núcleo. Esta es una envoltura simple para ayudar a simplificar el proceso de escribir consultas y ejecutarlas. No es un ORM. +- oficial [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord oficial de Flight. Gran biblioteca pequeña para recuperar y almacenar datos fácilmente en tu base de datos. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin para rastrear todos los cambios de base de datos para tu proyecto. ## Encriptación @@ -65,9 +65,9 @@ La encriptación es crucial para cualquier aplicación que almacene datos sensib - [defuse/php-encryption](/awesome-plugins/php-encryption) - Esta es una biblioteca que se puede usar para encriptar y desencriptar datos. Ponerse en marcha es bastante simple para comenzar a encriptar y desencriptar datos. -## Cola de Trabajos +## Cola de Tareas -Las colas de trabajos son realmente útiles para procesar tareas de manera asíncrona. Esto puede ser enviar correos electrónicos, procesar imágenes o cualquier cosa que no necesite hacerse en tiempo real. +Las colas de tareas son realmente útiles para procesar tareas de manera asíncrona. Esto puede ser enviar correos electrónicos, procesar imágenes o cualquier cosa que no necesite hacerse en tiempo real. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue es una biblioteca que se puede usar para procesar trabajos de manera asíncrona. Se puede usar con beanstalkd, MySQL/MariaDB, SQLite y PostgreSQL. @@ -75,23 +75,23 @@ Las colas de trabajos son realmente útiles para procesar tareas de manera asín Las sesiones no son realmente útiles para las API, pero para construir una aplicación web, las sesiones pueden ser cruciales para mantener el estado e información de inicio de sesión. -- oficial [flightphp/session](/awesome-plugins/session) - Biblioteca oficial de Sesión de Flight. Esta es una biblioteca de sesión simple que se puede usar para almacenar y recuperar datos de sesión. Usa el manejo de sesiones incorporado de PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - Gestor de Sesión PHP (no bloqueante, flash, segmento, encriptación de sesión). Usa PHP open_ssl para encriptación/desencriptación opcional de datos de sesión. +- oficial [flightphp/session](/awesome-plugins/session) - Biblioteca de Sesión oficial de Flight. Esta es una biblioteca de sesión simple que se puede usar para almacenar y recuperar datos de sesión. Usa el manejo de sesiones integrado de PHP. +- [Ghostff/Session](/awesome-plugins/ghost-session) - Gestor de Sesiones PHP (no bloqueante, flash, segmento, encriptación de sesión). Usa PHP open_ssl para encriptación/desencriptación opcional de datos de sesión. ## Plantillas La plantillación es el núcleo de cualquier aplicación web con una UI. Hay una serie de motores de plantillas que se pueden usar con Flight. - deprecado [flightphp/core View](/learn#views) - Este es un motor de plantillas muy básico que forma parte del núcleo. No se recomienda usarlo si tienes más de un par de páginas en tu proyecto. -- [latte/latte](/awesome-plugins/latte) - Latte es un motor de plantillas completo que es muy fácil de usar y se siente más cercano a la sintaxis de PHP que Twig o Smarty. También es muy fácil de extender y agregar tus propios filtros y funciones. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate es un potente motor de plantillas PHP con compilación de activos, herencia de plantillas y procesamiento de variables. Incluye minificación automática de CSS/JS, caché, codificación Base64 e integración opcional con el framework Flight PHP. +- [latte/latte](/awesome-plugins/latte) - Latte es un motor de plantillas completo que es muy fácil de usar y se siente más cercano a la sintaxis PHP que Twig o Smarty. También es muy fácil de extender y agregar tus propios filtros y funciones. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate es un potente motor de plantillas PHP con compilación de activos, herencia de plantillas y procesamiento de variables. Incluye minificación automática de CSS/JS, caché, codificación Base64 e integración opcional con el framework PHP Flight. ## Integración con WordPress ¿Quieres usar Flight en tu proyecto de WordPress? ¡Hay un plugin práctico para eso! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Este plugin de WordPress te permite ejecutar Flight junto con WordPress. Es perfecto para agregar APIs personalizadas, microservicios o incluso aplicaciones completas a tu sitio de WordPress usando el framework Flight. ¡Súper útil si quieres lo mejor de ambos mundos! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Este plugin de WordPress te permite ejecutar Flight justo al lado de WordPress. Es perfecto para agregar APIs personalizadas, microservicios o incluso aplicaciones completas a tu sitio de WordPress usando el framework Flight. ¡Súper útil si quieres lo mejor de ambos mundos! -## Contribuyendo +## Contribución ¿Tienes un plugin que te gustaría compartir? ¡Envía una solicitud de pull para agregarlo a la lista! \ No newline at end of file diff --git a/content/v3/es/awesome-plugins/comment_template.md b/content/v3/es/awesome-plugins/comment_template.md index 16a9a152..227e1e81 100644 --- a/content/v3/es/awesome-plugins/comment_template.md +++ b/content/v3/es/awesome-plugins/comment_template.md @@ -8,7 +8,7 @@ - **Compilación de Activos**: Minificación y caché automáticos de CSS/JS - **Procesamiento de Variables**: Variables de plantilla con filtros y comandos - **Codificación Base64**: Activos en línea como URIs de datos -- **Integración con Flight Framework**: Integración opcional con el framework PHP Flight +- **Integración con el Framework Flight**: Integración opcional con el framework PHP Flight ## Instalación @@ -33,13 +33,13 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Directorio raíz (donde está index.php) - la raíz del documento de su aplicación web + // Directorio raíz (donde está index.php) - el directorio raíz de tu aplicación web $engine->setPublicPath(__DIR__); - // Directorio de archivos de plantilla - soporta rutas relativas y absolutas + // Directorio de archivos de plantillas - soporta rutas relativas y absolutas $engine->setSkinPath('views'); // Relativo a la ruta pública - // Donde se almacenarán los activos compilados - soporta rutas relativas y absolutas + // Dónde se almacenarán los activos compilados - soporta rutas relativas y absolutas $engine->setAssetPath('assets'); // Relativo a la ruta pública // Extensión de archivo de plantilla @@ -76,17 +76,17 @@ $app->map('render', function(string $template, array $data) use ($app): void { ## Configuración de Rutas -CommentTemplate proporciona manejo inteligente de rutas para rutas relativas y absolutas: +CommentTemplate proporciona un manejo inteligente de rutas tanto relativas como absolutas: ### Ruta Pública -La **Ruta Pública** es el directorio raíz de su aplicación web, típicamente donde reside `index.php`. Este es el document root desde donde los servidores web sirven archivos. +La **Ruta Pública** es el directorio raíz de tu aplicación web, típicamente donde reside `index.php`. Este es el directorio raíz desde el que los servidores web sirven archivos. ```php -// Ejemplo: si su index.php está en /var/www/html/myapp/index.php +// Ejemplo: si tu index.php está en /var/www/html/myapp/index.php $template->setPublicPath('/var/www/html/myapp'); // Directorio raíz -// Ejemplo Windows: si su index.php está en C:\xampp\htdocs\myapp\index.php +// Ejemplo en Windows: si tu index.php está en C:\xampp\htdocs\myapp\index.php $template->setPublicPath('C:\\xampp\\htdocs\\myapp'); ``` @@ -98,19 +98,19 @@ La ruta de plantillas soporta tanto rutas relativas como absolutas: $template = new Engine(); $template->setPublicPath('/var/www/html/myapp'); // Directorio raíz (donde está index.php) -// Rutas relativas - automáticamente combinadas con la ruta pública +// Rutas relativas - se combinan automáticamente con la ruta pública $template->setSkinPath('views'); // → /var/www/html/myapp/views/ $template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ -// Rutas absolutas - usadas tal como están (Unix/Linux) +// Rutas absolutas - se usan tal cual (Unix/Linux) $template->setSkinPath('/var/www/templates'); // → /var/www/templates/ $template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ -// Rutas absolutas Windows +// Rutas absolutas en Windows $template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ $template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ -// Rutas UNC (recursos compartidos de red Windows) +// Rutas UNC (comparticiones de red en Windows) $template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ ``` @@ -119,41 +119,41 @@ $template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\te La ruta de activos también soporta tanto rutas relativas como absolutas: ```php -// Rutas relativas - automáticamente combinadas con la ruta pública +// Rutas relativas - se combinan automáticamente con la ruta pública $template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ $template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ -// Rutas absolutas - usadas tal como están (Unix/Linux) +// Rutas absolutas - se usan tal cual (Unix/Linux) $template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ $template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ -// Rutas absolutas Windows +// Rutas absolutas en Windows $template->setAssetPath('C:\\www\\static'); // → C:\www\static\ $template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ -// Rutas UNC (recursos compartidos de red Windows) +// Rutas UNC (comparticiones de red en Windows) $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ ``` **Detección Inteligente de Rutas:** -- **Rutas Relativas**: Sin separadores principales (`/`, `\`) o letras de unidad -- **Unix Absoluta**: Comienza con `/` (ej. `/var/www/assets`) -- **Windows Absoluta**: Comienza con letra de unidad (ej. `C:\www`, `D:/assets`) -- **Rutas UNC**: Comienza con `\\` (ej. `\\server\share`) +- **Rutas Relativas**: Sin separadores iniciales (`/`, `\`) ni letras de unidad +- **Absolutas Unix**: Comienzan con `/` (p. ej., `/var/www/assets`) +- **Absolutas Windows**: Comienzan con letra de unidad (p. ej., `C:\www`, `D:/assets`) +- **Rutas UNC**: Comienzan con `\\` (p. ej., `\\server\share`) **Cómo funciona:** -- Todas las rutas se resuelven automáticamente basándose en el tipo (relativa vs absoluta) +- Todas las rutas se resuelven automáticamente según el tipo (relativa vs absoluta) - Las rutas relativas se combinan con la ruta pública - `@css` y `@js` crean archivos minificados en: `{resolvedAssetPath}/css/` o `{resolvedAssetPath}/js/` -- `@asset` copia archivos únicos a: `{resolvedAssetPath}/{relativePath}` +- `@asset` copia archivos individuales a: `{resolvedAssetPath}/{relativePath}` - `@assetDir` copia directorios a: `{resolvedAssetPath}/{relativePath}` -- Caché inteligente: los archivos solo se copian cuando el origen es más nuevo que el destino +- Caché inteligente: los archivos solo se copian cuando la fuente es más nueva que el destino ## Directivas de Plantilla -### Herencia de Diseño +### Herencia de Diseños Usa diseños para crear una estructura común: @@ -204,7 +204,7 @@ CommentTemplate soporta diferentes estrategias de carga de JavaScript: CommentTemplate también procesa directivas de activos dentro de archivos CSS y JavaScript durante la compilación: -**Ejemplo de CSS:** +**Ejemplo CSS:** ```css /* En tus archivos CSS */ @font-face { @@ -221,7 +221,7 @@ CommentTemplate también procesa directivas de activos dentro de archivos CSS y } ``` -**Ejemplo de JavaScript:** +**Ejemplo JavaScript:** ```javascript /* En tus archivos JS */ const fontUrl = ''; @@ -304,26 +304,26 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### Encadenar Múltiples Filtros +#### Comandos de Variables ```html {$content|striptag|trim|escape} ``` ### Comentarios -Los comentarios de plantilla se eliminan completamente de la salida y no aparecen en el HTML final: +Los comentarios de plantilla se eliminan completamente de la salida y no aparecerán en el HTML final: ```html {* Este es un comentario de plantilla de una línea *} {* - Este es un comentario de plantilla - de múltiples líneas + Este es un comentario de plantilla + de varias líneas que abarca varias líneas *}

          {$title}

          -{* Comentario de depuración: verificar si la variable title funciona *} +{* Comentario de depuración: verificando si la variable title funciona *}

          {$content}

          ``` diff --git a/content/v3/es/awesome-plugins/runway.md b/content/v3/es/awesome-plugins/runway.md index 1edcde81..311c0f7b 100644 --- a/content/v3/es/awesome-plugins/runway.md +++ b/content/v3/es/awesome-plugins/runway.md @@ -1,6 +1,6 @@ -# Pista +# Runway -Pista es una aplicación CLI que te ayuda a gestionar tus aplicaciones Flight. Puede generar controladores, mostrar todas las rutas y más. Está basado en la excelente biblioteca [adhocore/php-cli](https://github.com/adhocore/php-cli). +Runway es una aplicación CLI que te ayuda a gestionar tus aplicaciones Flight. Puede generar controladores, mostrar todas las rutas y más. Se basa en la excelente biblioteca [adhocore/php-cli](https://github.com/adhocore/php-cli). Haz clic [aquí](https://github.com/flightphp/runway) para ver el código. @@ -14,40 +14,40 @@ composer require flightphp/runway ## Configuración Básica -La primera vez que ejecutes Pista, te guiará a través de un proceso de configuración y creará un archivo de configuración `.runway.json` en la raíz de tu proyecto. Este archivo contendrá algunas configuraciones necesarias para que Pista funcione correctamente. +La primera vez que ejecutes Runway, te guiará a través de un proceso de configuración y creará un archivo de configuración `.runway.json` en la raíz de tu proyecto. Este archivo contendrá algunas configuraciones necesarias para que Runway funcione correctamente. ## Uso -Pista tiene varios comandos que puedes usar para gestionar tu aplicación Flight. Hay dos formas fáciles de usar Pista. +Runway tiene una serie de comandos que puedes usar para gestionar tu aplicación Flight. Hay dos formas fáciles de usar Runway. -1. Si estás usando el proyecto esqueleto, puedes ejecutar `php runway [comando]` desde la raíz de tu proyecto. -1. Si estás usando Pista como un paquete instalado a través de composer, puedes ejecutar `vendor/bin/runway [comando]` desde la raíz de tu proyecto. +1. Si estás usando el proyecto esqueleto, puedes ejecutar `php runway [command]` desde la raíz de tu proyecto. +1. Si estás usando Runway como un paquete instalado vía composer, puedes ejecutar `vendor/bin/runway [command]` desde la raíz de tu proyecto. -Para cualquier comando, puedes agregar la bandera `--help` para obtener más información sobre cómo usar el comando. +Para cualquier comando, puedes pasar la bandera `--help` para obtener más información sobre cómo usar el comando. ```bash php runway routes --help ``` -Aquí tienes algunos ejemplos: +Aquí hay algunos ejemplos: ### Generar un Controlador Basado en la configuración en tu archivo `.runway.json`, la ubicación predeterminada generará un controlador para ti en el directorio `app/controllers/`. ```bash -php runway make:controller MiControlador +php runway make:controller MyController ``` -### Generar un Modelo de Active Record +### Generar un Modelo Active Record -Basado en la configuración en tu archivo `.runway.json`, la ubicación predeterminada generará un modelo de Active Record para ti en el directorio `app/records/`. +Basado en la configuración en tu archivo `.runway.json`, la ubicación predeterminada generará un controlador para ti en el directorio `app/records/`. ```bash -php runway make:record usuarios +php runway make:record users ``` -Si por ejemplo tienes la tabla `usuarios` con el siguiente esquema: `id`, `nombre`, `correo`, `creado_en`, `actualizado_en`, se creará un archivo similar al siguiente en el archivo `app/records/UserRecord.php`: +Si, por ejemplo, tienes la tabla `users` con el siguiente esquema: `id`, `name`, `email`, `created_at`, `updated_at`, se creará un archivo similar al siguiente en el archivo `app/records/UserRecord.php`: ```php $config JSON config de .runway-config.json + * @param array $config Configuración JSON de .runway-config.json */ public function __construct(array $config) { parent::__construct('make:example', 'Crear un ejemplo para la documentación', $config); - $this->argument('', 'El nombre del gif divertido'); + $this->argument('', 'El nombre del gif divertido'); } /** @@ -138,7 +138,7 @@ class ExampleCommand extends AbstractBaseCommand * * @return void */ - public function execute(string $controlador) + public function execute() { $io = $this->app()->io(); @@ -151,4 +151,43 @@ class ExampleCommand extends AbstractBaseCommand } ``` -Consulta la [Documentación de adhocore/php-cli](https://github.com/adhocore/php-cli) para obtener más información sobre cómo crear tus propios comandos personalizados en tu aplicación Flight. \ No newline at end of file +Consulta la [Documentación de adhocore/php-cli](https://github.com/adhocore/php-cli) para obtener más información sobre cómo construir tus propios comandos personalizados en tu aplicación Flight! + +### Configuración + +Si necesitas personalizar la configuración para Runway, puedes crear un archivo `.runway-config.json` en la raíz de tu proyecto. A continuación se muestran algunas configuraciones adicionales que puedes establecer: + +```js +{ + + // Aquí es donde se encuentra el directorio de tu aplicación + "app_root": "app/", + + // Este es el directorio donde se encuentra tu archivo index raíz + "index_root": "public/", + + // Estas son las rutas a las raíces de otros proyectos + "root_paths": [ + "/home/user/different-project", + "/var/www/another-project" + ], + + // Las rutas base probablemente no necesiten configurarse, pero está aquí si lo quieres + "base_paths": { + "/includes/libs/vendor", // si tienes una ruta realmente única para tu directorio vendor o algo + }, + + // Las rutas finales son ubicaciones dentro de un proyecto para buscar los archivos de comandos + "final_paths": { + "src/diff-path/commands", + "app/module/admin/commands", + }, + + // Si quieres agregar la ruta completa, adelante (absoluta o relativa a la raíz del proyecto) + "paths": [ + "/home/user/different-project/src/diff-path/commands", + "/var/www/another-project/app/module/admin/commands", + "app/my-unique-commands" + ] +} +``` \ No newline at end of file diff --git a/content/v3/es/examples.md b/content/v3/es/examples.md index 3dcf8760..1faf7537 100644 --- a/content/v3/es/examples.md +++ b/content/v3/es/examples.md @@ -3,7 +3,7 @@ Tienes dos opciones para comenzar con un nuevo proyecto de Flight: - [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Un ejemplo más completo con controladores y vistas. -- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Un solo archivo que incluye todo lo que necesitas para ejecutar tu aplicación en un archivo simple. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Un solo archivo que incluye todo lo que necesitas para ejecutar tu app en un archivo simple. Ejemplos contribuidos por la comunidad: @@ -16,11 +16,12 @@ Ejemplos contribuidos por la comunidad: Aunque estos no están patrocinados oficialmente por el equipo de Flight, podrían darte ideas sobre cómo estructurar tus propios proyectos construidos con Flight! +- [ASC REST API Spell Checker](https://github.com/AlMosahih-ASC/asc-api-sample) - Una API REST ligera para corrección ortográfica en árabe construida con FlightPHP y la biblioteca ArPHP. Esta API proporciona capacidades de corrección ortográfica de texto árabe, incluyendo detección de palabras mal escritas y sugerencias de corrección. - [Eventify](https://github.com/ilhanklisura/eventify) - Eventify es una aplicación de una sola página que conecta a organizadores de eventos con asistentes. Construida con PHP (FlightPHP), JavaScript y MySQL, cuenta con autenticación JWT, gestión de eventos y documentación de API RESTful usando OpenAPI. -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental es una aplicación web de alquiler de autos de una sola página, amigable con móviles, construida con PHP (FlightPHP), JavaScript y MySQL. Soporta registro de usuarios, navegación y reserva de autos, mientras que los administradores pueden gestionar autos, usuarios y reservas. La aplicación cuenta con una API REST, autenticación JWT y un diseño responsivo para una experiencia de alquiler moderna. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental es una aplicación web de alquiler de autos de una sola página, amigable con dispositivos móviles, construida con PHP (FlightPHP), JavaScript y MySQL. Soporta registro de usuarios, navegación y reserva de autos, mientras que los administradores pueden gestionar autos, usuarios y reservas. La app cuenta con una API REST, autenticación JWT y un diseño responsivo para una experiencia de alquiler moderna. - [Decay](https://github.com/boxybird/decay) - Flight v3 con HTMX y SleekDB todo sobre zombis! ([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 con Middleware, Controladores, Active Record y Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Proyecto simple de API CRUD usando el framework Flight, que proporciona una estructura básica para que los nuevos usuarios configuren rápidamente una aplicación PHP con operaciones CRUD y conectividad a la base de datos. El proyecto demuestra cómo usar Flight para el desarrollo de API RESTful, convirtiéndolo en una herramienta de aprendizaje ideal para principiantes y un kit de inicio útil para desarrolladores más experimentados. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Proyecto de API CRUD simple usando el framework Flight, que proporciona una estructura básica para que los nuevos usuarios configuren rápidamente una aplicación PHP con operaciones CRUD y conectividad a base de datos. El proyecto demuestra cómo usar Flight para el desarrollo de API RESTful, lo que lo convierte en una herramienta de aprendizaje ideal para principiantes y un kit de inicio útil para desarrolladores más experimentados. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -31,8 +32,8 @@ Aunque estos no están patrocinados oficialmente por el equipo de Flight, podrí - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework de autenticación listo para producción que te ahorra semanas de desarrollo. Cuenta con seguridad de grado empresarial: 2FA/TOTP, integración LDAP, Azure SSO, limitación de tasa inteligente, huella dactilar de sesión, protección contra fuerza bruta, panel de análisis de seguridad, registro de auditoría integral y control de acceso basado en roles granular. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework de autenticación listo para producción que te ahorra semanas de desarrollo. Características de seguridad de nivel empresarial: 2FA/TOTP, integración LDAP, SSO de Azure, limitación de velocidad inteligente, huella dactilar de sesión, protección contra fuerza bruta, panel de análisis de seguridad, registro de auditoría integral y control de acceso basado en roles granular. ## ¿Quieres compartir tu propio ejemplo? -Si tienes un proyecto que quieres compartir, por favor envía una solicitud de pull para agregarlo a esta lista! \ No newline at end of file +Si tienes un proyecto que quieres compartir, ¡por favor envía una solicitud de pull para agregarlo a esta lista! \ No newline at end of file diff --git a/content/v3/fr/awesome-plugins/active_record.md b/content/v3/fr/awesome-plugins/active_record.md index 048e6952..d781cb9f 100644 --- a/content/v3/fr/awesome-plugins/active_record.md +++ b/content/v3/fr/awesome-plugins/active_record.md @@ -1,12 +1,12 @@ -# Flight Active Record +# Flight Active Record -Un enregistrement actif est une cartographie d'une entité de base de données à un objet PHP. En d'autres termes, si vous avez une table utilisateurs dans votre base de données, vous pouvez "traduire" une ligne dans cette table en une classe `User` et un objet `$user` dans votre code. Voir [exemple de base](#basic-example). +Un active record est un mappage d'une entité de base de données vers un objet PHP. En termes simples, si vous avez un tableau users dans votre base de données, vous pouvez « traduire » une ligne de ce tableau vers une classe `User` et un objet `$user` dans votre codebase. Voir [exemple de base](#basic-example). Cliquez [ici](https://github.com/flightphp/active-record) pour le dépôt sur GitHub. -## Exemple de Base +## Exemple de base -Assumons que vous ayez la table suivante : +Supposons que vous ayez le tableau suivant : ```sql CREATE TABLE users ( @@ -16,13 +16,13 @@ CREATE TABLE users ( ); ``` -Maintenant, vous pouvez configurer une nouvelle classe pour représenter cette table : +Maintenant, vous pouvez configurer une nouvelle classe pour représenter ce tableau : ```php /** - * Une classe ActiveRecord est généralement singulière + * Une classe ActiveRecord est généralement au singulier * - * Il est fortement recommandé d'ajouter ici les propriétés de la table en tant que commentaires + * Il est fortement recommandé d'ajouter les propriétés du tableau en tant que commentaires ici * * @property int $id * @property string $name @@ -31,26 +31,26 @@ Maintenant, vous pouvez configurer une nouvelle classe pour représenter cette t class User extends flight\ActiveRecord { public function __construct($database_connection) { - // vous pouvez le définir de cette manière + // vous pouvez le définir de cette façon parent::__construct($database_connection, 'users'); - // ou de cette manière + // ou de cette façon parent::__construct($database_connection, null, [ 'table' => 'users']); } } ``` -Maintenant, regardez la magie opérer ! +Maintenant, regardez la magie opérer ! ```php // pour sqlite -$database_connection = new PDO('sqlite:test.db'); // ceci est juste un exemple, vous devriez probablement utiliser une vraie connexion à une base de données +$database_connection = new PDO('sqlite:test.db'); // ceci n'est qu'un exemple, vous utiliseriez probablement une vraie connexion à la base de données // pour mysql $database_connection = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'username', 'password'); // ou mysqli $database_connection = new mysqli('localhost', 'username', 'password', 'test_db'); -// ou mysqli avec création non basée sur des objets +// ou mysqli avec une création non basée sur les objets $database_connection = mysqli_connect('localhost', 'username', 'password', 'test_db'); $user = new User($database_connection); @@ -64,79 +64,79 @@ echo $user->id; // 1 $user->name = 'Joseph Mamma'; $user->password = password_hash('some cool password again!!!'); $user->insert(); -// impossible d'utiliser $user->save() ici sinon il pensera que c'est une mise à jour ! +// ne peut pas utiliser $user->save() ici ou il pensera que c'est une mise à jour ! echo $user->id; // 2 ``` -Et c'était aussi simple que cela d'ajouter un nouvel utilisateur ! Maintenant qu'il y a une ligne d'utilisateur dans la base de données, comment la récupérer ? +Et c'était aussi simple que cela d'ajouter un nouvel utilisateur ! Maintenant qu'il y a une ligne d'utilisateur dans la base de données, comment la récupérer ? ```php -$user->find(1); // trouver id = 1 dans la base de données et le renvoyer. +$user->find(1); // trouve id = 1 dans la base de données et le retourne. echo $user->name; // 'Bobby Tables' ``` -Et que se passe-t-il si vous souhaitez trouver tous les utilisateurs ? +Et si vous voulez trouver tous les utilisateurs ? ```php $users = $user->findAll(); ``` -Que dire d'une certaine condition ? +Et avec une certaine condition ? ```php $users = $user->like('name', '%mamma%')->findAll(); ``` -Voyez comme c'est amusant ? Installons-le et commençons ! +Voyez comme c'est amusant ? Installons-le et commençons ! ## Installation -Il suffit d'installer avec Composer +Installez simplement avec Composer ```php composer require flightphp/active-record ``` -## Usage +## Utilisation -Cela peut être utilisé comme une bibliothèque autonome ou avec le Framework PHP Flight. Complètement à vous de choisir. +Cela peut être utilisé comme une bibliothèque autonome ou avec le Framework PHP Flight. C'est entièrement à vous. ### Autonome -Il suffit de vous assurer que vous passez une connexion PDO au constructeur. +Assurez-vous simplement de passer une connexion PDO au constructeur. ```php -$pdo_connection = new PDO('sqlite:test.db'); // ceci est juste un exemple, vous devriez probablement utiliser une vraie connexion à une base de données +$pdo_connection = new PDO('sqlite:test.db'); // ceci n'est qu'un exemple, vous utiliseriez probablement une vraie connexion à la base de données $User = new User($pdo_connection); ``` -> Vous ne voulez pas toujours définir votre connexion à la base de données dans le constructeur ? Consultez [Gestion des Connexions à la Base de Données](#database-connection-management) pour d'autres idées ! +> Vous ne voulez pas toujours définir votre connexion à la base de données dans le constructeur ? Voir [Gestion des connexions à la base de données](#database-connection-management) pour d'autres idées ! -### Enregistrer en tant que méthode dans Flight -Si vous utilisez le Framework PHP Flight, vous pouvez enregistrer la classe ActiveRecord en tant que service, mais vous n'êtes vraiment pas obligé. +### Enregistrer comme une méthode dans Flight +Si vous utilisez le Framework PHP Flight, vous pouvez enregistrer la classe ActiveRecord comme un service, mais honnêtement, vous n'avez pas à le faire. ```php Flight::register('user', 'User', [ $pdo_connection ]); -// puis vous pouvez l'utiliser comme ceci dans un contrôleur, une fonction, etc. +// ensuite vous pouvez l'utiliser comme ceci dans un contrôleur, une fonction, etc. Flight::user()->find(1); ``` ## Méthodes `runway` -[runway](/awesome-plugins/runway) est un outil CLI pour Flight qui a une commande personnalisée pour cette bibliothèque. +[runway](/awesome-plugins/runway) est un outil CLI pour Flight qui a une commande personnalisée pour cette bibliothèque. ```bash -# Usage +# Utilisation php runway make:record database_table_name [class_name] # Exemple php runway make:record users ``` -Cela créera une nouvelle classe dans le répertoire `app/records/` sous le nom `UserRecord.php` avec le contenu suivant : +Cela créera une nouvelle classe dans le répertoire `app/records/` sous le nom `UserRecord.php` avec le contenu suivant : ```php find($id); #### `findAll(): array` -Trouve tous les enregistrements dans la table que vous spécifiez. +Trouve tous les enregistrements dans le tableau que vous spécifiez. ```php $user->findAll(); @@ -203,7 +203,7 @@ $user->findAll(); #### `isHydrated(): boolean` (v0.4.0) -Retourne `true` si l'enregistrement actuel a été hydraté (récupéré de la base de données). +Retourne `true` si l'enregistrement courant a été hydraté (récupéré depuis la base de données). ```php $user->find(1); @@ -213,7 +213,7 @@ $user->isHydrated(); // true #### `insert(): boolean|ActiveRecord` -Insère l'enregistrement actuel dans la base de données. +Insère l'enregistrement courant dans la base de données. ```php $user = new User($pdo_connection); @@ -222,9 +222,9 @@ $user->password = md5('demo'); $user->insert(); ``` -##### Clés Primaires Basées sur du Texte +##### Clés primaires basées sur du texte -Si vous avez une clé primaire basée sur du texte (comme un UUID), vous pouvez définir la valeur de la clé primaire avant d'insérer de deux manières. +Si vous avez une clé primaire basée sur du texte (comme un UUID), vous pouvez définir la valeur de la clé primaire avant l'insertion de deux façons. ```php $user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]); @@ -234,30 +234,28 @@ $user->password = md5('demo'); $user->insert(); // ou $user->save(); ``` -ou vous pouvez laisser la clé primaire être générée automatiquement pour vous via des événements. +ou vous pouvez avoir la clé primaire générée automatiquement pour vous via des événements. ```php class User extends flight\ActiveRecord { public function __construct($database_connection) { parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]); - // vous pouvez également définir la primaryKey de cette manière au lieu de l'array ci-dessus. + // vous pouvez aussi définir la primaryKey de cette façon au lieu du tableau ci-dessus. $this->primaryKey = 'uuid'; } protected function beforeInsert(self $self) { - $self->uuid = uniqid(); // ou comme vous avez besoin de générer vos identifiants uniques + $self->uuid = uniqid(); // ou cependant vous devez générer vos identifiants uniques } } ``` -Si vous ne définissez pas la clé primaire avant d'insérer, elle sera définie sur le `rowid` et la -base de données la générera pour vous, mais elle ne sera pas persistante car ce champ peut ne pas exister -dans votre table. C'est pourquoi il est recommandé d'utiliser l'événement pour gérer cela automatiquement. +Si vous ne définissez pas la clé primaire avant l'insertion, elle sera définie sur `rowid` et la base de données la générera pour vous, mais elle ne persistera pas car ce champ peut ne pas exister dans votre tableau. C'est pourquoi il est recommandé d'utiliser l'événement pour gérer cela automatiquement. #### `update(): boolean|ActiveRecord` -Met à jour l'enregistrement actuel dans la base de données. +Met à jour l'enregistrement courant dans la base de données. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); @@ -267,7 +265,7 @@ $user->update(); #### `save(): boolean|ActiveRecord` -Insère ou met à jour l'enregistrement actuel dans la base de données. Si l'enregistrement a un id, il sera mis à jour, sinon il sera inséré. +Insère ou met à jour l'enregistrement courant dans la base de données. Si l'enregistrement a un id, il mettra à jour, sinon il insérera. ```php $user = new User($pdo_connection); @@ -276,18 +274,18 @@ $user->password = md5('demo'); $user->save(); ``` -**Remarque :** Si vous avez des relations définies dans la classe, elles seront sauvegardées de manière récursive si elles ont été définies, instanciées et ont des données "sales" à mettre à jour. (v0.4.0 et plus) +**Note :** Si vous avez des relations définies dans la classe, il sauvegardera récursivement ces relations également si elles ont été définies, instanciées et ont des données modifiées à mettre à jour. (v0.4.0 et supérieur) #### `delete(): boolean` -Supprime l'enregistrement actuel de la base de données. +Supprime l'enregistrement courant de la base de données. ```php $user->gt('id', 0)->orderBy('id desc')->find(); $user->delete(); ``` -Vous pouvez également supprimer plusieurs enregistrements en exécutant une recherche au préalable. +Vous pouvez aussi supprimer plusieurs enregistrements en exécutant une recherche au préalable. ```php $user->like('name', 'Bob%')->delete(); @@ -295,23 +293,23 @@ $user->like('name', 'Bob%')->delete(); #### `dirty(array $dirty = []): ActiveRecord` -Les données "sales" se réfèrent aux données qui ont été modifiées dans un enregistrement. +Les données modifiées font référence aux données qui ont été changées dans un enregistrement. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); -// rien n'est "sale" à ce stade. +// rien n'est "modifié" à ce stade. -$user->email = 'test@example.com'; // maintenant l'email est considéré comme "sale" puisqu'il a changé. +$user->email = 'test@example.com'; // maintenant email est considéré comme "modifié" car il a changé. $user->update(); -// maintenant il n'y a pas de données qui sont sales car elles ont été mises à jour et persistées dans la base de données +// maintenant il n'y a plus de données modifiées car elles ont été mises à jour et persistées dans la base de données -$user->password = password_hash()'newpassword'); // maintenant c'est sale -$user->dirty(); // ne rien passer effacera toutes les entrées sales. -$user->update(); // rien ne sera mis à jour car rien n'a été capturé comme sale. +$user->password = password_hash()'newpassword'); // maintenant ceci est modifié +$user->dirty(); // ne passer rien effacera toutes les entrées modifiées. +$user->update(); // rien ne sera mis à jour car rien n'a été capturé comme modifié. $user->dirty([ 'name' => 'something', 'password' => password_hash('a different password') ]); -$user->update(); // à la fois le nom et le mot de passe sont mis à jour. +$user->update(); // nom et password sont tous deux mis à jour. ``` #### `copyFrom(array $data): ActiveRecord` (v0.4.0) @@ -320,12 +318,12 @@ Ceci est un alias pour la méthode `dirty()`. C'est un peu plus clair ce que vou ```php $user->copyFrom([ 'name' => 'something', 'password' => password_hash('a different password') ]); -$user->update(); // à la fois le nom et le mot de passe sont mis à jour. +$user->update(); // nom et password sont tous deux mis à jour. ``` #### `isDirty(): boolean` (v0.4.0) -Retourne `true` si l'enregistrement actuel a été modifié. +Retourne `true` si l'enregistrement courant a été modifié. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); @@ -335,8 +333,7 @@ $user->isDirty(); // true #### `reset(bool $include_query_data = true): ActiveRecord` -Réinitialise l'enregistrement actuel à son état initial. C'est vraiment bon à utiliser dans des comportements de type boucle. -Si vous passez `true`, il réinitialisera également les données de requête qui ont été utilisées pour trouver l'objet actuel (comportement par défaut). +Réinitialise l'enregistrement courant à son état initial. C'est vraiment bien à utiliser dans des comportements de type boucle. Si vous passez `true`, il réinitialisera également les données de requête utilisées pour trouver l'objet courant (comportement par défaut). ```php $users = $user->greaterThan('id', 0)->orderBy('id desc')->find(); @@ -352,12 +349,12 @@ foreach($users as $user) { #### `getBuiltSql(): string` (v0.4.1) -Après avoir exécuté une méthode `find()`, `findAll()`, `insert()`, `update()` ou `save()`, vous pouvez obtenir le SQL qui a été construit et l'utiliser à des fins de débogage. +Après avoir exécuté une méthode `find()`, `findAll()`, `insert()`, `update()`, ou `save()`, vous pouvez obtenir le SQL qui a été construit et l'utiliser pour des fins de débogage. -## Méthodes de Requête SQL +## Méthodes de requête SQL #### `select(string $field1 [, string $field2 ... ])` -Vous pouvez sélectionner uniquement quelques-unes des colonnes d'une table si vous le souhaitez (c'est plus performant sur des tables très larges avec de nombreuses colonnes) +Vous pouvez sélectionner seulement quelques colonnes d'un tableau si vous le souhaitez (c'est plus performant sur des tableaux très larges avec de nombreuses colonnes) ```php $user->select('id', 'name')->find(); @@ -365,7 +362,7 @@ $user->select('id', 'name')->find(); #### `from(string $table)` -Vous pouvez techniquement choisir une autre table aussi ! Pourquoi pas ?! +Vous pouvez techniquement choisir un autre tableau aussi ! Pourquoi pas ?! ```php $user->select('id', 'name')->from('user')->find(); @@ -373,7 +370,7 @@ $user->select('id', 'name')->from('user')->find(); #### `join(string $table_name, string $join_condition)` -Vous pouvez même joindre à une autre table dans la base de données. +Vous pouvez même joindre à un autre tableau dans la base de données. ```php $user->join('contacts', 'contacts.user_id = users.id')->find(); @@ -381,17 +378,17 @@ $user->join('contacts', 'contacts.user_id = users.id')->find(); #### `where(string $where_conditions)` -Vous pouvez définir quelques arguments where personnalisés (vous ne pouvez pas définir de paramètres dans cette déclaration where) +Vous pouvez définir des arguments where personnalisés (vous ne pouvez pas définir de paramètres dans cette instruction where) ```php $user->where('id=1 AND name="demo"')->find(); ``` -**Remarque de Sécurité** - Vous pourriez être tenté de faire quelque chose comme `$user->where("id = '{$id}' AND name = '{$name}'")->find();`. S'il vous plaît, NE FAITES PAS CELA !!! Cela est susceptible de ce qu'on appelle des attaques par injection SQL. Il existe de nombreux articles en ligne, s'il vous plaît recherchez "sql injection attacks php" et vous trouverez beaucoup d'articles sur ce sujet. La manière appropriée de gérer cela avec cette bibliothèque est qu'au lieu de cette méthode `where()`, vous feriez quelque chose de plus comme `$user->eq('id', $id)->eq('name', $name)->find();` Si vous devez absolument faire cela, la bibliothèque `PDO` a `$pdo->quote($var)` pour l'échapper pour vous. Ce n'est qu'après avoir utilisé `quote()` que vous pouvez l'utiliser dans une déclaration `where()`. +**Note de sécurité** - Vous pourriez être tenté de faire quelque chose comme `$user->where("id = '{$id}' AND name = '{$name}'")->find();`. S'il vous plaît NE FAITES PAS CELA !!! Cela est vulnérable à ce qu'on appelle des attaques par injection SQL. Il y a beaucoup d'articles en ligne, veuillez googler "sql injection attacks php" et vous trouverez beaucoup d'articles sur ce sujet. La bonne façon de gérer cela avec cette bibliothèque est, au lieu de cette méthode `where()`, de faire quelque chose comme `$user->eq('id', $id)->eq('name', $name)->find();` Si vous devez absolument faire cela, la bibliothèque `PDO` a `$pdo->quote($var)` pour l'échapper pour vous. Seulement après avoir utilisé `quote()` pouvez-vous l'utiliser dans une instruction `where()`. #### `group(string $group_by_statement)/groupBy(string $group_by_statement)` -Groupez vos résultats par une condition particulière. +Regroupez vos résultats par une condition particulière. ```php $user->select('COUNT(*) as count')->groupBy('name')->findAll(); @@ -399,7 +396,7 @@ $user->select('COUNT(*) as count')->groupBy('name')->findAll(); #### `order(string $order_by_statement)/orderBy(string $order_by_statement)` -Trier la requête retournée d'une certaine manière. +Triez la requête retournée d'une certaine manière. ```php $user->orderBy('name DESC')->find(); @@ -407,13 +404,13 @@ $user->orderBy('name DESC')->find(); #### `limit(string $limit)/limit(int $offset, int $limit)` -Limitez le nombre d'enregistrements retournés. Si un second int est donné, il sera décalé, limite tout comme en SQL. +Limitez le nombre d'enregistrements retournés. Si un second int est donné, ce sera offset, limit comme en SQL. ```php $user->orderby('name DESC')->limit(0, 10)->findAll(); ``` -## CONDITIONS WHERE +## Conditions WHERE #### `equal(string $field, mixed $value) / eq(string $field, mixed $value)` Où `field = $value` @@ -501,48 +498,48 @@ $user->between('id', [1, 2])->find(); ### Conditions OR -Il est possible d'envelopper vos conditions dans une déclaration OR. Cela se fait soit avec les méthodes `startWrap()` et `endWrap()`, soit en remplissant le 3ème paramètre de la condition après le champ et la valeur. +Il est possible d'entourer vos conditions d'une instruction OR. Cela se fait soit avec les méthodes `startWrap()` et `endWrap()`, soit en remplissant le 3e paramètre de la condition après le champ et la valeur. ```php // Méthode 1 $user->eq('id', 1)->startWrap()->eq('name', 'demo')->or()->eq('name', 'test')->endWrap('OR')->find(); -// Cela s'évaluera à `id = 1 AND (name = 'demo' OR name = 'test')` +// Cela évaluera à `id = 1 AND (name = 'demo' OR name = 'test')` // Méthode 2 $user->eq('id', 1)->eq('name', 'demo', 'OR')->find(); -// Cela s'évaluera à `id = 1 OR name = 'demo'` +// Cela évaluera à `id = 1 OR name = 'demo'` ``` ## Relations -Vous pouvez définir plusieurs types de relations à l'aide de cette bibliothèque. Vous pouvez établir des relations un->plusieurs et un->un entre des tables. Cela nécessite une petite configuration supplémentaire dans la classe au préalable. +Vous pouvez définir plusieurs types de relations en utilisant cette bibliothèque. Vous pouvez définir des relations un-à-plusieurs et un-à-un entre les tableaux. Cela nécessite un peu de configuration supplémentaire dans la classe au préalable. -Définir le tableau `$relations` n'est pas difficile, mais deviner la syntaxe correcte peut être déroutant. +Définir le tableau `$relations` n'est pas difficile, mais deviner la syntaxe correcte peut être confus. ```php protected array $relations = [ - // vous pouvez nommer la clé comme bon vous semble. Le nom de l'ActiveRecord est probablement bon. Ex : user, contact, client + // vous pouvez nommer la clé comme vous voulez. Le nom de l'ActiveRecord est probablement bon. Ex : user, contact, client 'user' => [ // requis // self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO self::HAS_ONE, // c'est le type de relation // requis - 'Some_Class', // c'est la classe ActiveRecord "autre" à laquelle cela fera référence + 'Some_Class', // c'est la classe ActiveRecord "autre" à laquelle ceci fera référence // requis - // selon le type de relation + // en fonction du type de relation // self::HAS_ONE = la clé étrangère qui référence la jointure // self::HAS_MANY = la clé étrangère qui référence la jointure // self::BELONGS_TO = la clé locale qui référence la jointure 'local_or_foreign_key', - // juste pour info, cela ne joint également qu'à la clé primaire du modèle "autre" + // juste pour info, cela ne joint aussi qu'à la clé primaire du modèle "autre" // optionnel - [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // conditions supplémentaires que vous souhaitez lors de la jointure de la relation + [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // conditions supplémentaires que vous voulez lors de la jointure de la relation // $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5)) // optionnel - 'back_reference_name' // c'est si vous voulez faire référence à cette relation à elle-même Ex : $user->contact->user; + 'back_reference_name' // c'est si vous voulez référencer en arrière cette relation vers elle-même Ex : $user->contact->user; ]; ] ``` @@ -572,7 +569,7 @@ class Contact extends ActiveRecord{ } ``` -Maintenant, nous avons les références configurées afin que nous puissions les utiliser très facilement ! +Maintenant que nous avons configuré les références, nous pouvons les utiliser très facilement ! ```php $user = new User($pdo_connection); @@ -580,7 +577,7 @@ $user = new User($pdo_connection); // trouver l'utilisateur le plus récent. $user->notNull('id')->orderBy('id desc')->find(); -// obtenir les contacts en utilisant la relation : +// obtenir les contacts en utilisant la relation : foreach($user->contacts as $contact) { echo $contact->id; } @@ -591,14 +588,115 @@ $contact = new Contact(); // trouver un contact $contact->find(); -// obtenir l'utilisateur en utilisant la relation : +// obtenir l'utilisateur en utilisant la relation : echo $contact->user->name; // c'est le nom de l'utilisateur ``` -Assez cool, non ? +Plutôt cool, hein ? -## Définir des Données Personnalisées -Parfois, vous pourriez avoir besoin d'attacher quelque chose d'unique à votre ActiveRecord, comme un calcul personnalisé qui serait plus facile à attacher à l'objet qui serait ensuite passé à un modèle, par exemple. +### Chargement impatient + +#### Aperçu +Le chargement impatient résout le problème de requête N+1 en chargeant les relations à l'avance. Au lieu d'exécuter une requête séparée pour les relations de chaque enregistrement, le chargement impatient récupère toutes les données liées en une seule requête supplémentaire par relation. + +> **Note :** Le chargement impatient n'est disponible que pour v0.7.0 et supérieur. + +#### Utilisation de base +Utilisez la méthode `with()` pour spécifier quelles relations charger de manière impatiente : +```php +// Charge les utilisateurs avec leurs contacts en 2 requêtes au lieu de N+1 +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + foreach ($u->contacts as $contact) { + echo $contact->email; // Pas de requête supplémentaire ! + } +} +``` + +#### Relations multiples +Chargez plusieurs relations à la fois : +```php +$users = $user->with(['contacts', 'profile', 'settings'])->findAll(); +``` + +#### Types de relations + +##### HAS_MANY +```php +// Charge de manière impatiente tous les contacts pour chaque utilisateur +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + // $u->contacts est déjà chargé comme un tableau + foreach ($u->contacts as $contact) { + echo $contact->email; + } +} +``` +##### HAS_ONE +```php +// Charge de manière impatiente un contact pour chaque utilisateur +$users = $user->with('contact')->findAll(); +foreach ($users as $u) { + // $u->contact est déjà chargé comme un objet + echo $u->contact->email; +} +``` + +##### BELONGS_TO +```php +// Charge de manière impatiente les utilisateurs parents pour tous les contacts +$contacts = $contact->with('user')->findAll(); +foreach ($contacts as $c) { + // $c->user est déjà chargé + echo $c->user->name; +} +``` +##### Avec find() +Le chargement impatient fonctionne avec +findAll() + et +find() +: + +```php +$user = $user->with('contacts')->find(1); +// Utilisateur et tous leurs contacts chargés en 2 requêtes +``` +#### Avantages en termes de performance +Sans chargement impatient (problème N+1) : +```php +$users = $user->findAll(); // 1 requête +foreach ($users as $u) { + $contacts = $u->contacts; // N requêtes (une par utilisateur !) +} +// Total : 1 + N requêtes +``` + +Avec chargement impatient : + +```php +$users = $user->with('contacts')->findAll(); // 2 requêtes totales +foreach ($users as $u) { + $contacts = $u->contacts; // 0 requêtes supplémentaires ! +} +// Total : 2 requêtes (1 pour les utilisateurs + 1 pour tous les contacts) +``` +Pour 10 utilisateurs, cela réduit les requêtes de 11 à 2 - une réduction de 82 % ! + +#### Notes importantes +- Le chargement impatient est complètement optionnel - le chargement paresseux fonctionne toujours comme avant +- Les relations déjà chargées sont automatiquement ignorées +- Les références arrière fonctionnent avec le chargement impatient +- Les rappels de relation sont respectés pendant le chargement impatient + +#### Limitations +- Le chargement impatient imbriqué (p. ex., +with(['contacts.addresses']) +) n'est pas pris en charge actuellement +- Les contraintes de chargement impatient via des fermetures ne sont pas prises en charge dans cette version + +## Définition de données personnalisées +Parfois, vous pourriez avoir besoin d'attacher quelque chose d'unique à votre ActiveRecord, comme un calcul personnalisé qui pourrait être plus facile à attacher à l'objet qui serait ensuite passé à un template. #### `setCustomData(string $field, mixed $value)` Vous attachez les données personnalisées avec la méthode `setCustomData()`. @@ -606,7 +704,7 @@ Vous attachez les données personnalisées avec la méthode `setCustomData()`. $user->setCustomData('page_view_count', $page_view_count); ``` -Et ensuite, vous le référencez simplement comme une propriété d'objet normale. +Et ensuite vous le référencez simplement comme une propriété d'objet normale. ```php echo $user->page_view_count; @@ -614,11 +712,11 @@ echo $user->page_view_count; ## Événements -Une autre fonctionnalité super géniale de cette bibliothèque concerne les événements. Les événements sont déclenchés à certains moments en fonction de certaines méthodes que vous appelez. Ils sont très utiles pour vous aider à configurer des données automatiquement. +Une autre fonctionnalité super géniale de cette bibliothèque concerne les événements. Les événements sont déclenchés à certains moments en fonction de certaines méthodes que vous appelez. Ils sont très très utiles pour configurer des données pour vous automatiquement. #### `onConstruct(ActiveRecord $ActiveRecord, array &config)` -Cela est vraiment utile si vous avez besoin de définir une connexion par défaut ou quelque chose comme cela. +Ceci est vraiment utile si vous avez besoin de définir une connexion par défaut ou quelque chose comme ça. ```php // index.php ou bootstrap.php @@ -632,12 +730,12 @@ Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); class User extends flight\ActiveRecord { protected function onConstruct(self $self, array &$config) { // n'oubliez pas la référence & - // vous pourriez faire cela pour définir automatiquement la connexion + // vous pourriez faire ceci pour définir automatiquement la connexion $config['connection'] = Flight::db(); // ou ceci $self->transformAndPersistConnection(Flight::db()); - // Vous pouvez également définir le nom de la table de cette manière. + // Vous pouvez aussi définir le nom du tableau de cette façon. $config['table'] = 'users'; } } @@ -645,7 +743,7 @@ class User extends flight\ActiveRecord { #### `beforeFind(ActiveRecord $ActiveRecord)` -Cela est probablement seulement utile si vous avez besoin d'une manipulation de requête chaque fois. +Ceci est probablement utile seulement si vous avez besoin d'une manipulation de requête à chaque fois. ```php class User extends flight\ActiveRecord { @@ -656,7 +754,7 @@ class User extends flight\ActiveRecord { } protected function beforeFind(self $self) { - // toujours exécuter id >= 0 si c'est votre truc + // exécutez toujours id >= 0 si c'est votre truc $self->gte('id', 0); } } @@ -664,7 +762,7 @@ class User extends flight\ActiveRecord { #### `afterFind(ActiveRecord $ActiveRecord)` -Celui-ci est probablement plus utile si vous devez toujours exécuter une logique chaque fois que cet enregistrement est récupéré. Avez-vous besoin de déchiffrer quelque chose ? Avez-vous besoin d'exécuter une requête de comptage personnalisée chaque fois (pas performant mais peu importe) ? +Celui-ci est probablement plus utile si vous avez toujours besoin d'exécuter une logique à chaque fois que cet enregistrement est récupéré. Avez-vous besoin de déchiffrer quelque chose ? Avez-vous besoin d'exécuter une requête de comptage personnalisée à chaque fois (pas performant mais bon) ? ```php class User extends flight\ActiveRecord { @@ -675,10 +773,10 @@ class User extends flight\ActiveRecord { } protected function afterFind(self $self) { - // déchiffrer quelque chose + // déchiffrage de quelque chose $self->secret = yourDecryptFunction($self->secret, $some_key); - // peut-être stocker quelque chose de personnalisé, comme une requête ??? + // peut-être stocker quelque chose de personnalisé comme une requête ??? $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']; } } @@ -686,7 +784,7 @@ class User extends flight\ActiveRecord { #### `beforeFindAll(ActiveRecord $ActiveRecord)` -Cela est probablement seulement utile si vous avez besoin d'une manipulation de requête chaque fois. +Ceci est probablement utile seulement si vous avez besoin d'une manipulation de requête à chaque fois. ```php class User extends flight\ActiveRecord { @@ -697,7 +795,7 @@ class User extends flight\ActiveRecord { } protected function beforeFindAll(self $self) { - // toujours exécuter id >= 0 si c'est votre truc + // exécutez toujours id >= 0 si c'est votre truc $self->gte('id', 0); } } @@ -705,7 +803,7 @@ class User extends flight\ActiveRecord { #### `afterFindAll(array $results)` -Semblable à `afterFind()` mais vous pouvez le faire pour tous les enregistrements à la place ! +Similaire à `afterFind()` mais vous pouvez le faire pour tous les enregistrements au lieu d'un seul ! ```php class User extends flight\ActiveRecord { @@ -718,7 +816,7 @@ class User extends flight\ActiveRecord { protected function afterFindAll(array $results) { foreach($results as $self) { - // faites quelque chose de cool comme aprèsFind() + // faites quelque chose de cool comme afterFind() } } } @@ -737,7 +835,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // définissez des valeurs par défaut + // définissez des valeurs par défaut solides if(!$self->created_date) { $self->created_date = gmdate('Y-m-d'); } @@ -751,7 +849,7 @@ class User extends flight\ActiveRecord { #### `afterInsert(ActiveRecord $ActiveRecord)` -Peut-être que vous avez un cas d'utilisation pour changer des données après leur insertion ? +Peut-être que vous avez un cas d'utilisation pour changer des données après leur insertion ? ```php class User extends flight\ActiveRecord { @@ -762,16 +860,16 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // vous faites comme bon vous semble + // faites ce que vous voulez Flight::cache()->set('most_recent_insert_id', $self->id); - // ou quoi que ce soit d'autre.... + // ou quoi que ce soit.... } } ``` #### `beforeUpdate(ActiveRecord $ActiveRecord)` -Vraiment utile si vous avez besoin de définir des valeurs par défaut chaque fois qu'une mise à jour a lieu. +Vraiment utile si vous avez besoin de définir des valeurs par défaut à chaque mise à jour. ```php class User extends flight\ActiveRecord { @@ -782,7 +880,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // définir des valeurs par défaut + // définissez des valeurs par défaut solides if(!$self->updated_date) { $self->updated_date = gmdate('Y-m-d'); } @@ -792,7 +890,7 @@ class User extends flight\ActiveRecord { #### `afterUpdate(ActiveRecord $ActiveRecord)` -Peut-être que vous avez un cas d'utilisation pour changer des données après qu'elles aient été mises à jour ? +Peut-être que vous avez un cas d'utilisation pour changer des données après leur mise à jour ? ```php class User extends flight\ActiveRecord { @@ -803,16 +901,16 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // vous faites comme bon vous semble + // faites ce que vous voulez Flight::cache()->set('most_recently_updated_user_id', $self->id); - // ou quoi que ce soit d'autre.... + // ou quoi que ce soit.... } } ``` #### `beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)` -Ceci est utile si vous souhaitez que des événements se produisent lorsque des insertions ou des mises à jour ont lieu. Je vous épargne une longue explication, mais je suis sûr que vous pouvez deviner ce que c'est. +Ceci est utile si vous voulez que des événements se produisent à la fois lors des insertions ou des mises à jour. Je vais vous épargner la longue explication, mais je suis sûr que vous pouvez deviner ce que c'est. ```php class User extends flight\ActiveRecord { @@ -830,7 +928,7 @@ class User extends flight\ActiveRecord { #### `beforeDelete(ActiveRecord $ActiveRecord)/afterDelete(ActiveRecord $ActiveRecord)` -Je ne suis pas sûr de ce que vous voudriez faire ici, mais pas de jugement ! Foncez ! +Pas sûr de ce que vous voudriez faire ici, mais pas de jugement ici ! Allez-y ! ```php class User extends flight\ActiveRecord { @@ -841,17 +939,17 @@ class User extends flight\ActiveRecord { } protected function beforeDelete(self $self) { - echo 'Il était un brave soldat... :cry-face:'; + echo 'He was a brave soldier... :cry-face:'; } } ``` -## Gestion des Connexions à la Base de Données +## Gestion des connexions à la base de données -Lorsque vous utilisez cette bibliothèque, vous pouvez définir la connexion à la base de données de plusieurs manières. Vous pouvez définir la connexion dans le constructeur, vous pouvez la définir via une variable de configuration `$config['connection']` ou vous pouvez la définir via `setDatabaseConnection()` (v0.4.1). +Lorsque vous utilisez cette bibliothèque, vous pouvez définir la connexion à la base de données de plusieurs façons différentes. Vous pouvez la définir dans le constructeur, vous pouvez la définir via une variable de configuration `$config['connection']` ou vous pouvez la définir via `setDatabaseConnection()` (v0.4.1). ```php -$pdo_connection = new PDO('sqlite:test.db'); // par exemple +$pdo_connection = new PDO('sqlite:test.db'); // pour exemple $user = new User($pdo_connection); // ou $user = new User(null, [ 'connection' => $pdo_connection ]); @@ -860,11 +958,11 @@ $user = new User(); $user->setDatabaseConnection($pdo_connection); ``` -Si vous souhaitez éviter de toujours définir un `$database_connection` chaque fois que vous appelez un enregistrement actif, il existe des moyens d'y parvenir ! +Si vous voulez éviter de toujours définir une `$database_connection` à chaque fois que vous appelez un active record, il y a des moyens d'y remédier ! ```php // index.php ou bootstrap.php -// Réglez cela en tant que classe enregistrée dans Flight +// Définissez ceci comme une classe enregistrée dans Flight Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php @@ -877,24 +975,23 @@ class User extends flight\ActiveRecord { } } -// Et maintenant, aucun argument requis ! +// Et maintenant, pas d'arguments requis ! $user = new User(); ``` -> **Remarque :** Si vous prévoyez des tests unitaires, faire de cette façon peut ajouter quelques défis aux tests unitaires, mais globalement parce que vous pouvez injecter votre -connexion avec `setDatabaseConnection()` ou `$config['connection']`, cela n'est pas trop mauvais. +> **Note :** Si vous prévoyez de faire des tests unitaires, le faire de cette façon peut ajouter quelques défis aux tests unitaires, mais globalement, parce que vous pouvez injecter votre connexion avec `setDatabaseConnection()` ou `$config['connection']`, ce n'est pas trop mal. -Si vous devez rafraîchir la connexion à la base de données, par exemple si vous exécutez un script CLI longue durée et devez rafraîchir la connexion de temps en temps, vous pouvez réinitialiser la connexion avec `$your_record->setDatabaseConnection($pdo_connection)`. +Si vous avez besoin de rafraîchir la connexion à la base de données, par exemple si vous exécutez un script CLI de longue durée et avez besoin de rafraîchir la connexion de temps en temps, vous pouvez la redéfinir avec `$your_record->setDatabaseConnection($pdo_connection)`. -## Contribuer +## Contribution -S'il vous plaît le faire. :D +S'il vous plaît, faites-le. :D ### Configuration -Lorsque vous contribuez, assurez-vous d'exécuter `composer test-coverage` pour maintenir une couverture de test de 100 % (ceci n'est pas une véritable couverture de test unitaire, plus comme un test d'intégration). +Lorsque vous contribuez, assurez-vous d'exécuter `composer test-coverage` pour maintenir une couverture de test à 100 % (ceci n'est pas une vraie couverture de test unitaire, plus comme des tests d'intégration). -Assurez-vous également d'exécuter `composer beautify` et `composer phpcs` pour corriger les erreurs de linting. +Assurez-vous aussi d'exécuter `composer beautify` et `composer phpcs` pour corriger les erreurs de linting. ## Licence diff --git a/content/v3/fr/awesome-plugins/apm.md b/content/v3/fr/awesome-plugins/apm.md index df1da64c..e133f0e0 100644 --- a/content/v3/fr/awesome-plugins/apm.md +++ b/content/v3/fr/awesome-plugins/apm.md @@ -1,14 +1,14 @@ # Documentation FlightPHP APM -Bienvenue dans FlightPHP APM—votre coach personnel de performance pour votre application ! Ce guide est votre feuille de route pour configurer, utiliser et maîtriser la Surveillance de la Performance des Applications (APM) avec FlightPHP. Que vous traquiez des requêtes lentes ou que vous souhaitiez simplement vous enthousiasmer pour des graphiques de latence, nous avons tout ce qu'il vous faut. Rendons votre application plus rapide, vos utilisateurs plus heureux, et vos sessions de débogage plus fluides ! +Bienvenue dans FlightPHP APM — votre coach personnel de performance pour votre application ! Ce guide est votre feuille de route pour configurer, utiliser et maîtriser la Surveillance de Performance des Applications (APM) avec FlightPHP. Que vous traquiez des requêtes lentes ou que vous souhaitiez simplement vous enthousiasmer pour des graphiques de latence, nous avons tout ce qu'il vous faut. Rendons votre application plus rapide, vos utilisateurs plus heureux, et vos sessions de débogage plus faciles ! -Découvrez une [démo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) du tableau de bord pour le site Flight Docs. +Découvrez un [démonstration](https://flightphp-docs-apm.sky-9.com/apm/dashboard) du tableau de bord pour le site Flight Docs. ![FlightPHP APM](/images/apm.png) ## Pourquoi l'APM est important -Imaginez ceci : votre application est un restaurant animé. Sans moyen de suivre la durée des commandes ou les endroits où la cuisine ralentit, vous devinez pourquoi les clients partent mécontents. L'APM est votre sous-chef—il surveille chaque étape, des requêtes entrantes aux requêtes de base de données, et signale tout ce qui vous ralentit. Les pages lentes font fuir les utilisateurs (des études disent que 53 % rebondissent si un site prend plus de 3 secondes à charger !), et l'APM vous aide à attraper ces problèmes *avant* qu'ils ne piquent. C'est une tranquillité d'esprit proactive—moins de moments « pourquoi c'est cassé ? », plus de victoires « regardez comme ça tourne bien ! ». +Imaginez ceci : votre application est un restaurant animé. Sans moyen de suivre la durée des commandes ou d'identifier où la cuisine ralentit, vous devinez pourquoi les clients partent mécontents. L'APM est votre sous-chef — il surveille chaque étape, des requêtes entrantes aux requêtes de base de données, et signale tout ce qui vous ralentit. Les pages lentes font perdre des utilisateurs (des études indiquent que 53 % abandonnent si un site prend plus de 3 secondes à charger !), et l'APM vous aide à détecter ces problèmes *avant* qu'ils ne fassent mal. C'est une tranquillité d'esprit proactive — moins de moments « pourquoi cela ne fonctionne pas ? », plus de victoires « regardez comme cela tourne bien ! ». ## Installation @@ -26,8 +26,8 @@ Vous aurez besoin de : FlightPHP APM prend actuellement en charge les bases de données suivantes pour stocker les métriques : -- **SQLite3** : Simple, basée sur fichier, et idéale pour le développement local ou les petites applications. Option par défaut dans la plupart des configurations. -- **MySQL/MariaDB** : Idéale pour les projets plus grands ou les environnements de production où vous avez besoin d'un stockage robuste et évolutif. +- **SQLite3** : Simple, basée sur des fichiers, et idéale pour le développement local ou les petites applications. Option par défaut dans la plupart des configurations. +- **MySQL/MariaDB** : Idéale pour les projets plus grands ou les environnements de production où vous avez besoin d'un stockage robuste et scalable. Vous pouvez choisir le type de base de données lors de l'étape de configuration (voir ci-dessous). Assurez-vous que votre environnement PHP a les extensions nécessaires installées (par exemple, `pdo_sqlite` ou `pdo_mysql`). @@ -37,10 +37,11 @@ Voici votre guide étape par étape vers l'excellence APM : ### 1. Enregistrer l'APM -Ajoutez ceci dans votre `index.php` ou un fichier `services.php` pour commencer le suivi : +Ajoutez ceci dans votre fichier `index.php` ou `services.php` pour commencer le suivi : ```php use flight\apm\logger\LoggerFactory; +use flight\database\PdoWrapper; use flight\Apm; $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); @@ -54,8 +55,8 @@ $Apm->addPdoConnection($pdo); ``` **Que se passe-t-il ici ?** -- `LoggerFactory::create()` récupère votre configuration (plus de détails bientôt) et configure un logger—SQLite par défaut. -- `Apm` est la star—il écoute les événements de Flight (requêtes, routes, erreurs, etc.) et collecte les métriques. +- `LoggerFactory::create()` récupère votre configuration (plus de détails bientôt) et configure un logger — SQLite par défaut. +- `Apm` est la star — il écoute les événements de Flight (requêtes, routes, erreurs, etc.) et collecte les métriques. - `bindEventsToFlightInstance($app)` lie tout à votre application Flight. **Astuce Pro : Échantillonnage** @@ -65,7 +66,7 @@ Si votre application est occupée, logger *chaque* requête pourrait surcharger $Apm = new Apm($ApmLogger, 0.1); // Logue 10 % des requêtes ``` -Cela garde les performances vives tout en vous donnant des données solides. +Cela maintient les performances fluides tout en vous fournissant des données solides. ### 2. Le configurer @@ -75,9 +76,9 @@ Exécutez ceci pour créer votre `.runway-config.json` : php vendor/bin/runway apm:init ``` -**Que fait ceci ?** +**Que fait cela ?** - Lance un assistant qui demande d'où viennent les métriques brutes (source) et où vont les données traitées (destination). -- Par défaut, c'est SQLite—par exemple, `sqlite:/tmp/apm_metrics.sqlite` pour la source, une autre pour la destination. +- Par défaut, c'est SQLite — par exemple, `sqlite:/tmp/apm_metrics.sqlite` pour la source, un autre pour la destination. - Vous obtiendrez une configuration comme : ```json { @@ -90,10 +91,10 @@ php vendor/bin/runway apm:init } ``` -> Ce processus demandera également si vous voulez exécuter les migrations pour cette configuration. Si vous l'installez pour la première fois, la réponse est oui. +> Ce processus vous demandera également si vous voulez exécuter les migrations pour cette configuration. Si c'est la première fois que vous la configurez, la réponse est oui. **Pourquoi deux emplacements ?** -Les métriques brutes s'accumulent vite (pensez à des logs non filtrés). Le worker les traite en une destination structurée pour le tableau de bord. Cela garde les choses en ordre ! +Les métriques brutes s'accumulent rapidement (pensez à des logs non filtrés). Le worker les traite en une destination structurée pour le tableau de bord. Cela garde les choses organisées ! ### 3. Traiter les métriques avec le Worker @@ -108,21 +109,21 @@ php vendor/bin/runway apm:worker - Traite jusqu'à 100 métriques (taille de lot par défaut) dans votre destination. - S'arrête quand c'est fait ou s'il n'y a plus de métriques. -**Le garder en cours** +**Le maintenir en marche** Pour les applications en direct, vous voudrez un traitement continu. Voici vos options : - **Mode Daemon** : ```bash php vendor/bin/runway apm:worker --daemon ``` - Tourne indéfiniment, traitant les métriques au fur et à mesure. Idéal pour le dev ou les petites configurations. + Tourne indéfiniment, traitant les métriques au fur et à mesure. Idéal pour le développement ou les petites configurations. - **Crontab** : Ajoutez ceci à votre crontab (`crontab -e`) : ```bash * * * * * php /path/to/project/vendor/bin/runway apm:worker ``` - S'exécute toutes les minutes—parfait pour la production. + S'exécute toutes les minutes — parfait pour la production. - **Tmux/Screen** : Démarrez une session détachable : @@ -131,7 +132,7 @@ Pour les applications en direct, vous voudrez un traitement continu. Voici vos o php vendor/bin/runway apm:worker --daemon # Ctrl+B, puis D pour détacher ; `tmux attach -t apm-worker` pour se reconnecter ``` - Le garde en cours même si vous vous déconnectez. + Le maintient en marche même si vous vous déconnectez. - **Ajustements personnalisés** : ```bash @@ -153,8 +154,8 @@ php vendor/bin/runway apm:dashboard ``` **Qu'est-ce que c'est ?** -- Lance un serveur PHP à `http://localhost:8001/apm/dashboard`. -- Affiche les logs de requêtes, les routes lentes, les taux d'erreur, et plus. +- Lance un serveur PHP sur `http://localhost:8001/apm/dashboard`. +- Affiche les logs de requêtes, les routes lentes, les taux d'erreurs, et plus encore. **Le personnaliser** : ```bash @@ -164,38 +165,38 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l - `--port 8080` : Utilisez un port différent si 8001 est pris. - `--php-path` : Pointez vers PHP s'il n'est pas dans votre PATH. -Ouvrez l'URL dans votre navigateur et explorez ! +Accédez à l'URL dans votre navigateur et explorez ! #### Mode Production -Pour la production, vous devrez peut-être essayer quelques techniques pour faire tourner le tableau de bord, car il y a probablement des pare-feu et d'autres mesures de sécurité en place. Voici quelques options : +Pour la production, vous devrez peut-être essayer quelques techniques pour faire fonctionner le tableau de bord, car il y a probablement des pare-feu et d'autres mesures de sécurité en place. Voici quelques options : -- **Utiliser un Reverse Proxy** : Configurez Nginx ou Apache pour rediriger les requêtes vers le tableau de bord. +- **Utiliser un Reverse Proxy** : Configurez Nginx ou Apache pour transférer les requêtes vers le tableau de bord. - **Tunnel SSH** : Si vous pouvez vous connecter en SSH au serveur, utilisez `ssh -L 8080:localhost:8001 youruser@yourserver` pour tunneler le tableau de bord vers votre machine locale. - **VPN** : Si votre serveur est derrière un VPN, connectez-vous-y et accédez directement au tableau de bord. - **Configurer le Pare-feu** : Ouvrez le port 8001 pour votre IP ou le réseau du serveur. (ou quel que soit le port que vous avez défini). -- **Configurer Apache/Nginx** : Si vous avez un serveur web devant votre application, vous pouvez le configurer pour un domaine ou un sous-domaine. Si vous faites cela, vous définirez la racine des documents à `/path/to/your/project/vendor/flightphp/apm/dashboard` +- **Configurer Apache/Nginx** : Si vous avez un serveur web devant votre application, vous pouvez le configurer pour un domaine ou un sous-domaine. Si vous faites cela, vous définirez la racine des documents sur `/path/to/your/project/vendor/flightphp/apm/dashboard` -#### Voulez-vous un tableau de bord différent ? +#### Voulez un tableau de bord différent ? Vous pouvez construire votre propre tableau de bord si vous le souhaitez ! Regardez le répertoire vendor/flightphp/apm/src/apm/presenter pour des idées sur la façon de présenter les données pour votre propre tableau de bord ! ## Fonctionnalités du Tableau de Bord -Le tableau de bord est votre quartier général APM—voici ce que vous verrez : +Le tableau de bord est votre QG APM — voici ce que vous verrez : -- **Log des Requêtes** : Chaque requête avec horodatage, URL, code de réponse, et temps total. Cliquez sur « Détails » pour les middlewares, requêtes, et erreurs. +- **Journal des Requêtes** : Chaque requête avec horodatage, URL, code de réponse, et temps total. Cliquez sur « Détails » pour les middlewares, requêtes, et erreurs. - **Requêtes les Plus Lentes** : Top 5 des requêtes qui monopolisent le temps (par exemple, « /api/heavy » à 2,5 s). -- **Routes les Plus Lentes** : Top 5 des routes par temps moyen—idéal pour repérer les patterns. -- **Taux d'Erreur** : Pourcentage de requêtes qui échouent (par exemple, 2,3 % de 500). -- **Percentiles de Latence** : 95e (p95) et 99e (p99) temps de réponse—connaissez vos scénarios pires cas. +- **Routes les Plus Lentes** : Top 5 des routes par temps moyen — idéal pour repérer les patterns. +- **Taux d'Erreurs** : Pourcentage de requêtes qui échouent (par exemple, 2,3 % de 500). +- **Percentiles de Latence** : 95e (p95) et 99e (p99) temps de réponse — connaissez vos scénarios dans le pire des cas. - **Graphique des Codes de Réponse** : Visualisez les 200, 404, 500 au fil du temps. - **Requêtes/Middlewares Longs** : Top 5 des appels de base de données lents et des couches de middleware. - **Taux de Cache Hit/Miss** : À quelle fréquence votre cache sauve la mise. **Extras** : - Filtrez par « Dernière Heure », « Dernier Jour », ou « Dernière Semaine ». -- Basculez en mode sombre pour ces sessions tardives. +- Activez le mode sombre pour ces sessions tardives. **Exemple** : Une requête vers `/users` pourrait montrer : @@ -204,9 +205,9 @@ Une requête vers `/users` pourrait montrer : - Requête : `SELECT * FROM users` (80 ms) - Cache : Hit sur `user_list` (5 ms) -## Ajout d'Événements Personnalisés +## Ajouter des Événements Personnalisés -Suivez n'importe quoi—comme un appel API ou un processus de paiement : +Suivez n'importe quoi — comme un appel API ou un processus de paiement : ```php use flight\apm\CustomEvent; @@ -218,8 +219,8 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ])); ``` -**Où apparaît-il ?** -Dans les détails de requête du tableau de bord sous « Événements Personnalisés »—extensible avec un formatage JSON joli. +**Où cela apparaît-il ?** +Dans les détails de requête du tableau de bord sous « Événements Personnalisés » — extensible avec un formatage JSON élégant. **Cas d'Utilisation** : ```php @@ -250,8 +251,8 @@ $Apm->addPdoConnection($pdo); - Nombre de lignes (par exemple, 42) **Attention** : -- **Optionnel** : Sautez ceci si vous n'avez pas besoin de suivi DB. -- **PdoWrapper Seulement** : Le PDO de base n'est pas encore accroché—restez à l'écoute ! +- **Optionnel** : Ignorez cela si vous n'avez pas besoin de suivi DB. +- **PdoWrapper Seulement** : Le PDO de base n'est pas encore connecté — restez à l'écoute ! - **Avertissement de Performance** : Logger chaque requête sur un site lourd en DB peut ralentir les choses. Utilisez l'échantillonnage (`$Apm = new Apm($ApmLogger, 0.1)`) pour alléger la charge. **Exemple de Sortie** : @@ -263,10 +264,10 @@ $Apm->addPdoConnection($pdo); Ajustez le worker à votre goût : -- `--timeout 300` : S'arrête après 5 minutes—bon pour les tests. -- `--max_messages 500` : Limite à 500 métriques—le garde fini. -- `--batch_size 200` : Traite 200 à la fois—équilibre vitesse et mémoire. -- `--daemon` : Tourne non-stop—idéal pour la surveillance en direct. +- `--timeout 300` : S'arrête après 5 minutes — bon pour les tests. +- `--max_messages 500` : Limite à 500 métriques — le garde fini. +- `--batch_size 200` : Traite 200 à la fois — équilibre vitesse et mémoire. +- `--daemon` : Tourne sans arrêt — idéal pour la surveillance en direct. **Exemple** : ```bash @@ -280,11 +281,11 @@ Chaque requête a un ID de requête unique pour le suivi. Vous pouvez utiliser c ```php Flight::map('error', function($message) { - // Obtenez l'ID de requête depuis l'en-tête de réponse X-Flight-Request-Id + // Récupérez l'ID de requête depuis l'en-tête de réponse X-Flight-Request-Id $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); // De plus, vous pourriez le récupérer depuis la variable Flight - // Cette méthode ne fonctionnera pas bien sur swoole ou d'autres plateformes asynchrones. + // Cette méthode ne fonctionnera pas bien sur Swoole ou d'autres plateformes asynchrones. // $requestId = Flight::get('apm.request_id'); echo "Erreur : $message (ID de Requête : $requestId)"; @@ -298,32 +299,42 @@ Si vous mettez à niveau vers une version plus récente de l'APM, il est possibl ```bash php vendor/bin/runway apm:migrate ``` -Ceci exécutera toutes les migrations nécessaires pour mettre à jour le schéma de la base de données vers la dernière version. +Cela exécutera toutes les migrations nécessaires pour mettre à jour le schéma de la base de données vers la dernière version. + +**Note :** Si votre base de données APM est volumineuse, ces migrations peuvent prendre du temps. Vous pourriez vouloir exécuter cette commande pendant les heures creuses. + +### Mise à Niveau de 0.4.3 -> 0.5.0 + +Si vous mettez à niveau de 0.4.3 vers 0.5.0, vous devrez exécuter la commande suivante : + +```bash +php vendor/bin/runway apm:config-migrate +``` -**Note :** Si votre base de données APM est grande en taille, ces migrations pourraient prendre un certain temps à s'exécuter. Vous pourriez vouloir exécuter cette commande pendant les heures creuses. +Cela migrera votre configuration de l'ancien format utilisant le fichier `.runway-config.json` vers le nouveau format qui stocke les clés/valeurs dans le fichier `config.php`. ## Purgage des Anciennes Données -Pour garder votre base de données en ordre, vous pouvez purger les anciennes données. C'est particulièrement utile si vous exécutez une application occupée et que vous voulez garder la taille de la base de données gérable. +Pour garder votre base de données propre, vous pouvez purger les anciennes données. C'est particulièrement utile si vous exécutez une application occupée et voulez garder la taille de la base de données gérable. Vous pouvez le faire en exécutant la commande suivante : ```bash php vendor/bin/runway apm:purge ``` -Ceci supprimera toutes les données plus anciennes que 30 jours de la base de données. Vous pouvez ajuster le nombre de jours en passant une valeur différente à l'option `--days` : +Cela supprimera toutes les données plus anciennes que 30 jours de la base de données. Vous pouvez ajuster le nombre de jours en passant une valeur différente à l'option `--days` : ```bash php vendor/bin/runway apm:purge --days 7 ``` -Ceci supprimera toutes les données plus anciennes que 7 jours de la base de données. +Cela supprimera toutes les données plus anciennes que 7 jours de la base de données. ## Dépannage -Coincé ? Essayez ceci : +Bloqué ? Essayez ceci : - **Pas de Données dans le Tableau de Bord ?** - Le worker tourne-t-il ? Vérifiez `ps aux | grep apm:worker`. - - Les chemins de configuration correspondent-ils ? Vérifiez que les DSN dans `.runway-config.json` pointent vers des fichiers réels. + - Les chemins de configuration correspondent-ils ? Vérifiez que les DSN de `.runway-config.json` pointent vers de vrais fichiers. - Exécutez `php vendor/bin/runway apm:worker` manuellement pour traiter les métriques en attente. - **Erreurs du Worker ?** @@ -331,7 +342,7 @@ Coincé ? Essayez ceci : - Vérifiez les logs PHP pour les traces de pile. - **Le Tableau de Bord Ne Démarre Pas ?** - - Port 8001 utilisé ? Utilisez `--port 8080`. + - Port 8001 en cours d'utilisation ? Utilisez `--port 8080`. - PHP non trouvé ? Utilisez `--php-path /usr/bin/php`. - Pare-feu bloquant ? Ouvrez le port ou utilisez `--host localhost`. @@ -340,8 +351,8 @@ Coincé ? Essayez ceci : - Réduisez la taille du lot : `--batch_size 20`. - **Pas de Suivi des Exceptions/Erreurs ?** - - Si vous avez [Tracy](https://tracy.nette.org/) activé pour votre projet, il remplacera la gestion d'erreurs de Flight. Vous devrez désactiver Tracy et vous assurer que `Flight::set('flight.handle_errors', true);` est défini. + - Si vous avez [Tracy](https://tracy.nette.org/) activé pour votre projet, il remplacera la gestion des erreurs de Flight. Vous devrez désactiver Tracy et vous assurer que `Flight::set('flight.handle_errors', true);` est défini. - **Pas de Suivi des Requêtes de Base de Données ?** - Assurez-vous d'utiliser `PdoWrapper` pour vos connexions à la base de données. - - Assurez-vous de passer `true` comme dernier argument dans le constructeur. \ No newline at end of file + - Assurez-vous de définir le dernier argument dans le constructeur à `true`. \ No newline at end of file diff --git a/content/v3/fr/awesome-plugins/awesome_plugins.md b/content/v3/fr/awesome-plugins/awesome_plugins.md index 2bf4f82e..c82b0d49 100644 --- a/content/v3/fr/awesome-plugins/awesome_plugins.md +++ b/content/v3/fr/awesome-plugins/awesome_plugins.md @@ -2,21 +2,21 @@ Flight est incroyablement extensible. Il existe un certain nombre de plugins qui peuvent être utilisés pour ajouter des fonctionnalités à votre application Flight. Certains sont officiellement pris en charge par l'équipe Flight et d'autres sont des bibliothèques micro/lite pour vous aider à démarrer. -## Documentation API +## Documentation de l'API -La documentation API est cruciale pour toute API. Elle aide les développeurs à comprendre comment interagir avec votre API et ce qu'ils peuvent attendre en retour. Il existe quelques outils disponibles pour vous aider à générer la documentation API pour vos projets Flight. +La documentation de l'API est cruciale pour toute API. Elle aide les développeurs à comprendre comment interagir avec votre API et ce qu'ils peuvent attendre en retour. Il existe quelques outils disponibles pour vous aider à générer la documentation de l'API pour vos projets Flight. - [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Article de blog écrit par Daniel Schreiber sur la façon d'utiliser la spécification OpenAPI avec FlightPHP pour construire votre API en adoptant une approche API-first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI est un excellent outil pour vous aider à générer la documentation API pour vos projets Flight. Il est très facile à utiliser et peut être personnalisé selon vos besoins. Il s'agit de la bibliothèque PHP pour vous aider à générer la documentation Swagger. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI est un excellent outil pour vous aider à générer la documentation de l'API pour vos projets Flight. Il est très facile à utiliser et peut être personnalisé pour répondre à vos besoins. Il s'agit de la bibliothèque PHP pour vous aider à générer la documentation Swagger. ## Surveillance des Performances des Applications (APM) -La surveillance des performances des applications (APM) est cruciale pour toute application. Elle vous aide à comprendre comment votre application se comporte et où se trouvent les goulots d'étranglement. Il existe un certain nombre d'outils APM qui peuvent être utilisés avec Flight. +La surveillance des performances des applications (APM) est cruciale pour toute application. Elle vous aide à comprendre comment votre application performe et où se trouvent les goulots d'étranglement. Il existe un certain nombre d'outils APM qui peuvent être utilisés avec Flight. - officiel [flightphp/apm](/awesome-plugins/apm) - Flight APM est une bibliothèque APM simple qui peut être utilisée pour surveiller vos applications Flight. Elle peut être utilisée pour surveiller les performances de votre application et vous aider à identifier les goulots d'étranglement. ## Asynchrone -Flight est déjà un framework rapide, mais lui ajouter un moteur turbo rend tout plus amusant (et plus stimulant) ! +Flight est déjà un framework rapide, mais lui ajouter un turbo le rend encore plus amusant (et stimulant) ! - [flightphp/async](/awesome-plugins/async) - Bibliothèque officielle Flight Async. Cette bibliothèque est une façon simple d'ajouter un traitement asynchrone à votre application. Elle utilise Swoole/Openswoole en arrière-plan pour fournir une façon simple et efficace d'exécuter des tâches de manière asynchrone. @@ -30,7 +30,7 @@ L'autorisation et les permissions sont cruciales pour toute application qui néc La mise en cache est un excellent moyen d'accélérer votre application. Il existe un certain nombre de bibliothèques de mise en cache qui peuvent être utilisées avec Flight. -- officiel [flightphp/cache](/awesome-plugins/php-file-cache) - Classe de mise en cache PHP légère, simple et autonome en fichier +- officiel [flightphp/cache](/awesome-plugins/php-file-cache) - Classe PHP légère, simple et autonome pour la mise en cache en fichier ## CLI @@ -53,30 +53,30 @@ Le débogage est crucial lorsque vous développez dans votre environnement local ## Bases de Données -Les bases de données sont au cœur de la plupart des applications. C'est ainsi que vous stockez et récupérez les données. Certaines bibliothèques de bases de données sont simplement des wrappers pour écrire des requêtes et d'autres sont des ORMs complets. +Les bases de données sont au cœur de la plupart des applications. C'est ainsi que vous stockez et récupérez les données. Certaines bibliothèques de base de données sont simplement des wrappers pour écrire des requêtes et d'autres sont des ORMs complets. - officiel [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO officiel Flight qui fait partie du cœur. Il s'agit d'un wrapper simple pour aider à simplifier le processus d'écriture et d'exécution des requêtes. Ce n'est pas un ORM. -- officiel [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord officiel Flight. Excellente petite bibliothèque pour récupérer et stocker facilement les données dans votre base de données. +- officiel [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord officiel Flight. Excellente petite bibliothèque pour récupérer et stocker facilement des données dans votre base de données. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin pour suivre toutes les modifications de base de données pour votre projet. ## Chiffrement Le chiffrement est crucial pour toute application qui stocke des données sensibles. Chiffrer et déchiffrer les données n'est pas terriblement difficile, mais stocker correctement la clé de chiffrement [peut](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [être](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difficile](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). La chose la plus importante est de ne jamais stocker votre clé de chiffrement dans un répertoire public ou de l'engager dans votre dépôt de code. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Il s'agit d'une bibliothèque qui peut être utilisée pour chiffrer et déchiffrer les données. Se mettre en route est assez simple pour commencer à chiffrer et déchiffrer les données. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - Il s'agit d'une bibliothèque qui peut être utilisée pour chiffrer et déchiffrer des données. Se lancer est assez simple pour commencer à chiffrer et déchiffrer des données. ## File d'Attente de Tâches Les files d'attente de tâches sont vraiment utiles pour traiter les tâches de manière asynchrone. Cela peut être l'envoi d'emails, le traitement d'images, ou tout ce qui n'a pas besoin d'être fait en temps réel. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue est une bibliothèque qui peut être utilisée pour traiter les tâches de manière asynchrone. Elle peut être utilisée avec beanstalkd, MySQL/MariaDB, SQLite et PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue est une bibliothèque qui peut être utilisée pour traiter les tâches de manière asynchrone. Elle peut être utilisée avec beanstalkd, MySQL/MariaDB, SQLite, et PostgreSQL. ## Session Les sessions ne sont pas vraiment utiles pour les API, mais pour construire une application web, les sessions peuvent être cruciales pour maintenir l'état et les informations de connexion. - officiel [flightphp/session](/awesome-plugins/session) - Bibliothèque officielle Flight Session. Il s'agit d'une bibliothèque de session simple qui peut être utilisée pour stocker et récupérer les données de session. Elle utilise la gestion de session intégrée de PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - Gestionnaire de sessions PHP (non-bloquant, flash, segment, chiffrement de session). Utilise PHP open_ssl pour le chiffrement/déchiffrement optionnel des données de session. +- [Ghostff/Session](/awesome-plugins/ghost-session) - Gestionnaire de Sessions PHP (non-bloquant, flash, segment, chiffrement de session). Utilise PHP open_ssl pour le chiffrement/déchiffrement optionnel des données de session. ## Modélisation @@ -84,13 +84,13 @@ La modélisation est au cœur de toute application web avec une interface utilis - déprécié [flightphp/core View](/learn#views) - Il s'agit d'un moteur de modélisation très basique qui fait partie du cœur. Il n'est pas recommandé de l'utiliser si vous avez plus de quelques pages dans votre projet. - [latte/latte](/awesome-plugins/latte) - Latte est un moteur de modélisation complet qui est très facile à utiliser et qui ressemble plus à une syntaxe PHP que Twig ou Smarty. Il est également très facile à étendre et à ajouter vos propres filtres et fonctions. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate est un puissant moteur de templates PHP avec compilation d'actifs, héritage de templates et traitement de variables. Fonctionnalités : minification automatique CSS/JS, mise en cache, encodage Base64 et intégration optionnelle avec le framework PHP Flight. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate est un puissant moteur de templates PHP avec compilation d'actifs, héritage de templates, et traitement de variables. Fonctionnalités : minification automatique CSS/JS, mise en cache, encodage Base64, et intégration optionnelle avec le framework PHP Flight. ## Intégration WordPress -Vous voulez utiliser Flight dans votre projet WordPress ? Il y a un plugin pratique pour cela ! +Vous souhaitez utiliser Flight dans votre projet WordPress ? Il existe un plugin pratique pour cela ! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Ce plugin WordPress vous permet d'exécuter Flight directement aux côtés de WordPress. C'est parfait pour ajouter des API personnalisées, des microservices, ou même des applications complètes à votre site WordPress en utilisant le framework Flight. Super utile si vous voulez le meilleur des deux mondes ! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Ce plugin WordPress vous permet d'exécuter Flight directement aux côtés de WordPress. Il est parfait pour ajouter des API personnalisées, des microservices, ou même des applications complètes à votre site WordPress en utilisant le framework Flight. Super utile si vous voulez le meilleur des deux mondes ! ## Contribution diff --git a/content/v3/fr/awesome-plugins/comment_template.md b/content/v3/fr/awesome-plugins/comment_template.md index 0a26bb97..b0c41598 100644 --- a/content/v3/fr/awesome-plugins/comment_template.md +++ b/content/v3/fr/awesome-plugins/comment_template.md @@ -1,12 +1,12 @@ # CommentTemplate -[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) est un puissant moteur de templates PHP avec compilation d'actifs, héritage de templates et traitement des variables. Il fournit une façon simple mais flexible de gérer les templates avec une minification CSS/JS intégrée et un cache. +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) est un puissant moteur de templates PHP avec compilation d'actifs, héritage de templates et traitement de variables. Il fournit une façon simple mais flexible de gérer les templates avec une minification CSS/JS intégrée et un cache. ## Fonctionnalités - **Héritage de Templates** : Utilisez des layouts et incluez d'autres templates -- **Compilation d'Actifs** : Minification et cache automatique CSS/JS -- **Traitement des Variables** : Variables de template avec filtres et commandes +- **Compilation d'Actifs** : Minification automatique CSS/JS et cache +- **Traitement de Variables** : Variables de template avec filtres et commandes - **Encodage Base64** : Actifs en ligne sous forme d'URI de données - **Intégration avec le Framework Flight** : Intégration optionnelle avec le framework PHP Flight @@ -20,9 +20,9 @@ composer require knifelemon/comment-template ## Configuration de Base -Il existe quelques options de configuration de base pour commencer. Vous pouvez en lire plus à leur sujet dans le [Repo CommentTemplate](https://github.com/KnifeLemon/CommentTemplate). +Il existe quelques options de configuration de base pour commencer. Vous pouvez en lire plus à ce sujet dans le [Repo CommentTemplate](https://github.com/KnifeLemon/CommentTemplate). -### Méthode 1 : Utilisation d'une Fonction de Callback +### Méthode 1 : Utilisation d'une Fonction de Rappel ```php register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Répertoire racine (où se trouve index.php) - la racine du document de votre application web + // Répertoire racine (où se trouve index.php) - la racine des documents de votre application web $engine->setPublicPath(__DIR__); // Répertoire des fichiers de templates - supporte les chemins relatifs et absolus @@ -42,7 +42,7 @@ $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { // Où les actifs compilés seront stockés - supporte les chemins relatifs et absolus $engine->setAssetPath('assets'); // Relatif au chemin public - // Extension des fichiers de template + // Extension des fichiers de templates $engine->setFileExtension('.php'); }); @@ -66,7 +66,7 @@ $app->register('view', Engine::class, [ __DIR__, // publicPath - répertoire racine (où se trouve index.php) 'views', // skinPath - chemin des templates (supporte relatif/absolu) 'assets', // assetPath - chemin des actifs compilés (supporte relatif/absolu) - '.php' // fileExtension - extension des fichiers de template + '.php' // fileExtension - extension des fichiers de templates ]); $app->map('render', function(string $template, array $data) use ($app): void { @@ -76,11 +76,11 @@ $app->map('render', function(string $template, array $data) use ($app): void { ## Configuration des Chemins -CommentTemplate offre une gestion intelligente des chemins pour les chemins relatifs et absolus : +CommentTemplate fournit une gestion intelligente des chemins pour les chemins relatifs et absolus : ### Chemin Public -Le **Chemin Public** est le répertoire racine de votre application web, généralement où se trouve `index.php`. C'est la racine du document que les serveurs web utilisent pour servir les fichiers. +Le **Chemin Public** est le répertoire racine de votre application web, typiquement où réside `index.php`. C'est la racine des documents à partir de laquelle les serveurs web servent les fichiers. ```php // Exemple : si votre index.php est à /var/www/html/myapp/index.php @@ -102,7 +102,7 @@ $template->setPublicPath('/var/www/html/myapp'); // Répertoire racine (où se $template->setSkinPath('views'); // → /var/www/html/myapp/views/ $template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ -// Chemins absolus - utilisés tel quel (Unix/Linux) +// Chemins absolus - utilisés tels quels (Unix/Linux) $template->setSkinPath('/var/www/templates'); // → /var/www/templates/ $template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ @@ -116,14 +116,14 @@ $template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\te ### Configuration du Chemin des Actifs -Le chemin des actifs supporte aussi les chemins relatifs et absolus : +Le chemin des actifs supporte également les chemins relatifs et absolus : ```php // Chemins relatifs - automatiquement combinés avec le chemin public $template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ $template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ -// Chemins absolus - utilisés tel quel (Unix/Linux) +// Chemins absolus - utilisés tels quels (Unix/Linux) $template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ $template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ @@ -137,19 +137,19 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse **Détection Intelligente des Chemins :** -- **Chemins Relatifs** : Pas de séparateurs de début (`/`, `\`) ou de lettres de lecteur -- **Unix Absolu** : Commence par `/` (ex : `/var/www/assets`) -- **Windows Absolu** : Commence par une lettre de lecteur (ex : `C:\www`, `D:/assets`) -- **Chemins UNC** : Commence par `\\` (ex : `\\server\share`) +- **Chemins Relatifs** : Pas de séparateurs initiaux (`/`, `\`) ou lettres de lecteur +- **Absolus Unix** : Commence par `/` (ex. : `/var/www/assets`) +- **Absolus Windows** : Commence par une lettre de lecteur (ex. : `C:\www`, `D:/assets`) +- **Chemins UNC** : Commence par `\\` (ex. : `\\server\share`) -**Comment ça fonctionne :** +**Comment ça marche :** -- Tous les chemins sont automatiquement résolus selon le type (relatif vs absolu) +- Tous les chemins sont automatiquement résolus en fonction du type (relatif vs absolu) - Les chemins relatifs sont combinés avec le chemin public - `@css` et `@js` créent des fichiers minifiés dans : `{resolvedAssetPath}/css/` ou `{resolvedAssetPath}/js/` - `@asset` copie les fichiers uniques vers : `{resolvedAssetPath}/{relativePath}` - `@assetDir` copie les répertoires vers : `{resolvedAssetPath}/{relativePath}` -- Cache intelligent : les fichiers ne sont copiés que lorsque la source est plus récente que la destination +- Cache intelligent : les fichiers ne sont copiés que si la source est plus récente que la destination ## Directives de Template @@ -157,7 +157,7 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse Utilisez des layouts pour créer une structure commune : -**layout/global_layout.php** : +**layout/global_layout.php**: ```html @@ -170,7 +170,7 @@ Utilisez des layouts pour créer une structure commune : ``` -**view/page.php** : +**view/page.php**: ```html

          {$title}

          @@ -186,15 +186,15 @@ Utilisez des layouts pour créer une structure commune : ``` #### Fichiers JavaScript -CommentTemplate prend en charge différentes stratégies de chargement JavaScript : +CommentTemplate supporte différentes stratégies de chargement JavaScript : ```html - - - + + + @@ -202,7 +202,7 @@ CommentTemplate prend en charge différentes stratégies de chargement JavaScrip #### Directives d'Actifs dans les Fichiers CSS/JS -CommentTemplate traite également les directives d'actifs au sein des fichiers CSS et JavaScript lors de la compilation : +CommentTemplate traite également les directives d'actifs au sein des fichiers CSS et JavaScript pendant la compilation : **Exemple CSS :** ```css @@ -248,8 +248,8 @@ const imageData = ''; ``` ** Exemple : ** ```html - -Bannière Héroïque + +Hero Banner Télécharger la Brochure @@ -259,7 +259,7 @@ const imageData = ''; ### Inclutions de Templates ```html - + ``` ** Exemple : ** ```html @@ -278,7 +278,7 @@ const imageData = ''; ``` -### Traitement des Variables +### Traitement de Variables #### Variables de Base ```html @@ -292,8 +292,8 @@ const imageData = ''; {$content|lower} {$html|striptag} {$text|escape} -{$multiline|nl2br} -{$html|br2nl} +{$multiline|nl2br} +{$html|br2nl} {$description|trim} {$subject|title} ``` @@ -304,30 +304,30 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### Chaîner Plusieurs Filtres +#### Commandes de Variables ```html {$content|striptag|trim|escape} ``` ### Commentaires -Les commentaires de template sont entièrement supprimés de la sortie et n'apparaissent pas dans le HTML final : +Les commentaires de template sont complètement supprimés de la sortie et n'apparaîtront pas dans le HTML final : ```html {* Ceci est un commentaire de template sur une ligne *} {* - Ceci est un commentaire de template - multi-lignes qui s'étend sur - plusieurs lignes + Ceci est un commentaire de + template sur plusieurs + lignes *}

          {$title}

          -{* Commentaire de débogage : vérifie si la variable title fonctionne *} +{* Commentaire de débogage : vérification si la variable title fonctionne *}

          {$content}

          ``` -**Note** : Les commentaires de template `{* ... *}` sont différents des commentaires HTML ``. Les commentaires de template sont supprimés lors du traitement et n'atteignent jamais le navigateur. +**Note** : Les commentaires de template `{* ... *}` sont différents des commentaires HTML ``. Les commentaires de template sont supprimés pendant le traitement et n'atteignent jamais le navigateur. ## Structure de Projet Exemple diff --git a/content/v3/fr/awesome-plugins/runway.md b/content/v3/fr/awesome-plugins/runway.md index 690c03b1..c6df2ca2 100644 --- a/content/v3/fr/awesome-plugins/runway.md +++ b/content/v3/fr/awesome-plugins/runway.md @@ -1,12 +1,12 @@ -# Piste +# Runway -**Runway** est une application CLI qui vous aide à gérer vos applications **Flight**. Il peut générer des contrôleurs, afficher toutes les routes, et bien plus encore. Il est basé sur l'excellente bibliothèque [adhocore/php-cli](https://github.com/adhocore/php-cli). +Runway est une application CLI qui vous aide à gérer vos applications Flight. Elle peut générer des contrôleurs, afficher toutes les routes, et plus encore. Elle est basée sur la bibliothèque excellente [adhocore/php-cli](https://github.com/adhocore/php-cli). Cliquez [ici](https://github.com/flightphp/runway) pour voir le code. ## Installation -Installez avec **composer**. +Installez avec composer. ```bash composer require flightphp/runway @@ -14,16 +14,16 @@ composer require flightphp/runway ## Configuration de Base -La première fois que vous exécutez **Runway**, il vous guidera à travers un processus de configuration et créera un fichier de configuration `.runway.json` à la racine de votre projet. Ce fichier contiendra certaines configurations nécessaires pour que **Runway** fonctionne correctement. +La première fois que vous exécutez Runway, il vous guidera à travers un processus de configuration et créera un fichier de configuration `.runway.json` à la racine de votre projet. Ce fichier contiendra certaines configurations nécessaires pour que Runway fonctionne correctement. ## Utilisation -**Runway** dispose de plusieurs commandes que vous pouvez utiliser pour gérer votre application **Flight**. Il y a deux façons faciles d'utiliser **Runway**. +Runway dispose d'un certain nombre de commandes que vous pouvez utiliser pour gérer votre application Flight. Il existe deux façons faciles d'utiliser Runway. -1. Si vous utilisez le projet de base, vous pouvez exécuter `php runway [commande]` depuis la racine de votre projet. -1. Si vous utilisez **Runway** comme un paquet installé via composer, vous pouvez exécuter `vendor/bin/runway [commande]` depuis la racine de votre projet. +1. Si vous utilisez le projet squelette, vous pouvez exécuter `php runway [commande]` depuis la racine de votre projet. +1. Si vous utilisez Runway en tant que package installé via composer, vous pouvez exécuter `vendor/bin/runway [commande]` depuis la racine de votre projet. -Pour n'importe quelle commande, vous pouvez ajouter le drapeau `--help` pour obtenir plus d'informations sur comment utiliser la commande. +Pour toute commande, vous pouvez passer l'option `--help` pour obtenir plus d'informations sur la façon d'utiliser la commande. ```bash php runway routes --help @@ -33,7 +33,7 @@ Voici quelques exemples : ### Générer un Contrôleur -Selon la configuration dans votre fichier `.runway.json`, l'emplacement par défaut générera un contrôleur pour vous dans le répertoire `app/controllers/`. +En se basant sur la configuration dans votre fichier `.runway.json`, l'emplacement par défaut générera un contrôleur pour vous dans le répertoire `app/controllers/`. ```bash php runway make:controller MyController @@ -41,13 +41,13 @@ php runway make:controller MyController ### Générer un Modèle Active Record -Selon la configuration dans votre fichier `.runway.json`, l'emplacement par défaut générera un contrôleur pour vous dans le répertoire `app/records/`. +En se basant sur la configuration dans votre fichier `.runway.json`, l'emplacement par défaut générera un modèle pour vous dans le répertoire `app/records/`. ```bash php runway make:record users ``` -Par exemple, si vous avez la table `users` avec le schéma suivant : `id`, `name`, `email`, `created_at`, `updated_at`, un fichier similaire au suivant sera créé dans le fichier `app/records/UserRecord.php` : +Si, par exemple, vous avez la table `users` avec le schéma suivant : `id`, `name`, `email`, `created_at`, `updated_at`, un fichier similaire à celui-ci sera créé dans le fichier `app/records/UserRecord.php` : ```php $config Config JSON de .runway-config.json + * @param array $config Configuration JSON de .runway-config.json */ public function __construct(array $config) { - parent::__construct('make:example', 'Crée un exemple pour la documentation', $config); + parent::__construct('make:example', 'Créer un exemple pour la documentation', $config); $this->argument('', 'Le nom du gif drôle'); } @@ -138,7 +138,7 @@ class ExampleCommand extends AbstractBaseCommand * * @return void */ - public function execute(string $controller) + public function execute() { $io = $this->app()->io(); @@ -151,4 +151,43 @@ class ExampleCommand extends AbstractBaseCommand } ``` -Consultez la [Documentation de **adhocore/php-cli**](https://github.com/adhocore/php-cli) pour plus d'informations sur la façon de créer vos propres commandes personnalisées dans votre application **Flight** ! \ No newline at end of file +Consultez la [Documentation adhocore/php-cli](https://github.com/adhocore/php-cli) pour plus d'informations sur la façon de construire vos propres commandes personnalisées dans votre application Flight ! + +### Configuration + +Si vous devez personnaliser la configuration pour Runway, vous pouvez créer un fichier `.runway-config.json` à la racine de votre projet. Voici quelques configurations supplémentaires que vous pouvez définir : + +```js +{ + + // C'est l'endroit où se trouve votre répertoire d'application + "app_root": "app/", + + // C'est le répertoire où se trouve votre fichier index racine + "index_root": "public/", + + // Ce sont les chemins vers les racines d'autres projets + "root_paths": [ + "/home/user/different-project", + "/var/www/another-project" + ], + + // Les chemins de base n'ont probablement pas besoin d'être configurés, mais c'est là si vous en voulez + "base_paths": { + "/includes/libs/vendor", // si vous avez un chemin vraiment unique pour votre répertoire vendor ou autre + }, + + // Les chemins finaux sont des emplacements dans un projet pour rechercher les fichiers de commande + "final_paths": { + "src/diff-path/commands", + "app/module/admin/commands", + }, + + // Si vous voulez simplement ajouter le chemin complet, allez-y (absolu ou relatif à la racine du projet) + "paths": [ + "/home/user/different-project/src/diff-path/commands", + "/var/www/another-project/app/module/admin/commands", + "app/my-unique-commands" + ] +} +``` \ No newline at end of file diff --git a/content/v3/fr/examples.md b/content/v3/fr/examples.md index 21e4a63a..e9cbf05f 100644 --- a/content/v3/fr/examples.md +++ b/content/v3/fr/examples.md @@ -5,7 +5,7 @@ Vous avez deux options pour démarrer un nouveau projet Flight : - [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton) : Un exemple plus complet avec des contrôleurs et des vues. - [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple) : Un fichier unique qui inclut tout ce dont vous avez besoin pour exécuter votre application dans un seul fichier simple. -Exemples contributés par la communauté : +Exemples contribués par la communauté : - [flightravel](https://github.com/fadrian06-templates/flighravel) : FlightPHP avec des répertoires Laravel, avec des outils PHP + GH Actions - [fleact](https://github.com/flightphp/fleact) - Un kit de démarrage FlightPHP avec intégration ReactJS. @@ -16,11 +16,12 @@ Exemples contributés par la communauté : Bien que ces exemples ne soient pas officiellement sponsorisés par l'équipe Flight, ils pourraient vous donner des idées sur la façon de structurer vos propres projets construits avec Flight ! -- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify est une application monopage connectant les organisateurs d'événements avec les participants. Construite avec PHP (FlightPHP), JavaScript et MySQL, elle inclut une authentification JWT, la gestion d'événements et des docs API RESTful utilisant OpenAPI. -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental est une application web monopage, adaptée aux mobiles, pour la location de voitures construite avec PHP (FlightPHP), JavaScript et MySQL. Elle supporte l'inscription des utilisateurs, la navigation et la réservation de voitures, tandis que les admins peuvent gérer les voitures, les utilisateurs et les réservations. L'application inclut une API REST, une authentification JWT et un design responsive pour une expérience de location moderne. -- [Decay](https://github.com/boxybird/decay) - Flight v3 avec HTMX et SleekDB tout sur les zombies ! ([Démo](https://decay.andrewrhyand.com)) -- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 avec Middleware, Contrôleurs, Active Record et Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Projet API CRUD simple utilisant le framework Flight, qui fournit une structure de base pour que les nouveaux utilisateurs configurent rapidement une application PHP avec des opérations CRUD et une connectivité à la base de données. Le projet démontre comment utiliser Flight pour le développement d'API RESTful, en en faisant un outil d'apprentissage idéal pour les débutants et un kit de démarrage utile pour les développeurs plus expérimentés. +- [ASC REST API Spell Checker](https://github.com/AlMosahih-ASC/asc-api-sample) - Une API REST légère pour la vérification orthographique en arabe construite avec FlightPHP et la bibliothèque ArPHP. Cette API fournit des capacités de vérification orthographique de texte arabe, y compris la détection de mots mal orthographiés et des suggestions de correction. +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify est une application monopage connectant les organisateurs d'événements avec les participants. Construite avec PHP (FlightPHP), JavaScript et MySQL, elle inclut une authentification JWT, la gestion d'événements et des documents d'API RESTful utilisant OpenAPI. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental est une application web monopage et conviviale pour mobile de location de voitures construite avec PHP (FlightPHP), JavaScript et MySQL. Elle prend en charge l'inscription des utilisateurs, la navigation et la réservation de voitures, tandis que les administrateurs peuvent gérer les voitures, les utilisateurs et les réservations. L'application propose une API REST, une authentification JWT et un design responsive pour une expérience de location moderne. +- [Decay](https://github.com/boxybird/decay) - Flight v3 avec HTMX et SleekDB, tout sur les zombies ! ([Demo](https://decay.andrewrhyand.com)) +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 avec Middleware, Controllers, Active Record et Latte. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Projet d'API CRUD simple utilisant le framework Flight, qui fournit une structure de base pour les nouveaux utilisateurs afin de configurer rapidement une application PHP avec des opérations CRUD et une connectivité à la base de données. Le projet démontre comment utiliser Flight pour le développement d'API RESTful, ce qui en fait un outil d'apprentissage idéal pour les débutants et un kit de démarrage utile pour les développeurs plus expérimentés. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -31,7 +32,7 @@ Bien que ces exemples ne soient pas officiellement sponsorisés par l'équipe Fl - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework d'authentification prêt pour la production qui vous fait économiser des semaines de développement. Fonctionnalités de sécurité de niveau entreprise : 2FA/TOTP, intégration LDAP, SSO Azure, limitation de taux intelligente, empreinte de session, protection contre les attaques par force brute, tableau de bord d'analyse de sécurité, journalisation d'audit complète et contrôle d'accès granulaire basé sur les rôles. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework d'authentification prêt pour la production qui vous fait gagner des semaines de développement. Fonctionnalités de sécurité de niveau entreprise : 2FA/TOTP, intégration LDAP, SSO Azure, limitation de taux intelligente, empreinte de session, protection contre les attaques par force brute, tableau de bord d'analyse de sécurité, journalisation d'audit complète et contrôle d'accès basé sur les rôles granulaire. ## Voulez-vous partager votre propre exemple ? diff --git a/content/v3/id/awesome-plugins/active_record.md b/content/v3/id/awesome-plugins/active_record.md index 011a61a7..6999c99a 100644 --- a/content/v3/id/awesome-plugins/active_record.md +++ b/content/v3/id/awesome-plugins/active_record.md @@ -1,12 +1,12 @@ # Flight Active Record -Sebuah active record adalah pemetaan entitas basis data ke objek PHP. Sederhananya, jika Anda memiliki tabel pengguna di basis data Anda, Anda dapat "menerjemahkan" sebuah baris di tabel tersebut ke dalam kelas `User` dan objek `$user` dalam kode Anda. Lihat [contoh dasar](#basic-example). +Active record adalah pemetaan entitas basis data ke objek PHP. Secara sederhana, jika Anda memiliki tabel users di basis data Anda, Anda dapat "menerjemahkan" baris dalam tabel tersebut ke kelas `User` dan objek `$user` di kode Anda. Lihat [contoh dasar](#basic-example). Klik [di sini](https://github.com/flightphp/active-record) untuk repositori di GitHub. ## Contoh Dasar -Mari kita asumsikan Anda memiliki tabel berikut: +Misalkan Anda memiliki tabel berikut: ```sql CREATE TABLE users ( @@ -16,11 +16,11 @@ CREATE TABLE users ( ); ``` -Sekarang Anda dapat mengatur kelas baru untuk mewakili tabel ini: +Sekarang Anda dapat membuat kelas baru untuk merepresentasikan tabel ini: ```php /** - * Sebuah kelas ActiveRecord biasanya tunggal + * Kelas ActiveRecord biasanya bersifat tunggal * * Sangat disarankan untuk menambahkan properti tabel sebagai komentar di sini * @@ -31,7 +31,7 @@ Sekarang Anda dapat mengatur kelas baru untuk mewakili tabel ini: class User extends flight\ActiveRecord { public function __construct($database_connection) { - // Anda dapat mengatur ini dengan cara ini + // Anda dapat mengaturnya dengan cara ini parent::__construct($database_connection, 'users'); // atau dengan cara ini parent::__construct($database_connection, null, [ 'table' => 'users']); @@ -39,18 +39,18 @@ class User extends flight\ActiveRecord { } ``` -Sekarang saksikan sihir terjadi! +Sekarang saksikan keajaiban itu terjadi! ```php // untuk sqlite -$database_connection = new PDO('sqlite:test.db'); // ini hanya untuk contoh, Anda mungkin akan menggunakan koneksi basis data yang nyata +$database_connection = new PDO('sqlite:test.db'); // ini hanya contoh, Anda mungkin menggunakan koneksi basis data nyata // untuk mysql $database_connection = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'username', 'password'); // atau mysqli $database_connection = new mysqli('localhost', 'username', 'password', 'test_db'); -// atau mysqli dengan pembuatan yang tidak berdasarkan objek +// atau mysqli dengan pembuatan berbasis non-objek $database_connection = mysqli_connect('localhost', 'username', 'password', 'test_db'); $user = new User($database_connection); @@ -64,19 +64,19 @@ echo $user->id; // 1 $user->name = 'Joseph Mamma'; $user->password = password_hash('some cool password again!!!'); $user->insert(); -// tidak dapat menggunakan $user->save() di sini, atau itu akan mengira ini adalah pembaruan! +// tidak bisa menggunakan $user->save() di sini atau itu akan mengira itu pembaruan! echo $user->id; // 2 ``` -Dan itu sangat mudah untuk menambahkan pengguna baru! Sekarang setelah ada baris pengguna di basis data, bagaimana cara Anda mengeluarkannya? +Dan itu semudah itu untuk menambahkan pengguna baru! Sekarang ada baris pengguna di basis data, bagaimana Anda mengambilnya? ```php -$user->find(1); // cari id = 1 dalam basis data dan kembalikan. +$user->find(1); // cari id = 1 di basis data dan kembalikan itu. echo $user->name; // 'Bobby Tables' ``` -Dan bagaimana jika Anda ingin menemukan semua pengguna? +Dan bagaimana jika Anda ingin mencari semua pengguna? ```php $users = $user->findAll(); @@ -88,7 +88,7 @@ Bagaimana dengan kondisi tertentu? $users = $user->like('name', '%mamma%')->findAll(); ``` -Lihat betapa menyenangkannya ini? Mari kita instal dan mulai! +Lihat betapa menyenangkannya ini? Mari instal dan mulai! ## Instalasi @@ -103,23 +103,23 @@ composer require flightphp/active-record Ini dapat digunakan sebagai pustaka mandiri atau dengan Flight PHP Framework. Sepenuhnya terserah Anda. ### Mandiri -Pastikan Anda mengoper koneksi PDO ke konstruktor. +Pastikan Anda mengirimkan koneksi PDO ke konstruktor. ```php -$pdo_connection = new PDO('sqlite:test.db'); // ini hanya untuk contoh, Anda mungkin akan menggunakan koneksi basis data yang nyata +$pdo_connection = new PDO('sqlite:test.db'); // ini hanya contoh, Anda mungkin menggunakan koneksi basis data nyata $User = new User($pdo_connection); ``` -> Tidak ingin selalu mengatur koneksi basis data Anda di konstruktor? Lihat [Manajemen Koneksi Basis Data](#database-connection-management) untuk ide lainnya! +> Tidak ingin selalu mengatur koneksi basis data di konstruktor? Lihat [Manajemen Koneksi Basis Data](#database-connection-management) untuk ide-ide lain! -### Daftarkan sebagai metode dalam Flight -Jika Anda menggunakan Flight PHP Framework, Anda dapat mendaftarkan kelas ActiveRecord sebagai layanan, tetapi sejujurnya Anda tidak harus melakukannya. +### Daftarkan sebagai metode di Flight +Jika Anda menggunakan Flight PHP Framework, Anda dapat mendaftarkan kelas ActiveRecord sebagai layanan, tapi sebenarnya tidak harus. ```php Flight::register('user', 'User', [ $pdo_connection ]); -// kemudian Anda dapat menggunakannya seperti ini di pengontrol, fungsi, dll. +// kemudian Anda dapat menggunakannya seperti ini di controller, fungsi, dll. Flight::user()->find(1); ``` @@ -146,7 +146,7 @@ declare(strict_types=1); namespace app\records; /** - * Kelas ActiveRecord untuk tabel pengguna. + * Kelas ActiveRecord untuk tabel users. * @link https://docs.flightphp.com/awesome-plugins/active-record * * @property int $id @@ -158,7 +158,7 @@ namespace app\records; class UserRecord extends \flight\ActiveRecord { /** - * @var array $relations Menetapkan hubungan untuk model + * @var array $relations Atur hubungan untuk model * https://docs.flightphp.com/awesome-plugins/active-record#relationships */ protected array $relations = [ @@ -180,22 +180,22 @@ class UserRecord extends \flight\ActiveRecord #### `find($id = null) : boolean|ActiveRecord` -Mencari satu catatan dan menetapkannya pada objek saat ini. Jika Anda mengoper `$id` dari jenis tertentu, itu akan melakukan pencarian pada kunci utama dengan nilai itu. Jika tidak ada yang dipassing, ini hanya akan menemukan catatan pertama di tabel. +Cari satu rekaman dan tetapkan ke objek saat ini. Jika Anda mengirimkan `$id` tertentu, itu akan melakukan pencarian pada kunci utama dengan nilai tersebut. Jika tidak ada yang dikirimkan, itu hanya akan mencari rekaman pertama di tabel. -Selain itu, Anda dapat mengoper metode pembantu lainnya untuk menanyakan tabel Anda. +Selain itu, Anda dapat mengirimkan metode pembantu lain untuk memquery tabel Anda. ```php -// mencari catatan dengan beberapa kondisi terlebih dahulu +// cari rekaman dengan beberapa kondisi sebelumnya $user->notNull('password')->orderBy('id DESC')->find(); -// mencari catatan berdasarkan id tertentu +// cari rekaman berdasarkan id tertentu $id = 123; $user->find($id); ``` #### `findAll(): array` -Menemukan semua catatan di tabel yang Anda tentukan. +Mencari semua rekaman di tabel yang Anda tentukan. ```php $user->findAll(); @@ -203,17 +203,17 @@ $user->findAll(); #### `isHydrated(): boolean` (v0.4.0) -Mengembalikan `true` jika catatan saat ini telah terhidrat (diambil dari database). +Mengembalikan `true` jika rekaman saat ini telah dihidrasi (diambil dari basis data). ```php $user->find(1); -// jika catatan ditemukan dengan data... +// jika rekaman ditemukan dengan data... $user->isHydrated(); // true ``` #### `insert(): boolean|ActiveRecord` -Menyisipkan catatan saat ini ke dalam basis data. +Memasukkan rekaman saat ini ke basis data. ```php $user = new User($pdo_connection); @@ -222,9 +222,9 @@ $user->password = md5('demo'); $user->insert(); ``` -##### Kunci Utama berbasis Teks +##### Kunci Utama Berbasis Teks -Jika Anda memiliki kunci utama berbasis teks (seperti UUID), Anda dapat mengatur nilai kunci utama sebelum menyisipkan dalam dua cara. +Jika Anda memiliki kunci utama berbasis teks (seperti UUID), Anda dapat mengatur nilai kunci utama sebelum memasukkan dengan salah satu dari dua cara. ```php $user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]); @@ -234,28 +234,31 @@ $user->password = md5('demo'); $user->insert(); // atau $user->save(); ``` -atau Anda dapat membiarkan kunci utama dihasilkan secara otomatis untuk Anda melalui peristiwa. +atau Anda dapat memiliki kunci utama yang dihasilkan secara otomatis untuk Anda melalui event. ```php class User extends flight\ActiveRecord { public function __construct($database_connection) { parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]); - // Anda juga dapat mengatur primaryKey ini alih-alih array di atas. + // Anda juga dapat mengatur primaryKey dengan cara ini daripada array di atas. $this->primaryKey = 'uuid'; } protected function beforeInsert(self $self) { - $self->uuid = uniqid(); // atau sesuaikan bagaimana Anda perlu menghasilkan id unik Anda + $self->uuid = uniqid(); // atau bagaimana pun Anda perlu menghasilkan id unik Anda } } ``` -Jika Anda tidak mengatur kunci utama sebelum menyisipkan, itu akan diatur ke `rowid` dan basis data akan menghasilkan untuk Anda, tetapi tidak akan dipertahankan karena bidang itu mungkin tidak ada dalam tabel Anda. Inilah sebabnya mengapa disarankan untuk menggunakan peristiwa untuk menangani ini secara otomatis untuk Anda. +Jika Anda tidak mengatur kunci utama sebelum memasukkan, itu akan diatur ke `rowid` dan +basis data akan menghasilkannya untuk Anda, tapi itu tidak akan bertahan karena field tersebut mungkin tidak ada +di tabel Anda. Inilah mengapa disarankan untuk menggunakan event untuk menangani ini secara otomatis +untuk Anda. #### `update(): boolean|ActiveRecord` -Memperbarui catatan saat ini ke dalam basis data. +Memperbarui rekaman saat ini ke basis data. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); @@ -265,7 +268,7 @@ $user->update(); #### `save(): boolean|ActiveRecord` -Menyisipkan atau memperbarui catatan saat ini ke dalam basis data. Jika catatan memiliki id, itu akan memperbarui, jika tidak, itu akan menyisipkan. +Memasukkan atau memperbarui rekaman saat ini ke basis data. Jika rekaman memiliki id, itu akan memperbarui, jika tidak itu akan memasukkan. ```php $user = new User($pdo_connection); @@ -274,18 +277,18 @@ $user->password = md5('demo'); $user->save(); ``` -**Catatan:** Jika Anda memiliki hubungan yang ditentukan dalam kelas, itu akan menyimpan hubungan tersebut secara rekursif juga jika telah ditentukan, diinstansiasi, dan memiliki data yang perlu diperbarui. (v0.4.0 dan lebih baru) +**Catatan:** Jika Anda memiliki hubungan yang didefinisikan di kelas, itu akan secara rekursif menyimpan hubungan tersebut juga jika mereka telah didefinisikan, diinstansiasi dan memiliki data kotor untuk diperbarui. (v0.4.0 dan di atas) #### `delete(): boolean` -Menghapus catatan saat ini dari basis data. +Menghapus rekaman saat ini dari basis data. ```php $user->gt('id', 0)->orderBy('id desc')->find(); $user->delete(); ``` -Anda juga dapat menghapus beberapa catatan dengan mengeksekusi pencarian terlebih dahulu. +Anda juga dapat menghapus beberapa rekaman dengan menjalankan pencarian sebelumnya. ```php $user->like('name', 'Bob%')->delete(); @@ -293,37 +296,37 @@ $user->like('name', 'Bob%')->delete(); #### `dirty(array $dirty = []): ActiveRecord` -Data "dirty" merujuk pada data yang telah diubah dalam sebuah catatan. +Data kotor merujuk pada data yang telah diubah dalam rekaman. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); -// tidak ada yang "dirty" pada titik ini. +// tidak ada yang "kotor" pada titik ini. -$user->email = 'test@example.com'; // sekarang email dianggap "dirty" karena telah diubah. +$user->email = 'test@example.com'; // sekarang email dianggap "kotor" karena telah diubah. $user->update(); -// sekarang tidak ada data yang dirty karena telah diperbarui dan dipertahankan dalam basis data +// sekarang tidak ada data yang kotor karena telah diperbarui dan disimpan di basis data -$user->password = password_hash('newpassword'); // sekarang ini kotor -$user->dirty(); // melewatkan apa pun akan membersihkan semua entri yang kotor. +$user->password = password_hash()'newpassword'); // sekarang ini kotor +$user->dirty(); // mengirimkan tidak ada akan membersihkan semua entri kotor. $user->update(); // tidak ada yang akan diperbarui karena tidak ada yang ditangkap sebagai kotor. -$user->dirty([ 'name' => 'sesuatu', 'password' => password_hash('password yang berbeda') ]); -$user->update(); // baik nama dan kata sandi diperbarui. +$user->dirty([ 'name' => 'something', 'password' => password_hash('a different password') ]); +$user->update(); // baik name maupun password diperbarui. ``` #### `copyFrom(array $data): ActiveRecord` (v0.4.0) -Ini adalah alias untuk metode `dirty()`. Ini sedikit lebih jelas tentang apa yang Anda lakukan. +Ini adalah alias untuk metode `dirty()`. Ini sedikit lebih jelas apa yang Anda lakukan. ```php -$user->copyFrom([ 'name' => 'sesuatu', 'password' => password_hash('password yang berbeda') ]); -$user->update(); // baik nama dan kata sandi diperbarui. +$user->copyFrom([ 'name' => 'something', 'password' => password_hash('a different password') ]); +$user->update(); // baik name maupun password diperbarui. ``` #### `isDirty(): boolean` (v0.4.0) -Mengembalikan `true` jika catatan saat ini telah diubah. +Mengembalikan `true` jika rekaman saat ini telah diubah. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); @@ -333,15 +336,15 @@ $user->isDirty(); // true #### `reset(bool $include_query_data = true): ActiveRecord` -Mereset catatan saat ini ke keadaan awalnya. Ini sangat baik digunakan dalam perilaku tipe loop. -Jika Anda mengoper `true`, itu juga akan mereset data kueri yang digunakan untuk menemukan objek saat ini (perilaku default). +Mengatur ulang rekaman saat ini ke keadaan awalnya. Ini sangat bagus untuk digunakan dalam perilaku tipe loop. +Jika Anda mengirimkan `true` itu juga akan mengatur ulang data query yang digunakan untuk menemukan objek saat ini (perilaku default). ```php $users = $user->greaterThan('id', 0)->orderBy('id desc')->find(); $user_company = new UserCompany($pdo_connection); foreach($users as $user) { - $user_company->reset(); // mulai dengan slate yang bersih + $user_company->reset(); // mulai dengan slate bersih $user_company->user_id = $user->id; $user_company->company_id = $some_company_id; $user_company->insert(); @@ -350,12 +353,12 @@ foreach($users as $user) { #### `getBuiltSql(): string` (v0.4.1) -Setelah Anda menjalankan metode `find()`, `findAll()`, `insert()`, `update()`, atau `save()`, Anda dapat memperoleh SQL yang dibangun dan menggunakannya untuk tujuan debugging. +Setelah Anda menjalankan metode `find()`, `findAll()`, `insert()`, `update()`, atau `save()` Anda dapat memperoleh SQL yang dibangun dan menggunakannya untuk tujuan debugging. -## Metode Kuery SQL +## Metode Query SQL #### `select(string $field1 [, string $field2 ... ])` -Anda dapat memilih hanya beberapa kolom di tabel jika Anda mau (ini lebih efisien pada tabel yang sangat lebar dengan banyak kolom) +Anda dapat memilih hanya beberapa kolom di tabel jika Anda suka (ini lebih performant pada tabel lebar yang sangat banyak kolomnya) ```php $user->select('id', 'name')->find(); @@ -363,7 +366,7 @@ $user->select('id', 'name')->find(); #### `from(string $table)` -Anda dapat memilih tabel lain juga! Untuk apa tidak?! +Anda secara teknis dapat memilih tabel lain juga! Mengapa tidak?! ```php $user->select('id', 'name')->from('user')->find(); @@ -371,7 +374,7 @@ $user->select('id', 'name')->from('user')->find(); #### `join(string $table_name, string $join_condition)` -Anda bahkan dapat bergabung dengan tabel lain di basis data. +Anda bahkan dapat bergabung ke tabel lain di basis data. ```php $user->join('contacts', 'contacts.user_id = users.id')->find(); @@ -379,13 +382,13 @@ $user->join('contacts', 'contacts.user_id = users.id')->find(); #### `where(string $where_conditions)` -Anda dapat menetapkan beberapa argumen where kustom (Anda tidak dapat mengatur parameter dalam pernyataan where ini) +Anda dapat mengatur beberapa argumen where kustom (Anda tidak dapat mengatur params di pernyataan where ini) ```php $user->where('id=1 AND name="demo"')->find(); ``` -**Catatan Keamanan** - Anda mungkin terdorong untuk melakukan sesuatu seperti `$user->where("id = '{$id}' AND name = '{$name}'")->find();`. Tolong JANGAN LAKUKAN INI!!! Ini rentan terhadap apa yang dikenal sebagai serangan SQL Injection. Ada banyak artikel di internet, silakan Google "sql injection attacks php" dan Anda akan menemukan banyak artikel tentang subjek ini. Cara yang tepat untuk menangani ini dengan perpustakaan ini adalah alih-alih metode `where()` ini, Anda akan melakukan sesuatu yang lebih seperti `$user->eq('id', $id)->eq('name', $name)->find();` Jika Anda harus melakukan ini, pustaka `PDO` memiliki `$pdo->quote($var)` untuk menghindarinya untuk Anda. Hanya setelah Anda menggunakan `quote()` Anda dapat menggunakannya dalam pernyataan `where()`. +**Catatan Keamanan** - Anda mungkin tergoda untuk melakukan sesuatu seperti `$user->where("id = '{$id}' AND name = '{$name}'")->find();`. Tolong JANGAN LAKUKAN INI!!! Ini rentan terhadap apa yang dikenal sebagai serangan SQL Injection. Ada banyak artikel online, silakan Google "sql injection attacks php" dan Anda akan menemukan banyak artikel tentang subjek ini. Cara yang tepat untuk menangani ini dengan pustaka ini adalah daripada metode `where()` ini, Anda akan melakukan sesuatu seperti `$user->eq('id', $id)->eq('name', $name)->find();` Jika Anda benar-benar harus melakukan ini, pustaka `PDO` memiliki `$pdo->quote($var)` untuk melarikan diri untuk Anda. Hanya setelah Anda menggunakan `quote()` Anda dapat menggunakannya dalam pernyataan `where()`. #### `group(string $group_by_statement)/groupBy(string $group_by_statement)` @@ -397,7 +400,7 @@ $user->select('COUNT(*) as count')->groupBy('name')->findAll(); #### `order(string $order_by_statement)/orderBy(string $order_by_statement)` -Urutkan kueri yang dikembalikan dengan cara tertentu. +Urutkan query yang dikembalikan dengan cara tertentu. ```php $user->orderBy('name DESC')->find(); @@ -405,7 +408,7 @@ $user->orderBy('name DESC')->find(); #### `limit(string $limit)/limit(int $offset, int $limit)` -Batasi jumlah rekaman yang dikembalikan. Jika bilangan kedua diberikan, itu akan di-offset, batasi saja seperti di SQL. +Batasi jumlah rekaman yang dikembalikan. Jika int kedua diberikan, itu akan menjadi offset, limit seperti di SQL. ```php $user->orderby('name DESC')->limit(0, 10)->findAll(); @@ -414,7 +417,7 @@ $user->orderby('name DESC')->limit(0, 10)->findAll(); ## Kondisi WHERE #### `equal(string $field, mixed $value) / eq(string $field, mixed $value)` -Di mana `field = $value` +Where `field = $value` ```php $user->eq('id', 1)->find(); @@ -422,7 +425,7 @@ $user->eq('id', 1)->find(); #### `notEqual(string $field, mixed $value) / ne(string $field, mixed $value)` -Di mana `field <> $value` +Where `field <> $value` ```php $user->ne('id', 1)->find(); @@ -430,14 +433,14 @@ $user->ne('id', 1)->find(); #### `isNull(string $field)` -Di mana `field IS NULL` +Where `field IS NULL` ```php $user->isNull('id')->find(); ``` #### `isNotNull(string $field) / notNull(string $field)` -Di mana `field IS NOT NULL` +Where `field IS NOT NULL` ```php $user->isNotNull('id')->find(); @@ -445,7 +448,7 @@ $user->isNotNull('id')->find(); #### `greaterThan(string $field, mixed $value) / gt(string $field, mixed $value)` -Di mana `field > $value` +Where `field > $value` ```php $user->gt('id', 1)->find(); @@ -453,21 +456,21 @@ $user->gt('id', 1)->find(); #### `lessThan(string $field, mixed $value) / lt(string $field, mixed $value)` -Di mana `field < $value` +Where `field < $value` ```php $user->lt('id', 1)->find(); ``` #### `greaterThanOrEqual(string $field, mixed $value) / ge(string $field, mixed $value) / gte(string $field, mixed $value)` -Di mana `field >= $value` +Where `field >= $value` ```php $user->ge('id', 1)->find(); ``` #### `lessThanOrEqual(string $field, mixed $value) / le(string $field, mixed $value) / lte(string $field, mixed $value)` -Di mana `field <= $value` +Where `field <= $value` ```php $user->le('id', 1)->find(); @@ -475,7 +478,7 @@ $user->le('id', 1)->find(); #### `like(string $field, mixed $value) / notLike(string $field, mixed $value)` -Di mana `field LIKE $value` atau `field NOT LIKE $value` +Where `field LIKE $value` atau `field NOT LIKE $value` ```php $user->like('name', 'de')->find(); @@ -483,7 +486,7 @@ $user->like('name', 'de')->find(); #### `in(string $field, array $values) / notIn(string $field, array $values)` -Di mana `field IN($value)` atau `field NOT IN($value)` +Where `field IN($value)` atau `field NOT IN($value)` ```php $user->in('id', [1, 2])->find(); @@ -491,7 +494,7 @@ $user->in('id', [1, 2])->find(); #### `between(string $field, array $values)` -Di mana `field BETWEEN $value AND $value1` +Where `field BETWEEN $value AND $value1` ```php $user->between('id', [1, 2])->find(); @@ -499,48 +502,48 @@ $user->between('id', [1, 2])->find(); ### Kondisi OR -Dimungkinkan untuk membungkus kondisi Anda dalam pernyataan OR. Ini dilakukan dengan metode `startWrap()` dan `endWrap()` atau dengan mengisi parameter ke-3 dari kondisi setelah bidang dan nilai. +Mungkin untuk membungkus kondisi Anda dalam pernyataan OR. Ini dilakukan dengan metode `startWrap()` dan `endWrap()` atau dengan mengisi parameter ke-3 dari kondisi setelah field dan value. ```php // Metode 1 $user->eq('id', 1)->startWrap()->eq('name', 'demo')->or()->eq('name', 'test')->endWrap('OR')->find(); -// Ini akan dievaluasi menjadi `id = 1 AND (name = 'demo' OR name = 'test')` +// Ini akan dievaluasi ke `id = 1 AND (name = 'demo' OR name = 'test')` // Metode 2 $user->eq('id', 1)->eq('name', 'demo', 'OR')->find(); -// Ini akan dievaluasi menjadi `id = 1 OR name = 'demo'` +// Ini akan dievaluasi ke `id = 1 OR name = 'demo'` ``` ## Hubungan -Anda dapat mengatur beberapa jenis hubungan menggunakan pustaka ini. Anda dapat mengatur hubungan satu->banyak dan satu->satu antara tabel. Ini membutuhkan pengaturan ekstra dalam kelas sebelumnya. +Anda dapat mengatur beberapa jenis hubungan menggunakan pustaka ini. Anda dapat mengatur hubungan one->many dan one->one antara tabel. Ini memerlukan sedikit pengaturan tambahan di kelas sebelumnya. -Mengatur array `$relations` tidaklah sulit, tetapi menebak sintaks yang benar bisa membingungkan. +Mengatur array `$relations` tidak sulit, tapi menebak sintaks yang benar bisa membingungkan. ```php protected array $relations = [ - // Anda dapat memberi nama kuncinya dengan cara apa pun yang Anda suka. Nama ActiveRecord mungkin bagus. Mis: user, contact, client + // Anda dapat menamai kunci apa saja yang Anda suka. Nama ActiveRecord mungkin bagus. Contoh: user, contact, client 'user' => [ - // wajib + // diperlukan // self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO self::HAS_ONE, // ini adalah jenis hubungan - // wajib - 'Some_Class', // ini adalah kelas ActiveRecord "lain" yang akan direferensikan + // diperlukan + 'Some_Class', // ini adalah kelas ActiveRecord "lain" yang akan dirujuk - // wajib + // diperlukan // tergantung pada jenis hubungan - // self::HAS_ONE = kunci asing yang mereferensikan gabungan - // self::HAS_MANY = kunci asing yang mereferensikan gabungan - // self::BELONGS_TO = kunci lokal yang mereferensikan gabungan + // self::HAS_ONE = kunci asing yang merujuk ke join + // self::HAS_MANY = kunci asing yang merujuk ke join + // self::BELONGS_TO = kunci lokal yang merujuk ke join 'local_or_foreign_key', - // hanya FYI, ini juga hanya bergabung dengan kunci utama model "lain" + // hanya FYI, ini juga hanya bergabung ke kunci utama dari model "lain" // opsional - [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // kondisi tambahan yang Anda inginkan ketika menggabungkan hubungan + [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // kondisi tambahan yang Anda inginkan saat bergabung hubungan // $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5)) // opsional - 'nama_referensi_kembali' // ini jika Anda ingin merujuk kembali hubungan ini kembali ke dirinya sendiri Mis: $user->contact->user; + 'back_reference_name' // ini jika Anda ingin merujuk balik hubungan ini kembali ke dirinya sendiri Contoh: $user->contact->user; ]; ] ``` @@ -578,12 +581,12 @@ $user = new User($pdo_connection); // cari pengguna terbaru. $user->notNull('id')->orderBy('id desc')->find(); -// ambil kontak dengan menggunakan hubungan: +// dapatkan kontak dengan menggunakan hubungan: foreach($user->contacts as $contact) { echo $contact->id; } -// atau kita bisa pergi ke arah yang lain. +// atau kita bisa pergi ke arah lain. $contact = new Contact(); // cari satu kontak @@ -593,10 +596,111 @@ $contact->find(); echo $contact->user->name; // ini adalah nama pengguna ``` -Keren kan? +Cukup keren ya? + +### Eager Loading + +#### Gambaran Umum +Eager loading menyelesaikan masalah query N+1 dengan memuat hubungan di muka. Daripada menjalankan query terpisah untuk hubungan setiap rekaman, eager loading mengambil semua data terkait hanya dalam satu query tambahan per hubungan. + +> **Catatan:** Eager loading hanya tersedia untuk v0.7.0 dan di atas. + +#### Penggunaan Dasar +Gunakan metode `with()` untuk menentukan hubungan mana yang akan dimuat secara eager: +```php +// Muat pengguna dengan kontak mereka dalam 2 query daripada N+1 +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + foreach ($u->contacts as $contact) { + echo $contact->email; // Tidak ada query tambahan! + } +} +``` + +#### Multiple Relations +Muat beberapa hubungan sekaligus: +```php +$users = $user->with(['contacts', 'profile', 'settings'])->findAll(); +``` + +#### Jenis Hubungan + +##### HAS_MANY +```php +// Eager load semua kontak untuk setiap pengguna +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + // $u->contacts sudah dimuat sebagai array + foreach ($u->contacts as $contact) { + echo $contact->email; + } +} +``` +##### HAS_ONE +```php +// Eager load satu kontak untuk setiap pengguna +$users = $user->with('contact')->findAll(); +foreach ($users as $u) { + // $u->contact sudah dimuat sebagai objek + echo $u->contact->email; +} +``` + +##### BELONGS_TO +```php +// Eager load pengguna induk untuk semua kontak +$contacts = $contact->with('user')->findAll(); +foreach ($contacts as $c) { + // $c->user sudah dimuat + echo $c->user->name; +} +``` +##### Dengan find() +Eager loading bekerja dengan baik +findAll() + dan +find() +: + +```php +$user = $user->with('contacts')->find(1); +// Pengguna dan semua kontak mereka dimuat dalam 2 query +``` +#### Manfaat Performa +Tanpa eager loading (masalah N+1): +```php +$users = $user->findAll(); // 1 query +foreach ($users as $u) { + $contacts = $u->contacts; // N query (satu per pengguna!) +} +// Total: 1 + N query +``` + +Dengan eager loading: + +```php +$users = $user->with('contacts')->findAll(); // 2 query total +foreach ($users as $u) { + $contacts = $u->contacts; // 0 query tambahan! +} +// Total: 2 query (1 untuk pengguna + 1 untuk semua kontak) +``` +Untuk 10 pengguna, ini mengurangi query dari 11 menjadi 2 - pengurangan 82%! + +#### Catatan Penting +- Eager loading sepenuhnya opsional - lazy loading masih bekerja seperti sebelumnya +- Hubungan yang sudah dimuat secara otomatis dilewati +- Back references bekerja dengan eager loading +- Callback hubungan dihormati selama eager loading + +#### Keterbatasan +- Eager loading bersarang (mis., +with(['contacts.addresses']) +) saat ini tidak didukung +- Batasan eager load melalui closure tidak didukung dalam versi ini ## Mengatur Data Kustom -Terkadang Anda mungkin perlu melampirkan sesuatu yang unik pada ActiveRecord Anda seperti perhitungan khusus yang mungkin lebih mudah untuk dilampirkan pada objek yang kemudian akan diteruskan ke template. +Kadang-kadang Anda mungkin perlu melampirkan sesuatu yang unik ke ActiveRecord Anda seperti perhitungan kustom yang mungkin lebih mudah untuk hanya melampirkannya ke objek yang kemudian diteruskan ke template. #### `setCustomData(string $field, mixed $value)` Anda melampirkan data kustom dengan metode `setCustomData()`. @@ -604,15 +708,15 @@ Anda melampirkan data kustom dengan metode `setCustomData()`. $user->setCustomData('page_view_count', $page_view_count); ``` -Dan kemudian Anda cukup merujuknya seperti properti objek biasa. +Dan kemudian Anda cukup merujuknya seperti properti objek normal. ```php echo $user->page_view_count; ``` -## Peristiwa +## Event -Satu fitur luar biasa lainnya tentang pustaka ini adalah tentang peristiwa. Peristiwa dipicu pada saat tertentu berdasarkan metode tertentu yang Anda panggil. Mereka sangat membantu dalam menyiapkan data untuk Anda secara otomatis. +Satu fitur super hebat lagi tentang pustaka ini adalah tentang event. Event dipicu pada waktu tertentu berdasarkan metode tertentu yang Anda panggil. Mereka sangat sangat membantu dalam mengatur data untuk Anda secara otomatis. #### `onConstruct(ActiveRecord $ActiveRecord, array &config)` @@ -643,7 +747,7 @@ class User extends flight\ActiveRecord { #### `beforeFind(ActiveRecord $ActiveRecord)` -Ini mungkin hanya berguna jika Anda perlu manipulasi kueri setiap kali. +Ini mungkin hanya berguna jika Anda perlu manipulasi query setiap kali. ```php class User extends flight\ActiveRecord { @@ -654,7 +758,7 @@ class User extends flight\ActiveRecord { } protected function beforeFind(self $self) { - // selalu jalankan id >= 0 jika itu adalah yang Anda inginkan + // selalu jalankan id >= 0 jika itu gaya Anda $self->gte('id', 0); } } @@ -662,7 +766,7 @@ class User extends flight\ActiveRecord { #### `afterFind(ActiveRecord $ActiveRecord)` -Yang ini mungkin lebih berguna jika Anda selalu perlu menjalankan beberapa logika setiap kali catatan ini diambil. Apakah Anda perlu mendekripsi sesuatu? Apakah Anda perlu menjalankan kueri hitung kustom setiap kali (tidak efisien tetapi tidak apa-apa)? +Yang ini mungkin lebih berguna jika Anda selalu perlu menjalankan beberapa logika setiap kali rekaman ini diambil. Apakah Anda perlu mendekripsi sesuatu? Apakah Anda perlu menjalankan query hitung kustom setiap kali (tidak performant tapi terserah)? ```php class User extends flight\ActiveRecord { @@ -676,15 +780,15 @@ class User extends flight\ActiveRecord { // mendekripsi sesuatu $self->secret = yourDecryptFunction($self->secret, $some_key); - // mungkin menyimpan sesuatu yang kustom seperti kueri??? - $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']); + // mungkin menyimpan sesuatu kustom seperti query??? + $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']; } } ``` #### `beforeFindAll(ActiveRecord $ActiveRecord)` -Ini mungkin hanya berguna jika Anda perlu manipulasi kueri setiap kali. +Ini mungkin hanya berguna jika Anda perlu manipulasi query setiap kali. ```php class User extends flight\ActiveRecord { @@ -695,7 +799,7 @@ class User extends flight\ActiveRecord { } protected function beforeFindAll(self $self) { - // selalu jalankan id >= 0 jika itu adalah yang Anda inginkan + // selalu jalankan id >= 0 jika itu gaya Anda $self->gte('id', 0); } } @@ -703,7 +807,7 @@ class User extends flight\ActiveRecord { #### `afterFindAll(array $results)` -Mirip dengan `afterFind()` tetapi Anda bisa melakukannya ke semua catatan! +Mirip dengan `afterFind()` tapi Anda bisa melakukannya untuk semua rekaman! ```php class User extends flight\ActiveRecord { @@ -724,7 +828,7 @@ class User extends flight\ActiveRecord { #### `beforeInsert(ActiveRecord $ActiveRecord)` -Sangat berguna jika Anda perlu menetapkan beberapa nilai default setiap kali. +Sangat membantu jika Anda perlu beberapa nilai default yang diatur setiap kali. ```php class User extends flight\ActiveRecord { @@ -735,7 +839,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // menetapkan beberapa default yang baik + // atur beberapa default yang masuk akal if(!$self->created_date) { $self->created_date = gmdate('Y-m-d'); } @@ -749,7 +853,7 @@ class User extends flight\ActiveRecord { #### `afterInsert(ActiveRecord $ActiveRecord)` -Mungkin Anda memiliki skenario untuk mengubah data setelah disisipkan? +Mungkin Anda memiliki kasus pengguna untuk mengubah data setelah dimasukkan? ```php class User extends flight\ActiveRecord { @@ -760,7 +864,7 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // Anda melakukan Anda + // lakukan apa yang Anda mau Flight::cache()->set('most_recent_insert_id', $self->id); // atau apa pun.... } @@ -769,7 +873,7 @@ class User extends flight\ActiveRecord { #### `beforeUpdate(ActiveRecord $ActiveRecord)` -Sangat berguna jika Anda perlu menetapkan beberapa nilai default setiap kali ada pembaruan. +Sangat membantu jika Anda perlu beberapa nilai default yang diatur setiap kali pada pembaruan. ```php class User extends flight\ActiveRecord { @@ -780,7 +884,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // menetapkan beberapa default yang baik + // atur beberapa default yang masuk akal if(!$self->updated_date) { $self->updated_date = gmdate('Y-m-d'); } @@ -790,7 +894,7 @@ class User extends flight\ActiveRecord { #### `afterUpdate(ActiveRecord $ActiveRecord)` -Mungkin Anda memiliki skenario untuk mengubah data setelah diperbarui? +Mungkin Anda memiliki kasus pengguna untuk mengubah data setelah diperbarui? ```php class User extends flight\ActiveRecord { @@ -801,7 +905,7 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // Anda melakukan Anda + // lakukan apa yang Anda mau Flight::cache()->set('most_recently_updated_user_id', $self->id); // atau apa pun.... } @@ -810,7 +914,7 @@ class User extends flight\ActiveRecord { #### `beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)` -Ini berguna jika Anda ingin peristiwa terjadi baik saat sisip atau pembaruan terjadi. Saya akan menghemat penjelasan panjangnya, tetapi saya yakin Anda bisa menebak apa itu. +Ini berguna jika Anda ingin event terjadi baik saat insert atau update. Saya akan menghemat penjelasan panjang, tapi saya yakin Anda bisa menebak apa itu. ```php class User extends flight\ActiveRecord { @@ -828,7 +932,7 @@ class User extends flight\ActiveRecord { #### `beforeDelete(ActiveRecord $ActiveRecord)/afterDelete(ActiveRecord $ActiveRecord)` -Tidak yakin apa yang ingin Anda lakukan di sini, tetapi tidak ada penilaian di sini! Ayo lakukan! +Tidak yakin apa yang ingin Anda lakukan di sini, tapi tidak ada penilaian di sini! Silakan! ```php class User extends flight\ActiveRecord { @@ -839,17 +943,17 @@ class User extends flight\ActiveRecord { } protected function beforeDelete(self $self) { - echo 'Dia adalah seorang prajurit yang berani... :cry-face:'; + echo 'He was a brave soldier... :cry-face:'; } } ``` ## Manajemen Koneksi Basis Data -Ketika Anda menggunakan pustaka ini, Anda dapat mengatur koneksi basis data dengan beberapa cara berbeda. Anda dapat mengatur koneksi di konstruktor, Anda dapat mengatur melalui variabel konfigurasi `$config['connection']` atau Anda dapat mengatur melalui `setDatabaseConnection()` (v0.4.1). +Saat Anda menggunakan pustaka ini, Anda dapat mengatur koneksi basis data dengan beberapa cara berbeda. Anda dapat mengatur koneksi di konstruktor, Anda dapat mengaturnya melalui variabel config `$config['connection']` atau Anda dapat mengaturnya melalui `setDatabaseConnection()` (v0.4.1). ```php -$pdo_connection = new PDO('sqlite:test.db'); // untuk contoh +$pdo_connection = new PDO('sqlite:test.db'); // misalnya $user = new User($pdo_connection); // atau $user = new User(null, [ 'connection' => $pdo_connection ]); @@ -858,11 +962,11 @@ $user = new User(); $user->setDatabaseConnection($pdo_connection); ``` -Jika Anda ingin menghindari selalu mengatur `$database_connection` setiap kali Anda memanggil record aktif, ada cara untuk mengatasinya! +Jika Anda ingin menghindari selalu mengatur `$database_connection` setiap kali Anda memanggil active record, ada cara untuk itu! ```php // index.php atau bootstrap.php -// Set ini sebagai kelas terdaftar di Flight +// Atur ini sebagai kelas terdaftar di Flight Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php @@ -879,19 +983,20 @@ class User extends flight\ActiveRecord { $user = new User(); ``` -> **Catatan:** Jika Anda berencana untuk melakukan pengujian unit, melakukan ini dapat menambah beberapa tantangan untuk pengujian unit, tetapi secara keseluruhan karena Anda dapat menyuntikkan koneksi Anda dengan `setDatabaseConnection()` atau `$config['connection']`, ini tidak terlalu buruk. +> **Catatan:** Jika Anda berencana untuk unit testing, melakukannya dengan cara ini dapat menambah beberapa tantangan untuk unit testing, tapi secara keseluruhan karena Anda dapat menyuntikkan +koneksi Anda dengan `setDatabaseConnection()` atau `$config['connection']` itu tidak terlalu buruk. -Jika Anda perlu menyegarkan koneksi basis data, misalnya jika Anda menjalankan skrip CLI yang berjalan lama dan perlu menyegarkan koneksi setiap saat, Anda dapat mengatur ulang koneksi dengan `$your_record->setDatabaseConnection($pdo_connection)`. +Jika Anda perlu menyegarkan koneksi basis data, misalnya jika Anda menjalankan skrip CLI yang panjang dan perlu menyegarkan koneksi setiap beberapa saat, Anda dapat mengatur ulang koneksi dengan `$your_record->setDatabaseConnection($pdo_connection)`. -## Kontribusi +## Berkontribusi Silakan lakukan. :D ### Pengaturan -Saat Anda berkontribusi, pastikan Anda menjalankan `composer test-coverage` untuk mempertahankan 100% cakupan pengujian (ini bukan cakupan pengujian unit yang sebenarnya, lebih seperti pengujian integrasi). +Saat Anda berkontribusi, pastikan Anda menjalankan `composer test-coverage` untuk mempertahankan cakupan tes 100% (ini bukan cakupan unit test yang sebenarnya, lebih seperti pengujian integrasi). -Juga pastikan Anda menjalankan `composer beautify` dan `composer phpcs` untuk memperbaiki kesalahan linting. +Juga pastikan Anda menjalankan `composer beautify` dan `composer phpcs` untuk memperbaiki kesalahan linting apa pun. ## Lisensi diff --git a/content/v3/id/awesome-plugins/apm.md b/content/v3/id/awesome-plugins/apm.md index 0e82137b..f14cda44 100644 --- a/content/v3/id/awesome-plugins/apm.md +++ b/content/v3/id/awesome-plugins/apm.md @@ -1,6 +1,6 @@ # Dokumentasi FlightPHP APM -Selamat datang di FlightPHP APM—pelatih performa pribadi untuk aplikasi Anda! Panduan ini adalah peta jalan Anda untuk menyiapkan, menggunakan, dan menguasai Application Performance Monitoring (APM) dengan FlightPHP. Baik Anda sedang memburu permintaan lambat atau hanya ingin bersemangat dengan grafik latensi, kami siap membantu. Mari buat aplikasi Anda lebih cepat, pengguna Anda lebih bahagia, dan sesi debugging Anda menjadi mudah! +Selamat datang di FlightPHP APM—pelatih performa pribadi aplikasi Anda! Panduan ini adalah peta jalan Anda untuk menyiapkan, menggunakan, dan menguasai Application Performance Monitoring (APM) dengan FlightPHP. Baik Anda sedang mencari permintaan lambat atau hanya ingin antusias dengan grafik latensi, kami telah menyiapkannya untuk Anda. Mari buat aplikasi Anda lebih cepat, pengguna Anda lebih bahagia, dan sesi debugging Anda menjadi lebih mudah! Lihat [demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) dari dashboard untuk situs Flight Docs. @@ -8,7 +8,7 @@ Lihat [demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) dari dashboard ## Mengapa APM Penting -Bayangkan ini: aplikasi Anda seperti restoran sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur tersendat, Anda hanya menebak-nebak mengapa pelanggan pergi dengan kesal. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri database, dan menandai apa pun yang memperlambat Anda. Halaman lambat membuat pengguna pergi (studi mengatakan 53% bounce jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah-masalah itu *sebelum* mereka menyakitkan. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?” dan lebih banyak kemenangan “lihat betapa lancarnya ini berjalan!”. +Bayangkan ini: aplikasi Anda adalah restoran sibuk. Tanpa cara untuk melacak berapa lama pesanan memakan waktu atau di mana dapur tersendat, Anda hanya menebak mengapa pelanggan pergi dengan kesal. APM adalah sous-chef Anda—ia mengawasi setiap langkah, dari permintaan masuk hingga kueri database, dan menandai apa pun yang memperlambat Anda. Halaman lambat membuat pengguna hilang (studi mengatakan 53% bounce jika situs memakan waktu lebih dari 3 detik untuk dimuat!), dan APM membantu Anda menangkap masalah tersebut *sebelum* mereka menyengat. Ini adalah ketenangan pikiran yang proaktif—lebih sedikit momen “mengapa ini rusak?” dan lebih banyak kemenangan “lihat betapa lancarnya ini berjalan!” ## Instalasi @@ -18,7 +18,7 @@ Mulai dengan Composer: composer require flightphp/apm ``` -Anda memerlukan: +Anda akan membutuhkan: - **PHP 7.4+**: Menjaga kami kompatibel dengan distribusi Linux LTS sambil mendukung PHP modern. - **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Framework ringan yang kami tingkatkan. @@ -33,7 +33,7 @@ Anda dapat memilih jenis database Anda selama langkah konfigurasi (lihat di bawa ## Memulai -Berikut langkah demi langkah untuk kehebatan APM: +Berikut langkah demi langkah Anda menuju kehebatan APM: ### 1. Daftarkan APM @@ -41,6 +41,7 @@ Masukkan ini ke dalam file `index.php` atau `services.php` Anda untuk mulai mela ```php use flight\apm\logger\LoggerFactory; +use flight\database\PdoWrapper; use flight\Apm; $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); @@ -56,10 +57,10 @@ $Apm->addPdoConnection($pdo); **Apa yang terjadi di sini?** - `LoggerFactory::create()` mengambil konfigurasi Anda (lebih lanjut nanti) dan menyiapkan logger—SQLite secara default. - `Apm` adalah bintangnya—ia mendengarkan peristiwa Flight (permintaan, rute, kesalahan, dll.) dan mengumpulkan metrik. -- `bindEventsToFlightInstance($app)` menghubungkannya semua ke aplikasi Flight Anda. +- `bindEventsToFlightInstance($app)` mengikat semuanya ke aplikasi Flight Anda. **Tips Pro: Sampling** -Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani sistem. Gunakan tingkat sampel (0.0 hingga 1.0): +Jika aplikasi Anda sibuk, mencatat *setiap* permintaan mungkin membebani. Gunakan tingkat sampel (0.0 hingga 1.0): ```php $Apm = new Apm($ApmLogger, 0.1); // Mencatat 10% permintaan @@ -93,11 +94,11 @@ php vendor/bin/runway apm:init > Proses ini juga akan menanyakan apakah Anda ingin menjalankan migrasi untuk pengaturan ini. Jika Anda menyiapkannya untuk pertama kali, jawabannya ya. **Mengapa dua lokasi?** -Metrik mentah menumpuk dengan cepat (bayangkan log yang tidak difilter). Worker memprosesnya menjadi tujuan terstruktur untuk dashboard. Menjaga semuanya rapi! +Metrik mentah menumpuk cepat (pikirkan log yang tidak difilter). Worker memprosesnya menjadi tujuan terstruktur untuk dashboard. Menjaga semuanya rapi! ### 3. Proses Metrik dengan Worker -Worker mengubah metrik mentah menjadi data siap dashboard. Jalankan sekali: +Worker mengubah metrik mentah menjadi data siap dashboard. Jalankannya sekali: ```bash php vendor/bin/runway apm:worker @@ -105,17 +106,17 @@ php vendor/bin/runway apm:worker **Apa yang dilakukannya?** - Membaca dari sumber Anda (misalnya, `apm_metrics.sqlite`). -- Memproses hingga 100 metrik (ukuran batch default) ke tujuan Anda. +- Memproses hingga 100 metrik (ukuran batch default) menjadi tujuan Anda. - Berhenti ketika selesai atau jika tidak ada metrik yang tersisa. **Jaga Agar Tetap Berjalan** -Untuk aplikasi langsung, Anda ingin pemrosesan berkelanjutan. Berikut opsi Anda: +Untuk aplikasi langsung, Anda akan ingin pemrosesan berkelanjutan. Berikut opsi Anda: - **Mode Daemon**: ```bash php vendor/bin/runway apm:worker --daemon ``` - Berjalan selamanya, memproses metrik saat datang. Bagus untuk dev atau pengaturan kecil. + Berjalan selamanya, memproses metrik saat mereka datang. Bagus untuk dev atau pengaturan kecil. - **Crontab**: Tambahkan ini ke crontab Anda (`crontab -e`): @@ -131,7 +132,7 @@ Untuk aplikasi langsung, Anda ingin pemrosesan berkelanjutan. Berikut opsi Anda: php vendor/bin/runway apm:worker --daemon # Ctrl+B, kemudian D untuk melepaskan; `tmux attach -t apm-worker` untuk terhubung kembali ``` - Menjaganya tetap berjalan bahkan jika Anda logout. + Menjaganya berjalan bahkan jika Anda logout. - **Penyesuaian Kustom**: ```bash @@ -153,14 +154,14 @@ php vendor/bin/runway apm:dashboard ``` **Apa ini?** -- Menghidupkan server PHP di `http://localhost:8001/apm/dashboard`. -- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan lainnya. +- Memutar server PHP di `http://localhost:8001/apm/dashboard`. +- Menampilkan log permintaan, rute lambat, tingkat kesalahan, dan banyak lagi. **Kustomisasi Itu**: ```bash php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php ``` -- `--host 0.0.0.0`: Dapat diakses dari IP mana pun (berguna untuk penampilan jarak jauh). +- `--host 0.0.0.0`: Dapat diakses dari IP mana pun (berguna untuk melihat jarak jauh). - `--port 8080`: Gunakan port berbeda jika 8001 sudah digunakan. - `--php-path`: Arahkan ke PHP jika tidak ada di PATH Anda. @@ -172,13 +173,13 @@ Untuk produksi, Anda mungkin harus mencoba beberapa teknik untuk menjalankan das - **Gunakan Reverse Proxy**: Siapkan Nginx atau Apache untuk meneruskan permintaan ke dashboard. - **SSH Tunnel**: Jika Anda bisa SSH ke server, gunakan `ssh -L 8080:localhost:8001 youruser@yourserver` untuk menyalurkan dashboard ke mesin lokal Anda. -- **VPN**: Jika server Anda di belakang VPN, hubungkan ke sana dan akses dashboard secara langsung. +- **VPN**: Jika server Anda di belakang VPN, hubungkan ke itu dan akses dashboard secara langsung. - **Konfigurasikan Firewall**: Buka port 8001 untuk IP Anda atau jaringan server. (atau port apa pun yang Anda atur). -- **Konfigurasikan Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda dapat mengonfigurasinya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard` +- **Konfigurasikan Apache/Nginx**: Jika Anda memiliki server web di depan aplikasi Anda, Anda bisa mengonfigurasinya ke domain atau subdomain. Jika Anda melakukan ini, Anda akan mengatur root dokumen ke `/path/to/your/project/vendor/flightphp/apm/dashboard` -#### Ingin dashboard berbeda? +#### Ingin dashboard yang berbeda? -Anda bisa membangun dashboard sendiri jika mau! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dashboard Anda sendiri! +Anda bisa membangun dashboard sendiri jika ingin! Lihat direktori vendor/flightphp/apm/src/apm/presenter untuk ide tentang cara menyajikan data untuk dashboard Anda sendiri! ## Fitur Dashboard @@ -188,14 +189,14 @@ Dashboard adalah markas APM Anda—berikut yang akan Anda lihat: - **Permintaan Terlambat**: 5 permintaan teratas yang memakan waktu (misalnya, “/api/heavy” di 2.5s). - **Rute Terlambat**: 5 rute teratas berdasarkan waktu rata-rata—bagus untuk melihat pola. - **Tingkat Kesalahan**: Persentase permintaan yang gagal (misalnya, 2.3% 500s). -- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—tahu skenario kasus terburuk Anda. +- **Persentil Latensi**: 95th (p95) dan 99th (p99) waktu respons—ketahui skenario kasus terburuk Anda. - **Grafik Kode Respons**: Visualisasikan 200s, 404s, 500s seiring waktu. - **Kueri/Middleware Panjang**: 5 panggilan database lambat teratas dan lapisan middleware. - **Cache Hit/Miss**: Seberapa sering cache Anda menyelamatkan hari. -**Tambahan**: +**Ekstra**: - Filter berdasarkan “Jam Terakhir,” “Hari Terakhir,” atau “Minggu Terakhir.” -- Toggle mode gelap untuk sesi malam larut. +- Toggle mode gelap untuk sesi malam hari itu. **Contoh**: Permintaan ke `/users` mungkin menunjukkan: @@ -218,7 +219,7 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ])); ``` -**Di mana munculnya?** +**Di mana itu muncul?** Di detail permintaan dashboard di bawah “Peristiwa Kustom”—dapat diperluas dengan format JSON yang bagus. **Kasus Penggunaan**: @@ -265,7 +266,7 @@ Sesuaikan worker sesuai keinginan Anda: - `--timeout 300`: Berhenti setelah 5 menit—bagus untuk pengujian. - `--max_messages 500`: Dibatasi pada 500 metrik—menjaganya terbatas. -- `--batch_size 200`: Memproses 200 sekaligus—menyeimbangkan kecepatan dan memori. +- `--batch_size 200`: Memproses 200 sekaligus—menseimbangkan kecepatan dan memori. - `--daemon`: Berjalan tanpa henti—ideal untuk pemantauan langsung. **Contoh**: @@ -276,7 +277,7 @@ Berjalan selama satu jam, memproses 100 metrik sekaligus. ## ID Permintaan di Aplikasi -Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda dapat menggunakan ID ini di aplikasi Anda untuk mengkorelasikan log dan metrik. Misalnya, Anda dapat menambahkan ID permintaan ke halaman kesalahan: +Setiap permintaan memiliki ID permintaan unik untuk pelacakan. Anda bisa menggunakan ID ini di aplikasi Anda untuk mengkorelasikan log dan metrik. Misalnya, Anda bisa menambahkan ID permintaan ke halaman kesalahan: ```php Flight::map('error', function($message) { @@ -293,7 +294,7 @@ Flight::map('error', function($message) { ## Upgrade -Jika Anda sedang meng-upgrade ke versi APM yang lebih baru, ada kemungkinan ada migrasi database yang perlu dijalankan. Anda bisa melakukannya dengan menjalankan perintah berikut: +Jika Anda sedang mengupgrade ke versi APM yang lebih baru, ada kemungkinan ada migrasi database yang perlu dijalankan. Anda bisa melakukan ini dengan menjalankan perintah berikut: ```bash php vendor/bin/runway apm:migrate @@ -302,15 +303,25 @@ Ini akan menjalankan migrasi apa pun yang diperlukan untuk memperbarui skema dat **Catatan:** Jika database APM Anda besar ukurannya, migrasi ini mungkin memakan waktu. Anda mungkin ingin menjalankan perintah ini selama jam non-puncak. +### Upgrade dari 0.4.3 -> 0.5.0 + +Jika Anda sedang mengupgrade dari 0.4.3 ke 0.5.0, Anda perlu menjalankan perintah berikut: + +```bash +php vendor/bin/runway apm:config-migrate +``` + +Ini akan memigrasikan konfigurasi Anda dari format lama menggunakan file `.runway-config.json` ke format baru yang menyimpan key/value di file `config.php`. + ## Membersihkan Data Lama Untuk menjaga database Anda rapi, Anda bisa membersihkan data lama. Ini sangat berguna jika Anda menjalankan aplikasi sibuk dan ingin menjaga ukuran database tetap terkendali. -Anda bisa melakukannya dengan menjalankan perintah berikut: +Anda bisa melakukan ini dengan menjalankan perintah berikut: ```bash php vendor/bin/runway apm:purge ``` -Ini akan menghapus semua data lebih tua dari 30 hari dari database. Anda bisa menyesuaikan jumlah hari dengan memberikan nilai berbeda ke opsi `--days`: +Ini akan menghapus semua data lebih tua dari 30 hari dari database. Anda bisa menyesuaikan jumlah hari dengan melewatkan nilai berbeda ke opsi `--days`: ```bash php vendor/bin/runway apm:purge --days 7 @@ -323,7 +334,7 @@ Tersangkut? Coba ini: - **Tidak Ada Data Dashboard?** - Apakah worker berjalan? Periksa `ps aux | grep apm:worker`. - - Path konfigurasi cocok? Verifikasi DSN di `.runway-config.json` menunjuk ke file nyata. + - Path konfigurasi cocok? Verifikasi DSN `.runway-config.json` mengarah ke file nyata. - Jalankan `php vendor/bin/runway apm:worker` secara manual untuk memproses metrik tertunda. - **Kesalahan Worker?** @@ -331,7 +342,7 @@ Tersangkut? Coba ini: - Periksa log PHP untuk jejak tumpukan. - **Dashboard Tidak Mau Mulai?** - - Port 8001 sedang digunakan? Gunakan `--port 8080`. + - Port 8001 digunakan? Gunakan `--port 8080`. - PHP tidak ditemukan? Gunakan `--php-path /usr/bin/php`. - Firewall memblokir? Buka port atau gunakan `--host localhost`. @@ -340,7 +351,7 @@ Tersangkut? Coba ini: - Kurangi ukuran batch: `--batch_size 20`. - **Tidak Melacak Pengecualian/Kesalahan?** - - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan menggantikan penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan kemudian pastikan bahwa `Flight::set('flight.handle_errors', true);` diatur. + - Jika Anda memiliki [Tracy](https://tracy.nette.org/) diaktifkan untuk proyek Anda, itu akan mengganti penanganan kesalahan Flight. Anda perlu menonaktifkan Tracy dan kemudian pastikan bahwa `Flight::set('flight.handle_errors', true);` diatur. - **Tidak Melacak Kueri Database?** - Pastikan Anda menggunakan `PdoWrapper` untuk koneksi database Anda. diff --git a/content/v3/id/awesome-plugins/awesome_plugins.md b/content/v3/id/awesome-plugins/awesome_plugins.md index 4535c3f0..50725e91 100644 --- a/content/v3/id/awesome-plugins/awesome_plugins.md +++ b/content/v3/id/awesome-plugins/awesome_plugins.md @@ -1,22 +1,22 @@ # Plugin Hebat -Flight sangat dapat dikembangkan. Ada sejumlah plugin yang dapat digunakan untuk menambahkan fungsionalitas ke aplikasi Flight Anda. Beberapa didukung secara resmi oleh Tim Flight dan yang lainnya adalah pustaka mikro/lite untuk membantu Anda memulai. +Flight sangat dapat diperluas. Ada sejumlah plugin yang dapat digunakan untuk menambahkan fungsionalitas ke aplikasi Flight Anda. Beberapa didukung secara resmi oleh Tim Flight dan yang lain adalah pustaka mikro/lite untuk membantu Anda memulai. ## Dokumentasi API Dokumentasi API sangat penting untuk API apa pun. Ini membantu pengembang memahami cara berinteraksi dengan API Anda dan apa yang diharapkan sebagai balasan. Ada beberapa alat yang tersedia untuk membantu Anda menghasilkan dokumentasi API untuk Proyek Flight Anda. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Posting blog yang ditulis oleh Daniel Schreiber tentang cara menggunakan Spesifikasi OpenAPI dengan FlightPHP untuk membangun API Anda menggunakan pendekatan API pertama. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Posting blog yang ditulis oleh Daniel Schreiber tentang cara menggunakan Spesifikasi OpenAPI dengan FlightPHP untuk membangun API Anda menggunakan pendekatan API first. - [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI adalah alat hebat untuk membantu Anda menghasilkan dokumentasi API untuk proyek Flight Anda. Ini sangat mudah digunakan dan dapat disesuaikan sesuai kebutuhan Anda. Ini adalah pustaka PHP untuk membantu Anda menghasilkan dokumentasi Swagger. ## Pemantauan Kinerja Aplikasi (APM) -Pemantauan Kinerja Aplikasi (APM) sangat penting untuk aplikasi apa pun. Ini membantu Anda memahami bagaimana aplikasi Anda berkinerja dan di mana kemacetan terjadi. Ada sejumlah alat APM yang dapat digunakan dengan Flight. -- resmi [flightphp/apm](/awesome-plugins/apm) - Flight APM adalah pustaka APM sederhana yang dapat digunakan untuk memantau aplikasi Flight Anda. Ini dapat digunakan untuk memantau kinerja aplikasi Anda dan membantu Anda mengidentifikasi kemacetan. +Pemantauan Kinerja Aplikasi (APM) sangat penting untuk aplikasi apa pun. Ini membantu Anda memahami bagaimana aplikasi Anda berkinerja dan di mana titik lemahnya. Ada sejumlah alat APM yang dapat digunakan dengan Flight. +- resmi [flightphp/apm](/awesome-plugins/apm) - Flight APM adalah pustaka APM sederhana yang dapat digunakan untuk memantau aplikasi Flight Anda. Ini dapat digunakan untuk memantau kinerja aplikasi Anda dan membantu Anda mengidentifikasi titik lemah. -## Asinkron +## Async -Flight sudah merupakan kerangka kerja yang cepat, tetapi menambahkan mesin turbo padanya membuat semuanya lebih menyenangkan (dan menantang)! +Flight sudah merupakan framework yang cepat, tetapi menambahkan mesin turbo padanya membuat semuanya lebih menyenangkan (dan menantang)! - [flightphp/async](/awesome-plugins/async) - Pustaka Async Flight resmi. Pustaka ini adalah cara sederhana untuk menambahkan pemrosesan asinkron ke aplikasi Anda. Ini menggunakan Swoole/Openswoole di balik layar untuk menyediakan cara sederhana dan efektif untuk menjalankan tugas secara asinkron. @@ -24,13 +24,13 @@ Flight sudah merupakan kerangka kerja yang cepat, tetapi menambahkan mesin turbo Otorisasi dan Izin sangat penting untuk aplikasi apa pun yang memerlukan kontrol atas siapa yang dapat mengakses apa. -- resmi [flightphp/permissions](/awesome-plugins/permissions) - Pustaka Permissions Flight resmi. Pustaka ini adalah cara sederhana untuk menambahkan izin tingkat pengguna dan aplikasi ke aplikasi Anda. +- resmi [flightphp/permissions](/awesome-plugins/permissions) - Pustaka Permissions Flight resmi. Pustaka ini adalah cara sederhana untuk menambahkan izin tingkat pengguna dan aplikasi ke aplikasi Anda. ## Penyimpanan Cache Penyimpanan cache adalah cara hebat untuk mempercepat aplikasi Anda. Ada sejumlah pustaka caching yang dapat digunakan dengan Flight. -- resmi [flightphp/cache](/awesome-plugins/php-file-cache) - Kelas caching dalam file PHP yang ringan, sederhana, dan mandiri +- resmi [flightphp/cache](/awesome-plugins/php-file-cache) - Kelas caching in-file PHP yang ringan, sederhana, dan standalone ## CLI @@ -40,34 +40,34 @@ Aplikasi CLI adalah cara hebat untuk berinteraksi dengan aplikasi Anda. Anda dap ## Cookies -Cookies adalah cara hebat untuk menyimpan bit data kecil di sisi klien. Mereka dapat digunakan untuk menyimpan preferensi pengguna, pengaturan aplikasi, dan banyak lagi. +Cookies adalah cara hebat untuk menyimpan potongan data kecil di sisi klien. Mereka dapat digunakan untuk menyimpan preferensi pengguna, pengaturan aplikasi, dan banyak lagi. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie adalah pustaka PHP yang menyediakan cara sederhana dan efektif untuk mengelola cookies. ## Debugging -Debugging sangat penting saat Anda mengembangkan di lingkungan lokal Anda. Ada beberapa plugin yang dapat meningkatkan pengalaman debugging Anda. +Debugging sangat penting ketika Anda mengembangkan di lingkungan lokal Anda. Ada beberapa plugin yang dapat meningkatkan pengalaman debugging Anda. -- [tracy/tracy](/awesome-plugins/tracy) - Ini adalah penanganan kesalahan lengkap yang dapat digunakan dengan Flight. Ini memiliki sejumlah panel yang dapat membantu Anda mendiagnosis aplikasi Anda. Ini juga sangat mudah untuk diperluas dan menambahkan panel Anda sendiri. +- [tracy/tracy](/awesome-plugins/tracy) - Ini adalah penanganan kesalahan lengkap yang dapat digunakan dengan Flight. Ini memiliki sejumlah panel yang dapat membantu Anda mendebug aplikasi Anda. Ini juga sangat mudah untuk diperluas dan menambahkan panel Anda sendiri. - resmi [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Digunakan dengan penanganan kesalahan [Tracy](/awesome-plugins/tracy), plugin ini menambahkan beberapa panel tambahan untuk membantu debugging khusus untuk proyek Flight. ## Database -Database adalah inti dari sebagian besar aplikasi. Inilah cara Anda menyimpan dan mengambil data. Beberapa pustaka database hanyalah pembungkus untuk menulis kueri dan beberapa adalah ORM lengkap. +Database adalah inti dari sebagian besar aplikasi. Inilah cara Anda menyimpan dan mengambil data. Beberapa pustaka database hanyalah wrapper untuk menulis query dan beberapa adalah ORM lengkap. -- resmi [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Pembungkus PDO Flight resmi yang merupakan bagian dari inti. Ini adalah pembungkus sederhana untuk membantu menyederhanakan proses penulisan kueri dan mengeksekusinya. Ini bukan ORM. +- resmi [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO Flight resmi yang merupakan bagian dari inti. Ini adalah wrapper sederhana untuk membantu menyederhanakan proses penulisan query dan mengeksekusinya. Ini bukan ORM. - resmi [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord Flight resmi. Pustaka kecil yang hebat untuk dengan mudah mengambil dan menyimpan data di database Anda. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin untuk melacak semua perubahan database untuk proyek Anda. ## Enkripsi -Enkripsi sangat penting untuk aplikasi apa pun yang menyimpan data sensitif. Mengenkripsi dan mendekripsi data tidak terlalu sulit, tetapi menyimpan kunci enkripsi dengan benar [bisa](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [jadi](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [sulit](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Hal yang paling penting adalah jangan pernah menyimpan kunci enkripsi Anda di direktori publik atau mengkomitnya ke repositori kode Anda. +Enkripsi sangat penting untuk aplikasi apa pun yang menyimpan data sensitif. Mengenkripsi dan mendekripsi data tidak terlalu sulit, tetapi menyimpan kunci enkripsi dengan benar [bisa](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [menjadi](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [sulit](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Hal terpenting adalah jangan pernah menyimpan kunci enkripsi Anda di direktori publik atau mengommitnya ke repositori kode Anda. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Ini adalah pustaka yang dapat digunakan untuk mengenkripsi dan mendekripsi data. Memulai dan menjalankannya cukup sederhana untuk mulai mengenkripsi dan mendekripsi data. ## Antrian Pekerjaan -Antrian pekerjaan sangat membantu untuk memproses tugas secara asinkron. Ini bisa berupa mengirim email, memproses gambar, atau apa pun yang tidak perlu dilakukan secara real-time. +Antrian pekerjaan sangat membantu untuk memproses tugas secara asinkron. Ini bisa berupa mengirim email, memproses gambar, atau apa pun yang tidak perlu dilakukan secara real time. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue adalah pustaka yang dapat digunakan untuk memproses pekerjaan secara asinkron. Ini dapat digunakan dengan beanstalkd, MySQL/MariaDB, SQLite, dan PostgreSQL. @@ -75,23 +75,23 @@ Antrian pekerjaan sangat membantu untuk memproses tugas secara asinkron. Ini bis Sesi tidak terlalu berguna untuk API tetapi untuk membangun aplikasi web, sesi bisa sangat penting untuk mempertahankan status dan informasi login. -- resmi [flightphp/session](/awesome-plugins/session) - Pustaka Sesi Flight resmi. Ini adalah pustaka sesi sederhana yang dapat digunakan untuk menyimpan dan mengambil data sesi. Ini menggunakan penanganan sesi bawaan PHP. +- resmi [flightphp/session](/awesome-plugins/session) - Pustaka Session Flight resmi. Ini adalah pustaka sesi sederhana yang dapat digunakan untuk menyimpan dan mengambil data sesi. Ini menggunakan penanganan sesi bawaan PHP. - [Ghostff/Session](/awesome-plugins/ghost-session) - Manajer Sesi PHP (non-blocking, flash, segment, enkripsi sesi). Menggunakan PHP open_ssl untuk enkripsi/dekripsi data sesi opsional. ## Templating Templating adalah inti dari aplikasi web apa pun dengan UI. Ada sejumlah mesin templating yang dapat digunakan dengan Flight. -- deprecated [flightphp/core View](/learn#views) - Ini adalah mesin templating dasar yang merupakan bagian dari inti. Tidak disarankan untuk digunakan jika Anda memiliki lebih dari beberapa halaman di proyek Anda. +- deprecated [flightphp/core View](/learn#views) - Ini adalah mesin templating dasar yang merupakan bagian dari inti. Tidak direkomendasikan untuk digunakan jika Anda memiliki lebih dari beberapa halaman di proyek Anda. - [latte/latte](/awesome-plugins/latte) - Latte adalah mesin templating lengkap yang sangat mudah digunakan dan terasa lebih dekat dengan sintaks PHP daripada Twig atau Smarty. Ini juga sangat mudah untuk diperluas dan menambahkan filter dan fungsi Anda sendiri. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate adalah mesin template PHP yang kuat dengan kompilasi aset, pewarisan template, dan pemrosesan variabel. Fitur minifikasi CSS/JS otomatis, caching, pengkodean Base64, dan integrasi kerangka kerja Flight PHP opsional. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate adalah mesin template PHP yang kuat dengan kompilasi aset, pewarisan template, dan pemrosesan variabel. Fitur minifikasi CSS/JS otomatis, caching, pengkodean Base64, dan integrasi framework PHP Flight opsional. ## Integrasi WordPress Ingin menggunakan Flight di proyek WordPress Anda? Ada plugin yang berguna untuk itu! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Plugin WordPress ini memungkinkan Anda menjalankan Flight tepat di samping WordPress. Ini sempurna untuk menambahkan API khusus, mikroservis, atau bahkan aplikasi lengkap ke situs WordPress Anda menggunakan kerangka kerja Flight. Sangat berguna jika Anda ingin yang terbaik dari kedua dunia! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Plugin WordPress ini memungkinkan Anda menjalankan Flight tepat di samping WordPress. Ini sempurna untuk menambahkan API khusus, microservices, atau bahkan aplikasi lengkap ke situs WordPress Anda menggunakan framework Flight. Sangat berguna jika Anda ingin yang terbaik dari kedua dunia! -## Kontribusi +## Berkontribusi Punya plugin yang ingin Anda bagikan? Kirimkan pull request untuk menambahkannya ke daftar! \ No newline at end of file diff --git a/content/v3/id/awesome-plugins/comment_template.md b/content/v3/id/awesome-plugins/comment_template.md index ea132625..81a4da43 100644 --- a/content/v3/id/awesome-plugins/comment_template.md +++ b/content/v3/id/awesome-plugins/comment_template.md @@ -1,11 +1,11 @@ # CommentTemplate -[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) adalah mesin template PHP yang kuat dengan kompilasi aset, pewarisan template, dan pemrosesan variabel. Ini menyediakan cara sederhana namun fleksibel untuk mengelola template dengan minifikasi CSS/JS bawaan dan caching. +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) adalah mesin template PHP yang kuat dengan kompilasi aset, pewarisan template, dan pemrosesan variabel. Ini menyediakan cara sederhana namun fleksibel untuk mengelola template dengan minifikasi CSS/JS dan caching bawaan. ## Fitur -- **Pewarisan Template**: Gunakan layout dan sertakan template lain -- **Kompilasi Aset**: Minifikasi CSS/JS otomatis dan caching +- **Pewarisan Template**: Gunakan tata letak dan sertakan template lain +- **Kompilasi Aset**: Minifikasi dan caching CSS/JS otomatis - **Pemrosesan Variabel**: Variabel template dengan filter dan perintah - **Encoding Base64**: Aset inline sebagai data URI - **Integrasi Framework Flight**: Integrasi opsional dengan framework PHP Flight @@ -20,7 +20,7 @@ composer require knifelemon/comment-template ## Konfigurasi Dasar -Ada beberapa opsi konfigurasi dasar untuk memulai. Anda dapat membaca lebih lanjut tentangnya di [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate). +Ada beberapa opsi konfigurasi dasar untuk memulai. Anda dapat membaca lebih lanjut tentangnya di [Repo CommentTemplate](https://github.com/KnifeLemon/CommentTemplate). ### Metode 1: Menggunakan Fungsi Callback @@ -63,9 +63,9 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__ . '/public', // publicPath - tempat aset akan disajikan - __DIR__ . '/views', // skinPath - tempat file template disimpan - 'assets', // assetPath - tempat aset yang dikompilasi akan disimpan + __DIR__, // publicPath - direktori root (tempat index.php berada) + 'views', // skinPath - path template (mendukung relatif/absolut) + 'assets', // assetPath - path aset yang dikompilasi (mendukung relatif/absolut) '.php' // fileExtension - ekstensi file template ]); @@ -74,84 +74,88 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` -### Konfigurasi Path +## Konfigurasi Path -CommentTemplate mendukung path relatif dan absolut dengan resolusi cerdas: +CommentTemplate menyediakan penanganan path yang cerdas untuk path relatif dan absolut: -#### Path Relatif -```php -setPublicPath(__DIR__ . '/public'); -$engine->setSkinPath('templates'); // Akan di-resolve ke {publicPath}/templates -$engine->setAssetPath('compiled'); // Akan di-resolve ke {publicPath}/compiled +**Path Publik** adalah direktori root aplikasi web Anda, biasanya tempat `index.php` berada. Ini adalah root dokumen yang disajikan oleh server web. -// Juga dapat menggunakan subdirektori -$engine->setSkinPath('views/templates'); -$engine->setAssetPath('assets/compiled'); +```php +// Contoh: jika index.php Anda berada di /var/www/html/myapp/index.php +$template->setPublicPath('/var/www/html/myapp'); // Direktori root + +// Contoh Windows: jika index.php Anda berada di C:\xampp\htdocs\myapp\index.php +$template->setPublicPath('C:\\xampp\\htdocs\\myapp'); ``` -#### Path Absolut +### Konfigurasi Path Template + +Path template mendukung path relatif dan absolut: + ```php -setPublicPath('/var/www/html/myapp'); // Direktori root (tempat index.php berada) + +// Path relatif - otomatis digabungkan dengan path publik +$template->setSkinPath('views'); // → /var/www/html/myapp/views/ +$template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ -// Path absolut lengkap -$engine->setSkinPath('/var/www/templates'); -$engine->setAssetPath('/var/www/public/assets'); +// Path absolut - digunakan apa adanya (Unix/Linux) +$template->setSkinPath('/var/www/templates'); // → /var/www/templates/ +$template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ -// Path Windows -$engine->setSkinPath('C:\xampp\htdocs\templates'); -$engine->setAssetPath('C:\xampp\htdocs\public\assets'); +// Path absolut Windows +$template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ +$template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ -// Path UNC (Windows network) -$engine->setSkinPath('\\server\share\templates'); -$engine->setAssetPath('\\server\share\public\assets'); +// Path UNC (share jaringan Windows) +$template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ ``` -#### Path Campuran +### Konfigurasi Path Aset + +Path aset juga mendukung path relatif dan absolut: + ```php -setPublicPath('/var/www/public'); +// Path relatif - otomatis digabungkan dengan path publik +$template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ +$template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ -// Campurkan path relatif dan absolut berdasarkan kebutuhan -$engine->setSkinPath('views'); // Relatif: /var/www/public/views -$engine->setAssetPath('/tmp/compiled-assets'); // Absolut: /tmp/compiled-assets -``` +// Path absolut - digunakan apa adanya (Unix/Linux) +$template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ +$template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ -#### Tips Praktis +// Path absolut Windows +$template->setAssetPath('C:\\www\\static'); // → C:\www\static\ +$template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ -**Pengembangan Lokal:** -```php -$engine->setPublicPath(__DIR__ . '/public'); -$engine->setSkinPath('views'); // Mudah untuk pengembangan -$engine->setAssetPath('assets'); // Aset terorganisir dalam struktur proyek +// Path UNC (share jaringan Windows) +$template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ ``` -**Produksi:** -```php -$engine->setPublicPath('/var/www/myapp/public'); -$engine->setSkinPath('/var/www/myapp/templates'); // Path absolut untuk kontrol penuh -$engine->setAssetPath('/var/www/myapp/public/dist'); // Aset di direktori yang dapat diakses web -``` +**Deteksi Path Cerdas:** -**Docker/Container:** -```php -$engine->setPublicPath('/app/public'); -$engine->setSkinPath('/app/resources/views'); -$engine->setAssetPath('/app/public/assets'); -``` +- **Path Relatif**: Tidak ada pemisah awal (`/`, `\`) atau huruf drive +- **Absolut Unix**: Dimulai dengan `/` (misalnya, `/var/www/assets`) +- **Absolut Windows**: Dimulai dengan huruf drive (misalnya, `C:\www`, `D:/assets`) +- **Path UNC**: Dimulai dengan `\\` (misalnya, `\\server\share`) -CommentTemplate secara otomatis mendeteksi jenis path dan menanganinya dengan benar, memberikan fleksibilitas maksimum untuk setup deployment yang berbeda. +**Cara Kerjanya:** + +- Semua path otomatis diselesaikan berdasarkan tipe (relatif vs absolut) +- Path relatif digabungkan dengan path publik +- `@css` dan `@js` membuat file yang diminifikasi di: `{resolvedAssetPath}/css/` atau `{resolvedAssetPath}/js/` +- `@asset` menyalin file tunggal ke: `{resolvedAssetPath}/{relativePath}` +- `@assetDir` menyalin direktori ke: `{resolvedAssetPath}/{relativePath}` +- Caching cerdas: file hanya disalin ketika sumber lebih baru daripada tujuan ## Direktif Template -### Pewarisan Layout +### Pewarisan Tata Letak -Gunakan layout untuk membuat struktur umum: +Gunakan tata letak untuk membuat struktur umum: **layout/global_layout.php**: ```html @@ -173,7 +177,7 @@ Gunakan layout untuk membuat struktur umum:

          {$content}

          ``` -### Pengelolaan Aset +### Manajemen Aset #### File CSS ```html @@ -185,9 +189,9 @@ Gunakan layout untuk membuat struktur umum: CommentTemplate mendukung strategi pemuatan JavaScript yang berbeda: ```html - - - + + + @@ -202,7 +206,7 @@ CommentTemplate juga memproses direktif aset dalam file CSS dan JavaScript selam **Contoh CSS:** ```css -/* Di file CSS Anda */ +/* Dalam file CSS Anda */ @font-face { font-family: 'CustomFont'; src: url('') format('woff2'); @@ -219,7 +223,7 @@ CommentTemplate juga memproses direktif aset dalam file CSS dan JavaScript selam **Contoh JavaScript:** ```javascript -/* Di file JS Anda */ +/* Dalam file JS Anda */ const fontUrl = ''; const imageData = ''; ``` @@ -248,7 +252,7 @@ const imageData = ''; Hero Banner Unduh Brosur - + ``` @@ -286,44 +290,44 @@ const imageData = ''; ```html {$title|upper} {$content|lower} -{$html|striptag} +{$html|striptag} {$text|escape} {$multiline|nl2br} {$html|br2nl} -{$description|trim} +{$description|trim} {$subject|title} ``` #### Perintah Variabel ```html -{$title|default=Default Title} +{$title|default=Default Title} {$name|concat= (Admin)} ``` -#### Rantai Beberapa Filter +#### Perintah Variabel ```html {$content|striptag|trim|escape} ``` ### Komentar -Komentar template sepenuhnya dihapus dari output dan tidak muncul di HTML final: +Komentar template sepenuhnya dihapus dari output dan tidak akan muncul di HTML akhir: ```html {* Ini adalah komentar template satu baris *} {* - Ini adalah komentar template - multi-baris yang mencakup - beberapa baris + Ini adalah komentar + template multi-baris + yang meliputi beberapa baris *}

          {$title}

          -{* Komentar debugging: memeriksa apakah variabel title berfungsi *} +{* Komentar debug: memeriksa apakah variabel title berfungsi *}

          {$content}

          ``` -**Catatan**: Komentar template `{* ... *}` berbeda dari komentar HTML ``. Komentar template dihapus selama pemrosesan dan tidak pernah sampai ke browser. +**Catatan**: Komentar template `{* ... *}` berbeda dari komentar HTML ``. Komentar template dihapus selama pemrosesan dan tidak pernah mencapai browser. ## Struktur Proyek Contoh diff --git a/content/v3/id/awesome-plugins/runway.md b/content/v3/id/awesome-plugins/runway.md index db09353b..bd6c86ca 100644 --- a/content/v3/id/awesome-plugins/runway.md +++ b/content/v3/id/awesome-plugins/runway.md @@ -1,8 +1,8 @@ -# Jalur +# Runway -Jalur adalah aplikasi CLI yang membantu Anda mengelola aplikasi Flight Anda. Ini dapat menghasilkan pengontrol, menampilkan semua rute, dan banyak lagi. Ini didasarkan pada pustaka [adhocore/php-cli](https://github.com/adhocore/php-cli) yang sangat baik. +Runway adalah aplikasi CLI yang membantu Anda mengelola aplikasi Flight Anda. Ini dapat menghasilkan controller, menampilkan semua rute, dan banyak lagi. Ini didasarkan pada pustaka [adhocore/php-cli](https://github.com/adhocore/php-cli) yang luar biasa. -Klik [di sini](https://github.com/flightphp/runway) untuk melihat kodenya. +Klik [di sini](https://github.com/flightphp/runway) untuk melihat kode. ## Instalasi @@ -14,16 +14,16 @@ composer require flightphp/runway ## Konfigurasi Dasar -Kali pertama Anda menjalankan Jalur, itu akan memandu Anda melalui proses pengaturan dan membuat file konfigurasi `.runway.json` di akar proyek Anda. File ini akan berisi beberapa konfigurasi yang diperlukan agar Jalur berfungsi dengan baik. +Pada pertama kali Anda menjalankan Runway, itu akan menjalankan Anda melalui proses pengaturan dan membuat file konfigurasi `.runway.json` di root proyek Anda. File ini akan berisi beberapa konfigurasi yang diperlukan agar Runway bekerja dengan benar. ## Penggunaan -Jalur memiliki sejumlah perintah yang dapat Anda gunakan untuk mengelola aplikasi Flight Anda. Ada dua cara mudah untuk menggunakan Jalur. +Runway memiliki sejumlah perintah yang dapat Anda gunakan untuk mengelola aplikasi Flight Anda. Ada dua cara mudah untuk menggunakan Runway. -1. Jika Anda menggunakan proyek tulang, Anda dapat menjalankan `php runway [command]` dari akar proyek Anda. -1. Jika Anda menggunakan Jalur sebagai paket yang diinstal melalui composer, Anda dapat menjalankan `vendor/bin/runway [command]` dari akar proyek Anda. +1. Jika Anda menggunakan proyek skeleton, Anda dapat menjalankan `php runway [command]` dari root proyek Anda. +1. Jika Anda menggunakan Runway sebagai paket yang diinstal melalui composer, Anda dapat menjalankan `vendor/bin/runway [command]` dari root proyek Anda. -Untuk setiap perintah, Anda dapat melewatkan bendera `--help` untuk mendapatkan informasi lebih lanjut tentang cara menggunakan perintah tersebut. +Untuk perintah apa pun, Anda dapat memberikan flag `--help` untuk mendapatkan informasi lebih lanjut tentang cara menggunakan perintah tersebut. ```bash php runway routes --help @@ -31,23 +31,23 @@ php runway routes --help Berikut adalah beberapa contoh: -### Menghasilkan Pengontrol +### Menghasilkan Controller -Berdasarkan konfigurasi dalam file `.runway.json` Anda, lokasi default akan menghasilkan pengontrol untuk Anda di direktori `app/controllers/`. +Berdasarkan konfigurasi di file `.runway.json` Anda, lokasi default akan menghasilkan controller untuk Anda di direktori `app/controllers/`. ```bash php runway make:controller MyController ``` -### Menghasilkan Model Rekaman Aktif +### Menghasilkan Model Active Record -Berdasarkan konfigurasi dalam file `.runway.json` Anda, lokasi default akan menghasilkan pengontrol untuk Anda di direktori `app/records/`. +Berdasarkan konfigurasi di file `.runway.json` Anda, lokasi default akan menghasilkan controller untuk Anda di direktori `app/records/`. ```bash php runway make:record users ``` -Jika misalnya Anda memiliki tabel `users` dengan skema berikut: `id`, `name`, `email`, `created_at`, `updated_at`, sebuah file yang mirip dengan yang berikut akan dibuat di file `app/records/UserRecord.php`: +Misalnya, jika Anda memiliki tabel `users` dengan skema berikut: `id`, `name`, `email`, `created_at`, `updated_at`, file serupa dengan yang berikut akan dibuat di file `app/records/UserRecord.php`: ```php $config Konfigurasi JSON dari .runway-config.json + * @param array $config JSON config from .runway-config.json */ public function __construct(array $config) { - parent::__construct('make:example', 'Buat contoh untuk dokumentasi', $config); - $this->argument('', 'Nama gif lucu'); + parent::__construct('make:example', 'Create an example for the documentation', $config); + $this->argument('', 'The name of the funny gif'); } /** - * Menjalankan fungsi + * Executes the function * * @return void */ - public function execute(string $controller) + public function execute() { $io = $this->app()->io(); - $io->info('Membuat contoh...'); + $io->info('Creating example...'); - // Lakukan sesuatu di sini + // Do something here - $io->ok('Contoh dibuat!'); + $io->ok('Example created!'); } } ``` -Lihat [adhocore/php-cli Documentation](https://github.com/adhocore/php-cli) untuk informasi lebih lanjut tentang cara membangun perintah kustom Anda sendiri ke dalam aplikasi Flight Anda! +Lihat [Dokumentasi adhocore/php-cli](https://github.com/adhocore/php-cli) untuk informasi lebih lanjut tentang cara membangun perintah kustom Anda sendiri ke dalam aplikasi Flight! ### Konfigurasi -Jika Anda perlu menyesuaikan konfigurasi untuk Jalur, Anda dapat membuat file `.runway-config.json` di akar proyek Anda. Di bawah ini adalah beberapa konfigurasi tambahan yang dapat Anda tetapkan: +Jika Anda perlu menyesuaikan konfigurasi untuk Runway, Anda dapat membuat file `.runway-config.json` di root proyek Anda. Berikut adalah beberapa konfigurasi tambahan yang dapat Anda atur: ```js { - // Ini adalah tempat direktori aplikasi Anda berada + // This is where your application directory is located "app_root": "app/", - // Ini adalah direktori tempat file indeks akar Anda berada + // This is the directory where your root index file is located "index_root": "public/", - // Ini adalah jalur ke akar proyek lainnya + // These are the paths to the roots of other projects "root_paths": [ "/home/user/different-project", "/var/www/another-project" ], - // Jalur dasar kemungkinan besar tidak perlu dikonfigurasi, tapi ada di sini jika Anda menginginkannya + // Base paths most likely don't need to be configured, but it's here if you want it "base_paths": { - "/includes/libs/vendor", // jika Anda memiliki jalur yang sangat unik untuk direktori vendor Anda atau sesuatu + "/includes/libs/vendor", // if you have a really unique path for your vendor directory or something }, - // Jalur akhir adalah lokasi dalam proyek untuk mencari file perintah + // Final paths are locations within a project to search for the command files "final_paths": { "src/diff-path/commands", "app/module/admin/commands", }, - // Jika Anda ingin hanya menambahkan jalur lengkap, silakan saja (absolut atau relatif terhadap akar proyek) + // If you want to just add the full path, go right ahead (absolute or relative to project root) "paths": [ "/home/user/different-project/src/diff-path/commands", "/var/www/another-project/app/module/admin/commands", diff --git a/content/v3/id/examples.md b/content/v3/id/examples.md index 500af2a7..be0c7e94 100644 --- a/content/v3/id/examples.md +++ b/content/v3/id/examples.md @@ -1,23 +1,24 @@ -# Perlu Mulai Cepat? +# Butuh mulai cepat? Anda memiliki dua opsi untuk memulai proyek Flight baru: - [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Contoh yang lebih lengkap dengan controller dan view. - [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Satu file tunggal yang mencakup semua yang Anda butuhkan untuk menjalankan aplikasi Anda dalam satu file sederhana. -Contoh yang disumbangkan oleh komunitas: +Contoh yang dikontribusikan oleh komunitas: -- [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP dengan direktori Laravel, dengan tooling PHP + GH Actions +- [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP dengan direktori Laravel, dengan alat PHP + GH Actions - [fleact](https://github.com/flightphp/fleact) - Kit starter FlightPHP dengan integrasi ReactJS. - [flastro](https://github.com/flightphp/flastro) - Kit starter FlightPHP dengan integrasi Astro. - [velt](https://github.com/flightphp/velt) - Velt adalah template starter Svelte yang cepat dan mudah dengan backend FlightPHP. ## Butuh Inspirasi? -Meskipun ini tidak secara resmi disponsori oleh Tim Flight, ini bisa memberi Anda ide tentang cara menyusun proyek Anda sendiri yang dibangun dengan Flight! +Meskipun ini tidak secara resmi disponsori oleh Tim Flight, ini bisa memberikan Anda ide tentang cara menyusun proyek Anda sendiri yang dibangun dengan Flight! -- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify adalah aplikasi satu halaman yang menghubungkan penyelenggara acara dengan peserta. Dibangun dengan PHP (FlightPHP), JavaScript, dan MySQL, fitur autentikasi JWT, manajemen acara, dan dokumentasi API RESTful menggunakan OpenAPI. -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental adalah aplikasi web penyewaan mobil satu halaman yang ramah seluler, dibangun dengan PHP (FlightPHP), JavaScript, dan MySQL. Mendukung pendaftaran pengguna, penelusuran, dan pemesanan mobil, sementara admin dapat mengelola mobil, pengguna, dan pemesanan. Aplikasi ini memiliki API REST, autentikasi JWT, dan desain responsif untuk pengalaman penyewaan modern. +- [ASC REST API Spell Checker](https://github.com/AlMosahih-ASC/asc-api-sample) - API REST ringan untuk pemeriksaan ejaan Arab yang dibangun dengan FlightPHP dan pustaka ArPHP. API ini menyediakan kemampuan pemeriksaan ejaan teks Arab termasuk deteksi kata salah eja dan saran koreksi. +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify adalah aplikasi single-page yang menghubungkan penyelenggara acara dengan peserta. Dibangun dengan PHP (FlightPHP), JavaScript, dan MySQL, ini menampilkan autentikasi JWT, manajemen acara, dan dokumentasi API RESTful menggunakan OpenAPI. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental adalah aplikasi web penyewaan mobil single-page yang ramah seluler yang dibangun dengan PHP (FlightPHP), JavaScript, dan MySQL. Ini mendukung pendaftaran pengguna, penelusuran, dan pemesanan mobil, sementara admin dapat mengelola mobil, pengguna, dan pemesanan. Aplikasi ini menampilkan API REST, autentikasi JWT, dan desain responsif untuk pengalaman penyewaan modern. - [Decay](https://github.com/boxybird/decay) - Flight v3 dengan HTMX dan SleekDB semuanya tentang zombie! ([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 dengan Middleware, Controllers, Active Record, dan Latte. - [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Proyek API CRUD sederhana menggunakan framework Flight, yang menyediakan struktur dasar bagi pengguna baru untuk dengan cepat menyiapkan aplikasi PHP dengan operasi CRUD dan konektivitas database. Proyek ini mendemonstrasikan cara menggunakan Flight untuk pengembangan API RESTful, menjadikannya alat pembelajaran ideal bagi pemula dan kit starter yang berguna bagi pengembang yang lebih berpengalaman. @@ -31,7 +32,7 @@ Meskipun ini tidak secara resmi disponsori oleh Tim Flight, ini bisa memberi And - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework autentikasi siap produksi yang menghemat waktu pengembangan berminggu-minggu. Fitur keamanan tingkat enterprise: 2FA/TOTP, integrasi LDAP, Azure SSO, pembatasan laju cerdas, sidik jari sesi, perlindungan brute-force, dasbor analitik keamanan, logging audit komprehensif, dan kontrol akses berbasis peran yang granular. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Framework autentikasi siap produksi yang menghemat minggu pengembangan Anda. Fitur keamanan tingkat enterprise: 2FA/TOTP, integrasi LDAP, Azure SSO, pembatasan laju cerdas, fingerprinting sesi, perlindungan brute-force, dashboard analitik keamanan, logging audit komprehensif, dan kontrol akses berbasis peran granular. ## Ingin Berbagi Contoh Anda Sendiri? diff --git a/content/v3/ja/awesome-plugins/active_record.md b/content/v3/ja/awesome-plugins/active_record.md index 52999a78..a6d44e8c 100644 --- a/content/v3/ja/awesome-plugins/active_record.md +++ b/content/v3/ja/awesome-plugins/active_record.md @@ -1,12 +1,12 @@ -# Flight アクティブレコード +# Flight Active Record -アクティブレコードとは、データベースのエンティティをPHPオブジェクトにマッピングすることです。簡単に言えば、データベースにユーザーテーブルがある場合、そのテーブルの行を`User`クラスと`$user`オブジェクトに「翻訳」することができます。 [基本例](#basic-example)を参照してください。 +アクティブ レコードは、データベース エンティティを PHP オブジェクトにマッピングするものです。簡単に言うと、データベースに users テーブルがある場合、そのテーブルの行をコードベース内の `User` クラスと `$user` オブジェクトに「変換」できます。[基本例](#basic-example) を参照してください。 -GitHubのリポジトリについては[こちら](https://github.com/flightphp/active-record)をクリックしてください。 +GitHub のリポジトリは [こちら](https://github.com/flightphp/active-record) をクリックしてください。 -## 基本例 +## Basic Example -次のテーブルがあると仮定しましょう: +以下のテーブルがあると仮定しましょう: ```sql CREATE TABLE users ( @@ -20,9 +20,9 @@ CREATE TABLE users ( ```php /** - * アクティブレコードクラスは通常単数です + * ActiveRecord クラスは通常単数形です * - * ここにテーブルのプロパティをコメントとして追加することを強くお勧めします + * テーブルのプロパティをコメントとしてここに追加することを強く推奨します * * @property int $id * @property string $name @@ -31,26 +31,26 @@ CREATE TABLE users ( class User extends flight\ActiveRecord { public function __construct($database_connection) { - // このように設定できます + // この方法で設定できます parent::__construct($database_connection, 'users'); - // またはこのように + // またはこの方法で parent::__construct($database_connection, null, [ 'table' => 'users']); } } ``` -さあ、魔法が起こるのを見てみましょう! +今、マジックが起こります! ```php -// sqliteの場合 -$database_connection = new PDO('sqlite:test.db'); // これは単なる例ですので、実際のデータベース接続を使用することになります +// SQLite の場合 +$database_connection = new PDO('sqlite:test.db'); // これは単なる例です。本物のデータベース接続を使用するはずです -// mysqlの場合 +// MySQL の場合 $database_connection = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'username', 'password'); -// またはmysqli +// または mysqli $database_connection = new mysqli('localhost', 'username', 'password', 'test_db'); -// または非オブジェクト型のmysqli作成 +// またはオブジェクトベースでない mysqli の作成 $database_connection = mysqli_connect('localhost', 'username', 'password', 'test_db'); $user = new User($database_connection); @@ -64,79 +64,79 @@ echo $user->id; // 1 $user->name = 'Joseph Mamma'; $user->password = password_hash('some cool password again!!!'); $user->insert(); -// ここで $user->save() を使用することはできません。更新として考えられてしまいます! +// ここで $user->save() を使用できません。更新と判断されるためです! echo $user->id; // 2 ``` -新しいユーザーを追加するのはとても簡単でした!データベースにユーザーロウがあるので、どうやって取り出すことができますか? +新しいユーザーを追加するのに、これほど簡単だったとは!データベースにユーザーの行が存在する今、それを引き出すにはどうしますか? ```php -$user->find(1); // データベースで id = 1 を探して返します。 +$user->find(1); // データベースで id = 1 を検索して返します。 echo $user->name; // 'Bobby Tables' ``` -すべてのユーザーを見つけたい場合はどうしますか? +すべてのユーザーを検索したい場合はどうでしょうか? ```php $users = $user->findAll(); ``` -特定の条件で検索する場合はどうですか? +特定の条件付きで? ```php $users = $user->like('name', '%mamma%')->findAll(); ``` -どうですか?楽しいでしょう?インストールして始めましょう! +これがどれほど楽しいかわかりますか?インストールして始めましょう! -## インストール +## Installation -Composerで簡単にインストールできます +Composer で簡単にインストールします ```php composer require flightphp/active-record ``` -## 使用法 +## Usage -これはスタンドアロンライブラリとして使用することも、Flight PHPフレームワークと一緒に使用することもできます。完全にあなたの好みです。 +これはスタンドアロン ライブラリとして使用するか、Flight PHP Framework と共に使用できます。完全にあなた次第です。 -### スタンドアロン -コンストラクタにPDO接続を渡すことを確認してください。 +### Standalone +コンストラクタに PDO 接続を渡すことを確認してください。 ```php -$pdo_connection = new PDO('sqlite:test.db'); // これは単なる例で、実際にはデータベース接続を使用することになります +$pdo_connection = new PDO('sqlite:test.db'); // これは単なる例です。本物のデータベース接続を使用するはずです $User = new User($pdo_connection); ``` -> 常にコンストラクタでデータベース接続を設定したくないですか?他のアイデアについては[データベース接続管理](#database-connection-management)を参照してください! +> コンストラクタでデータベース接続を毎回設定したくない場合、[データベース接続管理](#database-connection-management) を参照して他のアイデアを見てください! -### Flightでメソッドとして登録 -Flight PHPフレームワークを使用している場合、ActiveRecordクラスをサービスとして登録できますが、本当にそうする必要はありません。 +### Flight でメソッドとして登録 +Flight PHP Framework を使用している場合、ActiveRecord クラスをサービスとして登録できますが、必須ではありません。 ```php Flight::register('user', 'User', [ $pdo_connection ]); -// 次に、コントローラや関数などでこのように使用できます。 +// コントローラー、関数などで以下のように使用できます。 Flight::user()->find(1); ``` -## `runway` メソッド +## `runway` Methods -[runway](/awesome-plugins/runway) は、Flight用のCLIツールで、このライブラリ用のカスタムコマンドがあります。 +[runway](/awesome-plugins/runway) は Flight の CLI ツールで、このライブラリ用のカスタムコマンドがあります。 ```bash -# 使用法 +# Usage php runway make:record database_table_name [class_name] -# 例 +# Example php runway make:record users ``` -これにより、`app/records/`ディレクトリに`UserRecord.php`という新しいクラスが作成され、次の内容が含まれます: +これにより、`app/records/` ディレクトリに `UserRecord.php` という新しいクラスが作成され、以下の内容が含まれます: ```php notNull('password')->orderBy('id DESC')->find(); -// 特定のidでレコードを検索 +// 特定の id でレコードを検索 $id = 123; $user->find($id); ``` #### `findAll(): array` -指定したテーブル内のすべてのレコードを見つけます。 +指定したテーブルのすべてのレコードを検索します。 ```php $user->findAll(); @@ -203,11 +203,11 @@ $user->findAll(); #### `isHydrated(): boolean` (v0.4.0) -現在のレコードが水和(データベースから取得)されている場合は`true`を返します。 +現在のレコードがデータベースから取得(ハイドレート)されている場合に `true` を返します。 ```php $user->find(1); -// データが見つかった場合... +// データ付きのレコードが見つかった場合... $user->isHydrated(); // true ``` @@ -222,9 +222,9 @@ $user->password = md5('demo'); $user->insert(); ``` -##### テキストベースのプライマリキー +##### テキストベースの主キー -テキストベースのプライマリキー(例えばUUID)がある場合、挿入前に次の2つの方法でプライマリキーの値を設定できます。 +テキストベースの主キー(例: UUID)がある場合、挿入前に主キー値を 2 つの方法のいずれかで設定できます。 ```php $user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]); @@ -234,24 +234,24 @@ $user->password = md5('demo'); $user->insert(); // または $user->save(); ``` -または、イベントを通じてプライマリキーを自動的に生成させることもできます。 +または、イベントを通じて主キーを自動生成できます。 ```php class User extends flight\ActiveRecord { public function __construct($database_connection) { parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]); - // 上記の配列の代わりにこのようにプライマリキーを設定することもできます。 + // 上記の配列の代わりにこの方法で primaryKey を設定することもできます。 $this->primaryKey = 'uuid'; } protected function beforeInsert(self $self) { - $self->uuid = uniqid(); // またはユニークIDを生成する必要がある他の方法 + $self->uuid = uniqid(); // またはユニーク ID を生成する方法 } } ``` -挿入前にプライマリキーを設定しないと、`rowid`に設定され、データベースが自動生成しますが、そのフィールドがテーブルに存在しない場合、持続性がなくなります。したがって、これを定期的に処理するためにイベントを使うことをお勧めします。 +挿入前に主キーを設定しない場合、`rowid` に設定され、データベースが生成しますが、テーブルにそのフィールドが存在しない場合、永続化されません。これがイベントを使用して自動的に処理することを推奨する理由です。 #### `update(): boolean|ActiveRecord` @@ -265,7 +265,7 @@ $user->update(); #### `save(): boolean|ActiveRecord` -現在のレコードをデータベースに挿入または更新します。レコードにIDがある場合は更新し、そうでない場合は挿入します。 +現在のレコードをデータベースに挿入または更新します。レコードに id がある場合更新し、そうでない場合は挿入します。 ```php $user = new User($pdo_connection); @@ -274,7 +274,7 @@ $user->password = md5('demo'); $user->save(); ``` -**注:** クラスでリレーションシップが定義されている場合、それらの関係も再帰的に保存されます(v0.4.0以降)。 +**注意:** クラスにリレーションシップが定義されている場合、定義、インスタンス化、更新が必要なダーティ データがある場合、それらのリレーションを再帰的に保存します。(v0.4.0 以降) #### `delete(): boolean` @@ -285,7 +285,7 @@ $user->gt('id', 0)->orderBy('id desc')->find(); $user->delete(); ``` -事前に検索を実行して複数のレコードを削除することもできます。 +事前の検索を実行して複数のレコードを削除することもできます。 ```php $user->like('name', 'Bob%')->delete(); @@ -293,37 +293,37 @@ $user->like('name', 'Bob%')->delete(); #### `dirty(array $dirty = []): ActiveRecord` -ダーティデータとは、レコード内で変更されたデータを指します。 +ダーティ データとは、レコード内で変更されたデータを指します。 ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); // この時点では何も「ダーティ」ではありません。 -$user->email = 'test@example.com'; // これは変更されているので「ダーティ」と見なされます。 +$user->email = 'test@example.com'; // 変更されたので email は「ダーティ」と見なされます。 $user->update(); -// 更新され、データベースに永続化されたので、ダーティデータはありません。 +// 更新されてデータベースに永続化されたので、ダーティ データはなくなります -$user->password = password_hash('newpassword'); // これはダーティです。 -$user->dirty(); // 引数を何も渡さないと、すべてのダーティエントリがクリアされます。 -$user->update(); // 何も捕捉されていないため、何も更新されません。 +$user->password = password_hash()'newpassword'); // これがダーティになります +$user->dirty(); // 何も渡さないとすべてのダーティ エントリがクリアされます。 +$user->update(); // ダーティとしてキャプチャされたものが何もないので何も更新されません。 $user->dirty([ 'name' => 'something', 'password' => password_hash('a different password') ]); -$user->update(); // 名前とパスワードの両方が更新されます。 +$user->update(); // name と password の両方が更新されます。 ``` #### `copyFrom(array $data): ActiveRecord` (v0.4.0) -これは`dirty()`メソッドの別名です。何をしているのかがより明確です。 +これは `dirty()` メソッドのエイリアスです。何をしているのかが少し明確です。 ```php $user->copyFrom([ 'name' => 'something', 'password' => password_hash('a different password') ]); -$user->update(); // 名前とパスワードの両方が更新されます。 +$user->update(); // name と password の両方が更新されます。 ``` #### `isDirty(): boolean` (v0.4.0) -現在のレコードが変更された場合、`true`を返します。 +現在のレコードが変更されている場合に `true` を返します。 ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); @@ -333,15 +333,14 @@ $user->isDirty(); // true #### `reset(bool $include_query_data = true): ActiveRecord` -現在のレコードを初期状態にリセットします。これはループ型の動作で使用するのに非常に便利です。 -`true`を渡すと、現在のオブジェクトを見つけるために使用されたクエリデータもリセットされます(デフォルトの動作)。 +現在のレコードを初期状態にリセットします。ループ型の動作で使用するのに非常に便利です。`true` を渡すと、現在のオブジェクトを検索するために使用されたクエリ データもリセットされます(デフォルト動作)。 ```php $users = $user->greaterThan('id', 0)->orderBy('id desc')->find(); $user_company = new UserCompany($pdo_connection); foreach($users as $user) { - $user_company->reset(); // クリーンスレートで開始します + $user_company->reset(); // クリーンな状態から開始 $user_company->user_id = $user->id; $user_company->company_id = $some_company_id; $user_company->insert(); @@ -350,12 +349,12 @@ foreach($users as $user) { #### `getBuiltSql(): string` (v0.4.1) -`find()`, `findAll()`, `insert()`, `update()`, または`save()`メソッドを実行した後、生成されたSQLを取得してデバッグ目的で使用できます。 +`find()`、`findAll()`、`insert()`、`update()`、または `save()` メソッドを実行した後、構築された SQL を取得してデバッグに使用できます。 -## SQLクエリメソッド +## SQL Query Methods #### `select(string $field1 [, string $field2 ... ])` -必要に応じてテーブル内のいくつかのカラムだけを選択できます(非常に広いテーブルではパフォーマンスが向上します) +テーブル内の特定の列のみを選択できます(多くの列を持つ広いテーブルでパフォーマンスが向上します) ```php $user->select('id', 'name')->find(); @@ -363,7 +362,7 @@ $user->select('id', 'name')->find(); #### `from(string $table)` -実際には別のテーブルも選択できます!なぜそれをしないのですか? +技術的には別のテーブルを選択することもできます!なぜそうしないのですか?! ```php $user->select('id', 'name')->from('user')->find(); @@ -371,7 +370,7 @@ $user->select('id', 'name')->from('user')->find(); #### `join(string $table_name, string $join_condition)` -データベース内の別のテーブルを結合することもできます。 +データベース内の別のテーブルにジョインすることもできます。 ```php $user->join('contacts', 'contacts.user_id = users.id')->find(); @@ -379,13 +378,13 @@ $user->join('contacts', 'contacts.user_id = users.id')->find(); #### `where(string $where_conditions)` -カスタムのwhere引数を設定できます(このwhere文にパラメータを設定することはできません) +カスタム where 引数を設定できます(この where 文ではパラメータを設定できません) ```php $user->where('id=1 AND name="demo"')->find(); ``` -**セキュリティノート** - 何かこうしたくなるかもしれません `$user->where("id = '{$id}' AND name = '{$name}'")->find();`。絶対にこれを実行しないでください!これはSQLインジェクション攻撃の対象です。この件に関する多くのオンライン記事がありますので、"sql injection attacks php"とGoogle検索すれば、多くの記事が見つかります。このライブラリを使用する際は、`where()`メソッドの代わりに、`$user->eq('id', $id)->eq('name', $name)->find();`のようにするのが正しい方法です。絶対にこのようにする必要がある場合、`PDO`ライブラリには`$pdo->quote($var)`があり、これがあなたのためにエスケープします。 `quote()`を使用した後でなければ、`where()`文で使用することはできません。 +**セキュリティ 注意** - `$user->where("id = '{$id}' AND name = '{$name}'")->find();` のようなことをしたくなるかもしれません。絶対にこれをしないでください!!!これは SQL インジェクション攻撃の脆弱性があります。オンラインにたくさんの記事があります。「sql injection attacks php」を Google 検索してください。このトピックに関する多くの記事が見つかります。このライブラリでこれを適切に扱う方法は、この `where()` メソッドの代わりに、`$user->eq('id', $id)->eq('name', $name)->find();` のようなことを行うことです。絶対にこれをしなければならない場合、`PDO` ライブラリには `$pdo->quote($var)` があり、それをエスケープします。`quote()` を使用した後でのみ、`where()` 文で使用できます。 #### `group(string $group_by_statement)/groupBy(string $group_by_statement)` @@ -405,16 +404,16 @@ $user->orderBy('name DESC')->find(); #### `limit(string $limit)/limit(int $offset, int $limit)` -返されるレコードの数を制限します。二つ目のintが指定された場合、SQLと同様にオフセットを制限します。 +返されるレコードの数を制限します。2 番目の int が与えられた場合、SQL のようにオフセット、リミットになります。 ```php $user->orderby('name DESC')->limit(0, 10)->findAll(); ``` -## WHERE条件 +## WHERE conditions #### `equal(string $field, mixed $value) / eq(string $field, mixed $value)` -`field = $value` の場合 +Where `field = $value` ```php $user->eq('id', 1)->find(); @@ -422,7 +421,7 @@ $user->eq('id', 1)->find(); #### `notEqual(string $field, mixed $value) / ne(string $field, mixed $value)` -`field <> $value` の場合 +Where `field <> $value` ```php $user->ne('id', 1)->find(); @@ -430,14 +429,14 @@ $user->ne('id', 1)->find(); #### `isNull(string $field)` -`field IS NULL` の場合 +Where `field IS NULL` ```php $user->isNull('id')->find(); ``` #### `isNotNull(string $field) / notNull(string $field)` -`field IS NOT NULL` の場合 +Where `field IS NOT NULL` ```php $user->isNotNull('id')->find(); @@ -445,7 +444,7 @@ $user->isNotNull('id')->find(); #### `greaterThan(string $field, mixed $value) / gt(string $field, mixed $value)` -`field > $value` の場合 +Where `field > $value` ```php $user->gt('id', 1)->find(); @@ -453,21 +452,21 @@ $user->gt('id', 1)->find(); #### `lessThan(string $field, mixed $value) / lt(string $field, mixed $value)` -`field < $value` の場合 +Where `field < $value` ```php $user->lt('id', 1)->find(); ``` #### `greaterThanOrEqual(string $field, mixed $value) / ge(string $field, mixed $value) / gte(string $field, mixed $value)` -`field >= $value` の場合 +Where `field >= $value` ```php $user->ge('id', 1)->find(); ``` #### `lessThanOrEqual(string $field, mixed $value) / le(string $field, mixed $value) / lte(string $field, mixed $value)` -`field <= $value` の場合 +Where `field <= $value` ```php $user->le('id', 1)->find(); @@ -475,7 +474,7 @@ $user->le('id', 1)->find(); #### `like(string $field, mixed $value) / notLike(string $field, mixed $value)` -`field LIKE $value` または `field NOT LIKE $value` の場合 +Where `field LIKE $value` または `field NOT LIKE $value` ```php $user->like('name', 'de')->find(); @@ -483,7 +482,7 @@ $user->like('name', 'de')->find(); #### `in(string $field, array $values) / notIn(string $field, array $values)` -`field IN($value)` または `field NOT IN($value)` の場合 +Where `field IN($value)` または `field NOT IN($value)` ```php $user->in('id', [1, 2])->find(); @@ -491,56 +490,56 @@ $user->in('id', [1, 2])->find(); #### `between(string $field, array $values)` -`field BETWEEN $value AND $value1` の場合 +Where `field BETWEEN $value AND $value1` ```php $user->between('id', [1, 2])->find(); ``` -### OR条件 +### OR Conditions -条件をOR文でラップすることも可能です。これは、`startWrap()`および`endWrap()`メソッドを使用するか、フィールドと値の後に条件の3番目のパラメータを指定することで行います。 +条件を OR 文でラップすることが可能です。これは `startWrap()` と `endWrap()` メソッドを使用するか、フィールドと値の後の条件の 3 番目のパラメータを埋めることで行います。 ```php -// メソッド 1 +// Method 1 $user->eq('id', 1)->startWrap()->eq('name', 'demo')->or()->eq('name', 'test')->endWrap('OR')->find(); -// これは `id = 1 AND (name = 'demo' OR name = 'test')` と評価されます +// これは `id = 1 AND (name = 'demo' OR name = 'test')` に評価されます -// メソッド 2 +// Method 2 $user->eq('id', 1)->eq('name', 'demo', 'OR')->find(); -// これは `id = 1 OR name = 'demo'` と評価されます +// これは `id = 1 OR name = 'demo'` に評価されます ``` -## リレーションシップ -このライブラリを使用して、いくつかの種類のリレーションシップを設定できます。一対多および一対一のリレーションシップをテーブル間に設定できます。これには、事前にクラス内で追加のセットアップが必要です。 +## Relationships +このライブラリを使用して、テーブル間の one->many および one->one リレーションシップを設定できます。これにはクラス内で少し追加の設定が必要です。 -`$relations`配列の設定は難しくはありませんが、正しい構文を推測することは混乱を招くことがあります。 +`$relations` 配列を設定するのは簡単ですが、正しい構文を推測するのは混乱するかもしれません。 ```php protected array $relations = [ - // キーの名前は好きなように設定できます。アクティブレコードの名前はおそらく良いでしょう。例:user、contact、client + // キーの名前は任意に付けられます。ActiveRecord の名前が良いでしょう。例: user, contact, client 'user' => [ // 必須 // self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO - self::HAS_ONE, // これはリレーションのタイプです + self::HAS_ONE, // これはリレーションシップのタイプです // 必須 - 'Some_Class', // これは参照する「他の」アクティブレコードクラスです + 'Some_Class', // これは参照する「他の」ActiveRecord クラスです // 必須 - // リレーションシップの種類に応じて - // self::HAS_ONE = 結合を参照する外部キー - // self::HAS_MANY = 結合を参照する外部キー - // self::BELONGS_TO = 結合を参照するローカルキー + // リレーションシップのタイプによって異なります + // self::HAS_ONE = ジョインを参照する外部キー + // self::HAS_MANY = ジョインを参照する外部キー + // self::BELONGS_TO = ジョインを参照するローカルキー 'local_or_foreign_key', - // 他のモデルのプライマリキーにのみ結合しますので、ご注意ください。 + // FYI、これも「他の」モデルの主キーにのみジョインします - // オプショナル - [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // リレーションを結合する際に希望する追加条件 + // オプション + [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // ジョイン時の追加条件 // $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5)) - // オプショナル - 'back_reference_name' // これは、このリレーションシップを自身に戻して参照したい場合の名前です。例:$user->contact->user; + // オプション + 'back_reference_name' // これを自身にバック参照したい場合、例: $user->contact->user; ]; ] ``` @@ -570,12 +569,12 @@ class Contact extends ActiveRecord{ } ``` -これでリファレンスのセットアップができたので、非常に簡単に使用できます! +これで参照が設定されたので、簡単に使用できます! ```php $user = new User($pdo_connection); -// 最も最近のユーザーを見つける。 +// 最新のユーザーを検索。 $user->notNull('id')->orderBy('id desc')->find(); // リレーションを使用して連絡先を取得: @@ -583,43 +582,144 @@ foreach($user->contacts as $contact) { echo $contact->id; } -// または反対側に行くことができます。 +// または逆方向に。 $contact = new Contact(); -// 1つの連絡先を見つけます +// 1 つの連絡先を検索 $contact->find(); -// リレーションを使用してユーザーを取得: +// リレーションを使用してユーザー取得: echo $contact->user->name; // これはユーザー名です ``` -すごいですね! +かなりクールですね? -## カスタムデータの設定 -場合によっては、アクティブレコードにカスタム計算など、オブジェクトに直接接続したいユニークなものを添付する必要があるかもしれません。 +### Eager Loading + +#### Overview +Eager loading は、N+1 クエリ問題を解決し、リレーションシップを事前にロードします。各レコードのリレーションシップごとに別々のクエリを実行する代わりに、リレーションシップごとに 1 つの追加クエリですべての関連データを取得します。 + +> **注意:** Eager loading は v0.7.0 以降でのみ利用可能です。 + +#### Basic Usage +`with()` メソッドを使用して、eager load するリレーションシップを指定します: +```php +// N+1 の代わりに 2 つのクエリでユーザーとその連絡先をロード +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + foreach ($u->contacts as $contact) { + echo $contact->email; // 追加のクエリなし! + } +} +``` + +#### Multiple Relations +複数のリレーションシップを一度にロード: +```php +$users = $user->with(['contacts', 'profile', 'settings'])->findAll(); +``` + +#### Relationship Types + +##### HAS_MANY +```php +// 各ユーザーのすべての連絡先を eager load +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + // $u->contacts はすでに配列としてロードされています + foreach ($u->contacts as $contact) { + echo $contact->email; + } +} +``` +##### HAS_ONE +```php +// 各ユーザーの 1 つの連絡先を eager load +$users = $user->with('contact')->findAll(); +foreach ($users as $u) { + // $u->contact はすでにオブジェクトとしてロードされています + echo $u->contact->email; +} +``` + +##### BELONGS_TO +```php +// すべての連絡先の親ユーザーを eager load +$contacts = $contact->with('user')->findAll(); +foreach ($contacts as $c) { + // $c->user はすでにロードされています + echo $c->user->name; +} +``` +##### With find() +Eager loading は +findAll() + と +find() + の両方で動作します: + +```php +$user = $user->with('contacts')->find(1); +// ユーザーとすべての連絡先が 2 つのクエリでロードされます +``` +#### Performance Benefits +Eager loading なし(N+1 問題): +```php +$users = $user->findAll(); // 1 クエリ +foreach ($users as $u) { + $contacts = $u->contacts; // N クエリ(ユーザーごとに 1 つ!) +} +// 合計: 1 + N クエリ +``` + +Eager loading あり: + +```php +$users = $user->with('contacts')->findAll(); // 合計 2 クエリ +foreach ($users as $u) { + $contacts = $u->contacts; // 追加のクエリ 0! +} +// 合計: 2 クエリ(ユーザー用 1 + すべての連絡先用 1) +``` +10 人のユーザーの場合、クエリが 11 から 2 に減少し、82% の削減です! + +#### Important Notes +- Eager loading は完全にオプションです - 遅延ロードは以前通り動作します +- すでにロードされたリレーションシップは自動的にスキップされます +- バック参照は eager loading で動作します +- リレーションコールバックは eager loading 中に尊重されます + +#### Limitations +- ネストされた eager loading(例: +with(['contacts.addresses']) +)は現在サポートされていません +- クロージャによる eager load 制約はこのバージョンでサポートされていません + +## Setting Custom Data +時には ActiveRecord にカスタム計算などのユニークなものをアタッチする必要がある場合があります。これをテンプレートに渡されるオブジェクトにアタッチする方が簡単かもしれません。 #### `setCustomData(string $field, mixed $value)` -カスタムデータは、`setCustomData()`メソッドを使用して添付します。 +`setCustomData()` メソッドを使用してカスタム データをアタッチします。 ```php $user->setCustomData('page_view_count', $page_view_count); ``` -そして、通常のオブジェクトプロパティのように参照します。 +次に、通常のオブジェクト プロパティのように参照します。 ```php echo $user->page_view_count; ``` -## イベント +## Events -このライブラリのもう一つの素晴らしい機能は、イベントに関するものです。イベントは、呼び出す特定のメソッドに基づいて特定のタイミングでトリガーされます。自動的にデータをセットアップするのに非常に役立ちます。 +このライブラリのもう一つの超すごい機能はイベントについてです。イベントは特定のメソッドを呼び出す特定のタイミングでトリガーされます。データを自動的に設定するのに非常に役立ちます。 #### `onConstruct(ActiveRecord $ActiveRecord, array &config)` -これは、デフォルトの接続などを設定するのに非常に便利です。 +デフォルトの接続を設定する必要がある場合に非常に役立ちます。 ```php -// index.phpまたはbootstrap.php +// index.php または bootstrap.php Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // @@ -629,13 +729,13 @@ Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php class User extends flight\ActiveRecord { - protected function onConstruct(self $self, array &$config) { // &参照を忘れずに - // このように接続を自動的に設定できます + protected function onConstruct(self $self, array &$config) { // & 参照を忘れずに + // 接続を自動的に設定するためにこれを実行できます $config['connection'] = Flight::db(); // またはこれ $self->transformAndPersistConnection(Flight::db()); - // この方法でテーブル名を設定することもできます。 + // この方法でテーブル名も設定できます。 $config['table'] = 'users'; } } @@ -643,7 +743,7 @@ class User extends flight\ActiveRecord { #### `beforeFind(ActiveRecord $ActiveRecord)` -おそらく、毎回クエリ操作が必要な場合に役立ちます。 +毎回クエリ操作が必要な場合にのみ有用です。 ```php class User extends flight\ActiveRecord { @@ -654,7 +754,7 @@ class User extends flight\ActiveRecord { } protected function beforeFind(self $self) { - // 常に id >= 0 を実行します。 + // それがお好みなら id >= 0 を常に実行 $self->gte('id', 0); } } @@ -662,7 +762,7 @@ class User extends flight\ActiveRecord { #### `afterFind(ActiveRecord $ActiveRecord)` -おそらく、レコードが取得されるたびに何らかのロジックを実行する必要がある場合に役立ちます。何かを復号化する必要がありますか?毎回カスタムカウントクエリを実行する必要がありますか(パフォーマンスは良くありませんが、いかがでしょうか)? +このレコードが取得されるたびに常にロジックを実行する必要がある場合に、より有用です。何かを復号化する必要がありますか?毎回カスタム カウント クエリを実行する必要がありますか(パフォーマンスは悪いですが、まあ)? ```php class User extends flight\ActiveRecord { @@ -673,18 +773,18 @@ class User extends flight\ActiveRecord { } protected function afterFind(self $self) { - // 何かを復号化する + // 何かを復号化 $self->secret = yourDecryptFunction($self->secret, $some_key); - // 何かカスタムのストレージを行うかもしれません - $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']); + // クエリのようなカスタムなものを保存? + $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']; } } ``` #### `beforeFindAll(ActiveRecord $ActiveRecord)` -おそらく、毎回クエリ操作が必要な場合に役立ちます。 +毎回クエリ操作が必要な場合にのみ有用です。 ```php class User extends flight\ActiveRecord { @@ -695,7 +795,7 @@ class User extends flight\ActiveRecord { } protected function beforeFindAll(self $self) { - // 常に id >= 0 を実行します + // それがお好みなら id >= 0 を常に実行 $self->gte('id', 0); } } @@ -703,7 +803,7 @@ class User extends flight\ActiveRecord { #### `afterFindAll(array $results)` -`afterFind()` に似ていますが、すべてのレコードに対して行えます! +`afterFind()` に似ていますが、すべてのレコードに対して実行できます! ```php class User extends flight\ActiveRecord { @@ -716,7 +816,7 @@ class User extends flight\ActiveRecord { protected function afterFindAll(array $results) { foreach($results as $self) { - // afterFind()のような何かを行います + // afterFind() のように何かクールなことをする } } } @@ -724,7 +824,7 @@ class User extends flight\ActiveRecord { #### `beforeInsert(ActiveRecord $ActiveRecord)` -毎回いくつかのデフォルト値を設定するのに非常に便利です。 +毎回デフォルト値を設定する必要がある場合に非常に役立ちます。 ```php class User extends flight\ActiveRecord { @@ -735,7 +835,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // 有効なデフォルトを設定します + // いくつかの健全なデフォルトを設定 if(!$self->created_date) { $self->created_date = gmdate('Y-m-d'); } @@ -749,7 +849,7 @@ class User extends flight\ActiveRecord { #### `afterInsert(ActiveRecord $ActiveRecord)` -挿入後にデータを変更する必要があるユースケースがあるかもしれません。 +挿入後にデータを変更するユース ケースがあるかもしれません? ```php class User extends flight\ActiveRecord { @@ -760,16 +860,16 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // 自分の好きなように + // あなた次第 Flight::cache()->set('most_recent_insert_id', $self->id); - // または何か... + // または何でも.... } } ``` #### `beforeUpdate(ActiveRecord $ActiveRecord)` -毎回更新時にデフォルト値を設定するのに非常に便利です。 +更新時に毎回デフォルト値を設定する必要がある場合に非常に役立ちます。 ```php class User extends flight\ActiveRecord { @@ -779,8 +879,8 @@ class User extends flight\ActiveRecord { parent::__construct($database_connection, 'users'); } - protected function beforeUpdate(self $self) { - // 有効なデフォルトを設定します + protected function beforeInsert(self $self) { + // いくつかの健全なデフォルトを設定 if(!$self->updated_date) { $self->updated_date = gmdate('Y-m-d'); } @@ -790,7 +890,7 @@ class User extends flight\ActiveRecord { #### `afterUpdate(ActiveRecord $ActiveRecord)` -更新後にデータを変更する必要があるユースケースがあるかもしれません。 +更新後にデータを変更するユース ケースがあるかもしれません? ```php class User extends flight\ActiveRecord { @@ -800,17 +900,17 @@ class User extends flight\ActiveRecord { parent::__construct($database_connection, 'users'); } - protected function afterUpdate(self $self) { - // 自分の好きなように + protected function afterInsert(self $self) { + // あなた次第 Flight::cache()->set('most_recently_updated_user_id', $self->id); - // または何か... + // または何でも.... } } ``` #### `beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)` -これは、挿入または更新が行われるときに、イベントを発生させたい場合に役立ちます。長い説明は省きますが、何を意味するのかを推測できますよね。 +挿入または更新の両方でイベントが発生するようにしたい場合に有用です。長い説明は省きますが、何かわかるはずです。 ```php class User extends flight\ActiveRecord { @@ -828,7 +928,7 @@ class User extends flight\ActiveRecord { #### `beforeDelete(ActiveRecord $ActiveRecord)/afterDelete(ActiveRecord $ActiveRecord)` -ここで何をするかは不明ですが、判断はありません!あなたの好きなようにやってください! +ここで何をしたいかわかりませんが、判断はしません!やってみてください! ```php class User extends flight\ActiveRecord { @@ -839,17 +939,17 @@ class User extends flight\ActiveRecord { } protected function beforeDelete(self $self) { - echo '彼は勇敢な兵士でした... :cry-face:'; + echo 'He was a brave soldier... :cry-face:'; } } ``` -## データベース接続管理 +## Database Connection Management -このライブラリを使用する際、データベース接続をいくつかの異なる方法で設定できます。コンストラクタ内で接続を設定することも、`$config['connection']`変数を介して設定することも、`setDatabaseConnection()`を使用して設定することもできます(v0.4.1)。 +このライブラリを使用する場合、データベース接続をいくつかの方法で設定できます。コンストラクタで設定するか、`$config['connection']` で設定するか、`setDatabaseConnection()` で設定できます (v0.4.1)。 ```php -$pdo_connection = new PDO('sqlite:test.db'); // 例として +$pdo_connection = new PDO('sqlite:test.db'); // 例 $user = new User($pdo_connection); // または $user = new User(null, [ 'connection' => $pdo_connection ]); @@ -858,11 +958,11 @@ $user = new User(); $user->setDatabaseConnection($pdo_connection); ``` -アクティブレコードを呼び出すたびに、`$database_connection`を設定するのを避けたい場合は、その方法がいくつかあります! +アクティブ レコードを呼び出すたびに `$database_connection` を常に設定したくない場合、それには方法があります! ```php -// index.phpまたはbootstrap.php -// Flightで登録済みのクラスとしてこれを設定します +// index.php または bootstrap.php +// Flight で登録されたクラスとして設定 Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php @@ -875,24 +975,24 @@ class User extends flight\ActiveRecord { } } -// これで、引数は不要です! +// そして今、引数は不要! $user = new User(); ``` -> **注:** 単体テストを計画している場合、この方法で行うと単体テストにいくつかの課題が生じる可能性がありますが、全体的には`setDatabaseConnection()`や`$config['connection']`で接続を注入できるため、あまり問題ではありません。 +> **注意:** ユニット テストを計画している場合、この方法でいくつかの課題が生じる可能性がありますが、`setDatabaseConnection()` または `$config['connection']` で接続をインジェクトできるため、全体としてそれほど悪くありません。 -例えば、長時間実行されるCLIスクリプトを実行している場合に接続をリフレッシュする必要がある場合、`$your_record->setDatabaseConnection($pdo_connection)`で接続を再設定することができます。 +データベース接続を更新する必要がある場合、例えば長時間実行される CLI スクリプトを実行していて、定期的に接続を更新する必要がある場合、` $your_record->setDatabaseConnection($pdo_connection)` で接続を再設定できます。 -## 貢献 +## Contributing -ぜひご協力ください。 :D +ぜひ貢献してください。 :D -### セットアップ +### Setup -貢献する際は、`composer test-coverage`を実行して100%のテストカバレッジを維持してください(これは真の単体テストカバレッジではなく、むしろ統合テストのカバレッジです)。 +貢献する場合、`composer test-coverage` を実行して 100% のテスト カバレッジを維持してください(これは真のユニット テスト カバレッジではなく、統合テストに近いです)。 -また、`composer beautify`および`composer phpcs`を実行して、すべてのリンティングエラーを修正することを確認してください。 +また、`composer beautify` と `composer phpcs` を実行して、リンティング エラーを修正してください。 -## ライセンス +## License MIT \ No newline at end of file diff --git a/content/v3/ja/awesome-plugins/apm.md b/content/v3/ja/awesome-plugins/apm.md index 20194b6c..34003df9 100644 --- a/content/v3/ja/awesome-plugins/apm.md +++ b/content/v3/ja/awesome-plugins/apm.md @@ -1,6 +1,6 @@ # FlightPHP APM ドキュメント -FlightPHP APM へようこそ—アプリのパーソナルパフォーマンスコーチです!このガイドは、FlightPHP を使用したアプリケーション パフォーマンス モニタリング (APM) の設定、使用、マスターするためのロードマップです。遅いリクエストを追跡したり、レイテンシ チャートに没頭したりするかどうかにかかわらず、私たちがカバーします。アプリを速くし、ユーザーを幸せにし、デバッグ セッションを楽にしましょう! +FlightPHP APM へようこそ—あなたのアプリのパーソナルパフォーマンスコーチです!このガイドは、FlightPHP を使用した Application Performance Monitoring (APM) のセットアップ、使用、マスターのためのロードマップです。遅いリクエストを追跡したり、レイテンシーチャートに没頭したりするかどうかにかかわらず、私たちがカバーします。あなたのアプリを速くし、ユーザーを幸せにし、デバッグセッションを楽にしましょう! Flight Docs サイトのダッシュボードの [デモ](https://flightphp-docs-apm.sky-9.com/apm/dashboard) をご覧ください。 @@ -8,7 +8,7 @@ Flight Docs サイトのダッシュボードの [デモ](https://flightphp-docs ## APM が重要な理由 -これを想像してください:アプリが忙しいレストランです。注文にかかる時間を追跡したり、キッチンがどこで詰まっているかを追跡する方法がないと、顧客が不機嫌になって去る理由を推測するだけです。APM はあなたの副シェフです—受信リクエストからデータベース クエリまで、すべてのステップを監視し、遅延を引き起こすものをフラグ付けします。遅いページはユーザーを失います(研究によると、サイトの読み込みに 3 秒以上かかると 53% がバウンス!)、APM はそれらの問題を *事前に* キャッチするのに役立ちます。それは積極的な安心感です—「これが壊れているのはなぜ?」という瞬間が少なくなり、「これがどれだけスムーズに動作するか見て!」という勝利が増えます。 +こんな状況を想像してください:あなたのアプリは忙しいレストランです。注文にかかる時間を追跡したり、キッチンがどこで滞っているかを把握する手段がなければ、なぜ顧客が不機嫌になって去るのかを推測するだけです。APM はあなたの副シェフです—着信リクエストからデータベースクエリまですべてのステップを監視し、遅延を引き起こすものをフラグ付けします。遅いページはユーザーを失います(研究によると、サイトの読み込みに3秒以上かかると53%がバウンス!)、APM はそれらの問題を *事前に* キャッチするのに役立ちます。それは積極的な安心感—「なぜこれが壊れているのか?」という瞬間を減らし、「これがどれだけスムーズに動作するか見て!」という勝利を増やします。 ## インストール @@ -19,28 +19,29 @@ composer require flightphp/apm ``` 必要なもの: -- **PHP 7.4+**:LTS Linux ディストリビューションとの互換性を保ちつつ、モダンな PHP をサポートします。 +- **PHP 7.4+**:LTS Linux ディストリビューションとの互換性を保ちつつ、現代の PHP をサポートします。 - **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**:私たちが強化する軽量フレームワークです。 ## サポートされるデータベース -FlightPHP APM は、現在、指標を保存するための以下のデータベースをサポートしています: +FlightPHP APM は現在、以下のデータベースをメトリクスの保存にサポートしています: -- **SQLite3**:シンプルでファイルベースで、ローカル開発や小規模アプリに最適です。ほとんどのセットアップでデフォルト オプションです。 +- **SQLite3**:シンプルでファイルベース、ローカル開発や小規模アプリに最適。ほとんどのセットアップでデフォルトオプションです。 - **MySQL/MariaDB**:大規模プロジェクトや本番環境で堅牢でスケーラブルなストレージが必要な場合に理想的です。 -構成ステップ(以下を参照)でデータベース タイプを選択できます。PHP 環境に必要な拡張機能がインストールされていることを確認してください(例:`pdo_sqlite` または `pdo_mysql`)。 +構成ステップ(以下参照)でデータベースタイプを選択できます。PHP 環境に必要な拡張機能がインストールされていることを確認してください(例:`pdo_sqlite` または `pdo_mysql`)。 ## 開始方法 -APM の素晴らしさへのステップバイステップです: +APM の素晴らしさへのステップバイステップ: ### 1. APM を登録する -`index.php` または `services.php` ファイルにこれを追加して追跡を開始してください: +追跡を開始するために、これを `index.php` または `services.php` ファイルに追加してください: ```php use flight\apm\logger\LoggerFactory; +use flight\database\PdoWrapper; use flight\Apm; $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); @@ -48,18 +49,18 @@ $Apm = new Apm($ApmLogger); $Apm->bindEventsToFlightInstance($app); // データベース接続を追加する場合 -// Tracy Extensions からの PdoWrapper または PdoQueryCapture である必要があります -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- APM で追跡を有効にするために True が必要です。 +// Tracy Extensions からの PdoWrapper または PdoQueryCapture でなければなりません +$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- APM での追跡を有効にするために True が必要です。 $Apm->addPdoConnection($pdo); ``` -**ここで何が起こっていますか?** -- `LoggerFactory::create()` は構成を取得(まもなく詳述)し、ロガーをセットアップします—デフォルトで SQLite です。 -- `Apm` はスターです—Flight のイベント(リクエスト、ルート、エラーなど)を監視し、指標を収集します。 -- `bindEventsToFlightInstance($app)` はこれをすべて Flight アプリに結びつけます。 +**ここで何が起こっているか?** +- `LoggerFactory::create()` は構成を取得(まもなく詳述)し、ロガーをセットアップします—デフォルトで SQLite。 +- `Apm` はスターです—Flight のイベント(リクエスト、ルート、エラーなど)を監視し、メトリクスを収集します。 +- `bindEventsToFlightInstance($app)` はこれをすべてあなたの Flight アプリに結びつけます。 -**プロ ティップ: サンプリング** -アプリが忙しい場合、*すべての* リクエストをログにするとオーバーロードする可能性があります。サンプル レート(0.0 から 1.0)を使用してください: +**プロチップ:サンプリング** +アプリが忙しい場合、*すべての* リクエストをログにすると過負荷になる可能性があります。サンプルレート(0.0 から 1.0)を使用してください: ```php $Apm = new Apm($ApmLogger, 0.1); // リクエストの 10% をログにします @@ -75,10 +76,10 @@ $Apm = new Apm($ApmLogger, 0.1); // リクエストの 10% をログにします php vendor/bin/runway apm:init ``` -**これは何をしますか?** -- 生の指標のソース(source)と処理されたデータの宛先(destination)を尋ねるウィザードを起動します。 +**これは何をするか?** +- 生メトリクスのソース(source)と処理済みデータの宛先(destination)を尋ねるウィザードを起動します。 - デフォルトは SQLite—例:ソース用に `sqlite:/tmp/apm_metrics.sqlite`、宛先用に別のもの。 -- 次のような構成が得られます: +- 以下のような構成が得られます: ```json { "apm": { @@ -90,35 +91,35 @@ php vendor/bin/runway apm:init } ``` -> このプロセスは、このセットアップのマイグレーションを実行するかどうかも尋ねます。初めて設定する場合、答えは yes です。 +> このプロセスは、このセットアップのマイグレーションを実行するかどうかも尋ねます。初めてセットアップする場合、答えは yes です。 -**なぜ 2 つの場所ですか?** -生の指標は急速に蓄積されます(フィルタリングされていないログを想像してください)。ワーカーがこれを構造化された宛先のダッシュボードに処理します。整理を保ちます! +**なぜ2つの場所か?** +生メトリクスは急速に蓄積されます(フィルタリングされていないログを想像してください)。ワーカーがこれを構造化された宛先へ処理し、ダッシュボード用にします。すべてを整理します! -### 3. ワーカーで指標を処理する +### 3. ワーカーでメトリクスを処理する -ワーカーは生の指標をダッシュボード対応データに変換します。一度実行してください: +ワーカーは生メトリクスをダッシュボード対応データに変換します。一度実行してください: ```bash php vendor/bin/runway apm:worker ``` -**何をしていますか?** +**何をしているか?** - ソースから読み込みます(例:`apm_metrics.sqlite`)。 -- 最大 100 指標(デフォルト バッチ サイズ)を宛先に処理します。 -- 完了するか、指標が残っていない場合に停止します。 +- 最大 100 メトリクス(デフォルトバッチサイズ)を宛先へ処理します。 +- 完了するか、メトリクスがなくなると停止します。 **継続実行する** -ライブ アプリの場合、継続的な処理を望みます。オプションはこちらです: +ライブアプリでは、継続的な処理を望みます。オプションはこちら: -- **デーモン モード**: +- **デーモンモード**: ```bash php vendor/bin/runway apm:worker --daemon ``` - 指標が来るたびに永遠に実行します。開発や小規模セットアップに最適です。 + ずっと実行し、メトリクスを処理します。開発や小規模セットアップに最適です。 - **Crontab**: - crontab に追加してください(`crontab -e`): + crontab に追加(`crontab -e`): ```bash * * * * * php /path/to/project/vendor/bin/runway apm:worker ``` @@ -129,7 +130,7 @@ php vendor/bin/runway apm:worker ```bash tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon - # Ctrl+B, 続いて D で分離;`tmux attach -t apm-worker` で再接続 + # Ctrl+B, then D で分離;`tmux attach -t apm-worker` で再接続 ``` ログアウトしても実行を続けます。 @@ -137,76 +138,76 @@ php vendor/bin/runway apm:worker ```bash php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 ``` - - `--batch_size 50`:一度に 50 指標を処理。 - - `--max_messages 1000`:1000 指標後に停止。 - - `--timeout 300`:5 分後に終了。 + - `--batch_size 50`:一度に 50 メトリクスを処理。 + - `--max_messages 1000`:1000 メトリクス後に停止。 + - `--timeout 300`:5分後に終了。 -**なぜ面倒を見るのですか?** -ワーカーがないと、ダッシュボードは空です。生のログと実用的な洞察の橋渡しです。 +**なぜ面倒を見るか?** +ワーカーがないと、ダッシュボードは空です。それは生ログと実用的な洞察の橋です。 ### 4. ダッシュボードを起動する -アプリのバイタル サインを表示: +アプリのバイタルサインを表示: ```bash php vendor/bin/runway apm:dashboard ``` -**これは何ですか?** -- `http://localhost:8001/apm/dashboard` で PHP サーバーを起動します。 -- リクエスト ログ、遅いルート、エラー レートなどを表示します。 +**これは何?** +- `http://localhost:8001/apm/dashboard` で PHP サーバーを起動。 +- リクエストログ、遅いルート、エラーレートなどを表示。 **カスタマイズ**: ```bash php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php ``` -- `--host 0.0.0.0`:任意の IP からアクセス可能(リモート表示に便利)。 -- `--port 8080`:8001 が使用されている場合に別のポートを使用。 +- `--host 0.0.0.0`:任意の IP からアクセス可能(リモート閲覧に便利)。 +- `--port 8080`:8001 が使用中の場合に異なるポートを使用。 - `--php-path`:PATH にない場合に PHP を指定。 ブラウザで URL にアクセスして探索してください! #### 本番モード -本番では、ファイアウォールや他のセキュリティ対策があるため、ダッシュボードを実行するためにいくつかのテクニックを試す必要があるかもしれません。オプションはこちらです: +本番では、ファイアウォールや他のセキュリティ対策があるため、ダッシュボードを起動するためにいくつかのテクニックを試す必要があります。オプションはこちら: -- **リバース プロキシを使用**:Nginx または Apache をセットアップして、ダッシュボードへのリクエストを転送します。 -- **SSH トンネル**:サーバーに SSH でアクセスできる場合、`ssh -L 8080:localhost:8001 youruser@yourserver` を使用して、ダッシュボードをローカル マシンにトンネルします。 -- **VPN**:サーバーが VPN の背後にある場合、それに接続してダッシュボードに直接アクセスします。 -- **ファイアウォール構成**:ポート 8001 を自分の IP またはサーバーのネットワーク用に開放します。(または設定したポート)。 -- **Apache/Nginx 構成**:アプリケーションの前にウェブ サーバーがある場合、ドメインまたはサブドメインに構成できます。これを行う場合、ドキュメント ルートを `/path/to/your/project/vendor/flightphp/apm/dashboard` に設定します。 +- **リバースプロキシを使用**:Nginx または Apache をセットアップして、ダッシュボードへのリクエストを転送。 +- **SSH トンネル**:サーバーに SSH で接続できる場合、`ssh -L 8080:localhost:8001 youruser@yourserver` を使用してダッシュボードをローカルマシンにトンネル。 +- **VPN**:サーバーが VPN の背後にある場合、接続してダッシュボードに直接アクセス。 +- **ファイアウォール構成**:ポート 8001 をあなたの IP またはサーバーネットワーク用に開放(または設定したポート)。 +- **Apache/Nginx 構成**:アプリケーションの前にウェブサーバーがある場合、ドメインまたはサブドメインに構成可能。これを行う場合、ドキュメントルートを `/path/to/your/project/vendor/flightphp/apm/dashboard` に設定。 -#### 別のダッシュボードが欲しいですか? +#### 別のダッシュボードが欲しい? -自分のダッシュボードを構築できます!vendor/flightphp/apm/src/apm/presenter ディレクトリを参照して、自分のダッシュボードでデータを提示する方法のアイデアを得てください! +独自のダッシュボードを構築できます!vendor/flightphp/apm/src/apm/presenter ディレクトリを参照して、独自のダッシュボードでデータを提示する方法のアイデアを得てください! ## ダッシュボードの機能 -ダッシュボードは APM の本部です—ここで見えるものは: +ダッシュボードは APM の本部—ここで見られるもの: -- **リクエスト ログ**:タイムスタンプ、URL、レスポンス コード、合計時間付きのすべてのリクエスト。「詳細」をクリックしてミドルウェア、クエリ、エラーを表示。 -- **最も遅いリクエスト**:時間を消費する上位 5 つのリクエスト(例:`/api/heavy` が 2.5s)。 -- **最も遅いルート**:平均時間による上位 5 つのルート—パターンを特定するのに最適。 -- **エラー レート**:失敗するリクエストのパーセンテージ(例:2.3% の 500s)。 -- **レイテンシ パーセンタイル**:95 番目 (p95) と 99 番目 (p99) のレスポンス時間—最悪の場合のシナリオを知る。 -- **レスポンス コード チャート**:時間経過による 200s、404s、500s を可視化。 -- **長いクエリ/ミドルウェア**:上位 5 つの遅いデータベース コールとミドルウェア レイヤー。 -- **キャッシュ ヒット/ミス**:キャッシュがどれだけ役立つか。 +- **リクエストログ**:タイムスタンプ、URL、レスポンスコード、総時間付きのすべてのリクエスト。「詳細」をクリックしてミドルウェア、クエリ、エラーを表示。 +- **最も遅いリクエスト**:時間を消費するトップ 5 リクエスト(例:「/api/heavy」 2.5s)。 +- **最も遅いルート**:平均時間によるトップ 5 ルート—パターンを特定するのに最適。 +- **エラーレート**:失敗するリクエストのパーセンテージ(例:2.3% の 500s)。 +- **レイテンシーパーセンタイル**:95th (p95) および 99th (p99) レスポンス時間—最悪ケースを知る。 +- **レスポンスコードチャート**:時間経過による 200s、404s、500s を可視化。 +- **長いクエリ/ミドルウェア**:トップ 5 の遅いデータベースコールとミドルウェアレイヤー。 +- **キャッシュヒット/ミス**:キャッシュがどれだけ役立つか。 -**追加機能**: -- 「最終 1 時間」、「最終 1 日」、「最終 1 週間」でフィルタリング。 -- 深夜のセッション用にダーク モードを切り替え。 +**エクストラ**: +- 「最終1時間」、「最終1日」、「最終1週間」でフィルタ。 +- 深夜セッション用のダークモードを切り替え。 **例**: -`/users` へのリクエストは以下を表示するかもしれません: -- 合計時間: 150ms -- ミドルウェア: `AuthMiddleware->handle` (50ms) -- クエリ: `SELECT * FROM users` (80ms) -- キャッシュ: `user_list` でヒット (5ms) +`/users` へのリクエストは以下を表示する可能性: +- 総時間:150ms +- ミドルウェア:`AuthMiddleware->handle` (50ms) +- クエリ:`SELECT * FROM users` (80ms) +- キャッシュ:`user_list` でヒット (5ms) -## カスタム イベントの追加 +## カスタムイベントの追加 -API コールや支払いプロセスなど、何でも追跡: +API コールや支払いプロセスなど何でも追跡: ```php use flight\apm\CustomEvent; @@ -218,10 +219,10 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ])); ``` -**どこに表示されますか?** -ダッシュボードのリクエスト詳細の「カスタム イベント」下—プリティ JSON 形式で展開可能。 +**どこに表示されるか?** +ダッシュボードのリクエスト詳細の「カスタムイベント」下—プリティ JSON フォーマットで展開可能。 -**使用例**: +**ユースケース**: ```php $start = microtime(true); $apiResponse = file_get_contents('https://api.example.com/data'); @@ -231,60 +232,60 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -これで、その API がアプリを遅くしているかどうかを確認できます! +これで、その API がアプリを遅くしているかどうかがわかります! -## データベース モニタリング +## データベース監視 -PDO クエリをこのように追跡: +PDO クエリを以下のように追跡: ```php use flight\database\PdoWrapper; -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- APM で追跡を有効にするために True が必要です。 +$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- APM での追跡を有効にするために True が必要です。 $Apm->addPdoConnection($pdo); ``` -**何が得られますか?** -- クエリ テキスト(例:`SELECT * FROM users WHERE id = ?`) +**得られるもの**: +- クエリテキスト(例:`SELECT * FROM users WHERE id = ?`) - 実行時間(例:0.015s) - 行数(例:42) **注意**: - **オプション**:DB 追跡が必要ない場合スキップ。 - **PdoWrapper のみ**:コア PDO はまだフックされていません—続報をお待ちください! -- **パフォーマンス警告**:DB 重いサイトですべてのクエリをログにすると遅くなる可能性があります。サンプリング(`$Apm = new Apm($ApmLogger, 0.1)`)を使用して負荷を軽減。 +- **パフォーマンス警告**:DB 重いサイトですべてのクエリをログにすると遅くなる可能性。サンプリング(`$Apm = new Apm($ApmLogger, 0.1)`)を使用して負荷を軽減。 -**出力例**: -- クエリ: `SELECT name FROM products WHERE price > 100` -- 時間: 0.023s -- 行: 15 +**例出力**: +- クエリ:`SELECT name FROM products WHERE price > 100` +- 時間:0.023s +- 行:15 ## ワーカーのオプション ワーカーを好みに調整: -- `--timeout 300`:5 分後に停止—テストに適しています。 -- `--max_messages 500`:500 指標で上限—有限に保ちます。 +- `--timeout 300`:5分後に停止—テストに適。 +- `--max_messages 500`:500 メトリクスで上限—有限に保つ。 - `--batch_size 200`:一度に 200 を処理—速度とメモリのバランス。 -- `--daemon`:非停止で実行—ライブ モニタリングに理想的。 +- `--daemon`:非停止実行—ライブ監視に理想。 **例**: ```bash php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ``` -1 時間実行、一度に 100 指標を処理。 +1時間実行し、一度に 100 メトリクスを処理。 ## アプリ内のリクエスト ID -各リクエストには追跡のためのユニークなリクエスト ID があります。この ID をアプリで使用してログと指標を相関させることができます。例えば、エラー ページにリクエスト ID を追加できます: +各リクエストには追跡用のユニークなリクエスト ID があります。この ID をアプリで使用してログとメトリクスを相関できます。例えば、エラーページにリクエスト ID を追加: ```php Flight::map('error', function($message) { - // レスポンス ヘッダー X-Flight-Request-Id からリクエスト ID を取得 + // レスポンスヘッダー X-Flight-Request-Id からリクエスト ID を取得 $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - // また、Flight 変数から取得することもできます - // この方法は swoole や他の非同期プラットフォームではうまく動作しません。 + // また Flight 変数から取得可能 + // Swoole や他の非同期プラットフォームではこの方法はうまく動作しません。 // $requestId = Flight::get('apm.request_id'); echo "Error: $message (Request ID: $requestId)"; @@ -293,55 +294,65 @@ Flight::map('error', function($message) { ## アップグレード -APM の新しいバージョンにアップグレードする場合、データベース マイグレーションを実行する必要がある可能性があります。以下のコマンドを実行してこれを行います: +APM の新しいバージョンにアップグレードする場合、データベースマイグレーションを実行する必要がある可能性があります。以下のコマンドを実行してください: ```bash php vendor/bin/runway apm:migrate ``` -これにより、データベース スキーマを最新バージョンに更新するために必要なすべてのマイグレーションが実行されます。 +これにより、データベーススキーマを最新バージョンに更新するための必要なマイグレーションが実行されます。 + +**注意:** APM データベースがサイズが大きい場合、これらのマイグレーションは実行に時間がかかる可能性があります。オフピーク時にこのコマンドを実行することを検討してください。 + +### 0.4.3 から 0.5.0 へのアップグレード + +0.4.3 から 0.5.0 にアップグレードする場合、以下のコマンドを実行する必要があります: + +```bash +php vendor/bin/runway apm:config-migrate +``` -**注意:** APM データベースのサイズが大きい場合、これらのマイグレーションは実行に時間がかかる可能性があります。オフピーク時間にこのコマンドを実行することを検討してください。 +これにより、古い形式の `.runway-config.json` ファイルを使用した構成を、新しい形式の `config.php` ファイルにキー/値を保存する形式にマイグレーションします。 -## 古いデータの消去 +## 古いデータの削除 -データベースを整理するために、古いデータを消去できます。これは、忙しいアプリを実行していてデータベースのサイズを管理しやすくしたい場合に特に有用です。 -以下のコマンドを実行してこれを行います: +データベースを整理するために、古いデータを削除できます。これは、忙しいアプリを実行していてデータベースサイズを管理したい場合に特に有用です。 +以下のコマンドを実行してください: ```bash php vendor/bin/runway apm:purge ``` -これにより、データベースから 30 日より古いすべてのデータが削除されます。`--days` オプションに異なる値を渡すことで、日数を調整できます: +これにより、データベースから 30 日以上前のすべてのデータが削除されます。`--days` オプションに異なる値を渡すことで、日数を調整できます: ```bash php vendor/bin/runway apm:purge --days 7 ``` -これにより、データベースから 7 日より古いすべてのデータが削除されます。 +これにより、データベースから 7 日以上前のすべてのデータが削除されます。 ## トラブルシューティング -困っていますか?これを試してください: +困ったら、これを試してください: - **ダッシュボードにデータがない?** - - ワーカーが実行中ですか?`ps aux | grep apm:worker` をチェック。 - - 構成パスが一致しますか?`.runway-config.json` の DSN が実際のファイルにポイントしていることを確認。 - - 保留中の指標を処理するために `php vendor/bin/runway apm:worker` を手動で実行。 + - ワーカーが実行中か?`ps aux | grep apm:worker` をチェック。 + - 構成パスが一致するか?`.runway-config.json` の DSN が実際のファイル指向を確認。 + - `php vendor/bin/runway apm:worker` を手動で実行して保留中のメトリクスを処理。 -- **ワーカーのエラー?** +- **ワーカーエラー?** - SQLite ファイルを確認(例:`sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`)。 - - PHP ログでスタック トレースを確認。 + - PHP ログでスタックトレースを確認。 -- **ダッシュボードが開始されない?** +- **ダッシュボードが起動しない?** - ポート 8001 が使用中?`--port 8080` を使用。 - PHP が見つからない?`--php-path /usr/bin/php` を使用。 - - ファイアウォールがブロック?ポートを開放するか、`--host localhost` を使用。 + - ファイアウォールがブロック?ポートを開放するか `--host localhost` を使用。 - **遅すぎる?** - - サンプル レートを下げる:`$Apm = new Apm($ApmLogger, 0.05)` (5%)。 - - バッチ サイズを減らす:`--batch_size 20`。 + - サンプルレートを下げる:`$Apm = new Apm($ApmLogger, 0.05)` (5%)。 + - バッチサイズを減らす:`--batch_size 20`。 - **例外/エラーが追跡されない?** - - プロジェクトで [Tracy](https://tracy.nette.org/) が有効の場合、Flight のエラー処理をオーバーライドします。Tracy を無効にして、`Flight::set('flight.handle_errors', true);` が設定されていることを確認してください。 + - プロジェクトで [Tracy](https://tracy.nette.org/) が有効の場合、Flight のエラーハンドリングをオーバーライドします。Tracy を無効にし、`Flight::set('flight.handle_errors', true);` が設定されていることを確認してください。 -- **データベース クエリが追跡されない?** +- **データベースクエリが追跡されない?** - データベース接続に `PdoWrapper` を使用していることを確認。 - - コンストラクタの最後の引数を `true` にしていることを確認。 \ No newline at end of file + - コンストラクタの最後の引数が `true` であることを確認。 \ No newline at end of file diff --git a/content/v3/ja/awesome-plugins/awesome_plugins.md b/content/v3/ja/awesome-plugins/awesome_plugins.md index ad13cc13..4abe21ea 100644 --- a/content/v3/ja/awesome-plugins/awesome_plugins.md +++ b/content/v3/ja/awesome-plugins/awesome_plugins.md @@ -1,40 +1,40 @@ # 素晴らしいプラグイン -Flight は非常に拡張性が高いです。Flight アプリケーションに機能を追加するために使用できるプラグインがいくつかあります。一部は Flight チームによって公式にサポートされており、他のものは開始するためのマイクロ/ライトライブラリです。 +Flight は非常に拡張性が高いです。Flight アプリケーションに機能を追加するために使用できるプラグインがいくつかあります。一部は Flight チームによって公式にサポートされており、他のものはあなたが始めるのを助けるマイクロ/ライトライブラリです。 ## API ドキュメント -API ドキュメントは、あらゆる API にとって重要です。開発者が API とどのようにやり取りするかを理解し、返されるものを期待することを助けます。Flight プロジェクトの API ドキュメントを生成するのに役立つツールがいくつかあります。 +API ドキュメントは、API にとって非常に重要です。開発者が API とどのようにやり取りし、返されるものを期待するかを理解するのに役立ちます。Flight プロジェクトの API ドキュメントを生成するのに役立つツールがいくつかあります。 -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber によるブログ投稿で、OpenAPI Spec を FlightPHP と使用して API ファーストのアプローチで API を構築する方法について説明しています。 +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber によるブログ記事で、OpenAPI Spec を FlightPHP と使用して API ファーストアプローチで API を構築する方法について説明しています。 - [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI は、Flight プロジェクトの API ドキュメントを生成するのに役立つ優れたツールです。非常に使いやすく、ニーズに合わせてカスタマイズできます。これは Swagger ドキュメントを生成するための PHP ライブラリです。 ## アプリケーション パフォーマンス監視 (APM) -アプリケーション パフォーマンス監視 (APM) は、あらゆるアプリケーションにとって重要です。アプリケーションのパフォーマンスを理解し、ボトルネックがどこにあるかを特定するのに役立ちます。Flight で使用できる APM ツールがいくつかあります。 +アプリケーション パフォーマンス監視 (APM) は、アプリケーションにとって非常に重要です。アプリケーションのパフォーマンスを理解し、ボトルネックがどこにあるかを特定するのに役立ちます。Flight で使用できる APM ツールがいくつかあります。 - official [flightphp/apm](/awesome-plugins/apm) - Flight APM は、Flight アプリケーションを監視するために使用できるシンプルな APM ライブラリです。アプリケーションのパフォーマンスを監視し、ボトルネックを特定するのに役立ちます。 ## 非同期 -Flight はすでに高速なフレームワークですが、ターボエンジンを追加するとすべてがより楽しく(そして挑戦的)になります! +Flight はすでに高速なフレームワークですが、それにターボエンジンを追加するとすべてがより楽しく(そして挑戦的)になります! -- [flightphp/async](/awesome-plugins/async) - 公式の Flight Async ライブラリです。このライブラリは、アプリケーションに非同期処理を追加するシンプルな方法です。Swoole/Openswoole を基盤として使用し、タスクを非同期で実行するシンプルで効果的な方法を提供します。 +- [flightphp/async](/awesome-plugins/async) - 公式の Flight Async ライブラリです。このライブラリは、アプリケーションに非同期処理を追加するシンプルな方法です。バックエンドで Swoole/Openswoole を使用して、タスクを非同期で実行するためのシンプルで効果的な方法を提供します。 -## 認証/権限 +## 認可/権限 -認証と権限は、誰が何にアクセスできるかを制御する必要があるあらゆるアプリケーションにとって重要です。 +認可と権限は、誰が何にアクセスできるかを制御する必要があるアプリケーションにとって非常に重要です。 -- official [flightphp/permissions](/awesome-plugins/permissions) - 公式の Flight Permissions ライブラリです。このライブラリは、アプリケーションにユーザーおよびアプリケーション レベルの権限を追加するシンプルな方法です。 +- official [flightphp/permissions](/awesome-plugins/permissions) - 公式の Flight Permissions ライブラリです。このライブラリは、アプリケーションにユーザーおよびアプリケーション レベルの権限を追加するシンプルな方法です。 ## キャッシュ キャッシュはアプリケーションを高速化する優れた方法です。Flight で使用できるキャッシュ ライブラリがいくつかあります。 -- official [flightphp/cache](/awesome-plugins/php-file-cache) - 軽量でシンプルなスタンドアロン PHP イン-File キャッシュ クラス +- official [flightphp/cache](/awesome-plugins/php-file-cache) - 軽量でシンプルなスタンドアロン PHP インデータベースキャッシュクラス ## CLI -CLI アプリケーションは、アプリケーションとやり取りする優れた方法です。コントローラーを生成したり、すべてのルートを表示したり、その他さまざまなことを行うことができます。 +CLI アプリケーションは、アプリケーションとやり取りする優れた方法です。コントローラーを生成したり、すべてのルートを表示したり、その他多くのことを行うことができます。 - official [flightphp/runway](/awesome-plugins/runway) - Runway は、Flight アプリケーションを管理するのに役立つ CLI アプリケーションです。 @@ -42,32 +42,32 @@ CLI アプリケーションは、アプリケーションとやり取りする クッキーは、クライアント側に少量のデータを保存する優れた方法です。ユーザー設定、アプリケーション設定などを保存するために使用できます。 -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie は、クッキーを管理するためのシンプルで効果的な PHP ライブラリです。 +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie は、クッキーを管理するためのシンプルで効果的な方法を提供する PHP ライブラリです。 ## デバッグ -ローカル環境で開発する際のデバッグは重要です。デバッグ体験を向上させるプラグインがいくつかあります。 +ローカル環境で開発する際、デバッグは非常に重要です。デバッグ体験を向上させるプラグインがいくつかあります。 -- [tracy/tracy](/awesome-plugins/tracy) - Flight で使用できる完全機能のエラー ハンドラーです。アプリケーションのデバッグに役立つパネルがいくつかあります。また、拡張して独自のパネルを追加することも非常に簡単です。 -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) エラー ハンドラーと使用され、Flight プロジェクト専用のデバッグに役立つ追加のパネルをいくつか追加します。 +- [tracy/tracy](/awesome-plugins/tracy) - Flight で使用できる完全なエラーハンドラーです。アプリケーションのデバッグに役立つパネルがいくつかあります。また、拡張して独自のパネルを追加することも非常に簡単です。 +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) エラーハンドラーと使用され、このプラグインは Flight プロジェクト特有のデバッグに役立つ追加のパネルをいくつか追加します。 ## データベース データベースはほとんどのアプリケーションのコアです。これによりデータを保存および取得します。一部のデータベース ライブラリはクエリを書くためのラッパーであり、他のものは完全な ORM です。 -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - コアの一部である公式の Flight PDO Wrapper です。クエリを書いて実行するプロセスを簡素化するためのシンプルなラッパーです。ORM ではありません。 +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - コアの一部である公式の Flight PDO Wrapper です。クエリの書き方と実行を簡素化するためのシンプルなラッパーです。ORM ではありません。 - official [flightphp/active-record](/awesome-plugins/active-record) - 公式の Flight ActiveRecord ORM/マッパーです。データベースからデータを簡単に取得および保存するための優れたライブラリです。 - [byjg/php-migration](/awesome-plugins/migrations) - プロジェクトのすべてのデータベース変更を追跡するためのプラグインです。 ## 暗号化 -暗号化は、機密データを保存するあらゆるアプリケーションにとって重要です。データを暗号化および復号化するのはそれほど難しくありませんが、暗号化キーを適切に保存することは [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [です](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [が](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)、難しい場合があります。最も重要なのは、暗号化キーを公開ディレクトリに保存したり、コード リポジトリにコミットしたりしないことです。 +暗号化は、機密データを保存するアプリケーションにとって非常に重要です。データを暗号化および復号化するのはそれほど難しくありませんが、暗号化キーを適切に保存することは [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [です](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [が難しい](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key) です。最も重要なのは、暗号化キーを公開ディレクトリに保存したり、コード リポジトリにコミットしたりしないことです。 -- [defuse/php-encryption](/awesome-plugins/php-encryption) - データを暗号化および復号化するために使用できるライブラリです。データを暗号化および復号化するのを開始するのはかなりシンプルです。 +- [defuse/php-encryption](/awesome-plugins/php-encryption) - データを暗号化および復号化するために使用できるライブラリです。データを暗号化および復号化するためのセットアップはかなりシンプルです。 -## ジョブ キュー +## ジョブキュー -ジョブ キューは、タスクを非同期で処理するのに非常に役立ちます。これはメールの送信、画像の処理、またはリアルタイムで実行する必要のないあらゆるものです。 +ジョブキューは、タスクを非同期で処理するのに非常に役立ちます。これは、メールの送信、画像の処理、またはリアルタイムで実行する必要がないあらゆるものです。 - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue は、ジョブを非同期で処理するために使用できるライブラリです。beanstalkd、MySQL/MariaDB、SQLite、PostgreSQL と使用できます。 @@ -75,23 +75,23 @@ CLI アプリケーションは、アプリケーションとやり取りする セッションは API にはあまり有用ではありませんが、Web アプリケーションを構築する際には、状態とログイン情報を維持するために重要です。 -- official [flightphp/session](/awesome-plugins/session) - 公式の Flight Session ライブラリです。セッションデータを保存および取得するために使用できるシンプルなセッション ライブラリです。PHP のビルトイン セッション ハンドリングを使用します。 -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP セッション マネージャー(非ブロッキング、フラッシュ、セグメント、セッション暗号化)。セッションデータのオプションの暗号化/復号化に PHP open_ssl を使用します。 +- official [flightphp/session](/awesome-plugins/session) - 公式の Flight Session ライブラリです。セッションデータを保存および取得するために使用できるシンプルなセッション ライブラリです。PHP のビルトインセッション処理を使用します。 +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (非ブロッキング、フラッシュ、セグメント、セッション暗号化)。セッションデータのオプションの暗号化/復号化のために PHP open_ssl を使用します。 ## テンプレート -テンプレートは UI を備えたあらゆる Web アプリケーションのコアです。Flight で使用できるテンプレート エンジンがいくつかあります。 +テンプレートは UI を持つ Web アプリケーションのコアです。Flight で使用できるテンプレート エンジンがいくつかあります。 - deprecated [flightphp/core View](/learn#views) - コアの一部である非常に基本的なテンプレート エンジンです。プロジェクトに数ページ以上ある場合は使用を推奨しません。 -- [latte/latte](/awesome-plugins/latte) - Latte は、Twig や Smarty よりも PHP 構文に近い、非常に使いやすい完全機能のテンプレート エンジンです。また、拡張して独自のフィルターや関数を追加することも非常に簡単です。 -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate は、アセット コンパイル、テンプレート継承、変数処理を備えた強力な PHP テンプレート エンジンです。自動 CSS/JS 最小化、キャッシュ、Base64 エンコーディング、およびオプションの Flight PHP フレームワーク統合を特徴とします。 +- [latte/latte](/awesome-plugins/latte) - Latte は、Twig や Smarty よりも PHP 構文に近い、非常に使いやすく完全なテンプレート エンジンです。また、独自のフィルターと関数を拡張して追加することも非常に簡単です。 +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate は、アセットコンパイル、テンプレート継承、変数処理を備えた強力な PHP テンプレート エンジンです。自動 CSS/JS 圧縮、キャッシュ、Base64 エンコーディング、およびオプションの Flight PHP フレームワーク統合を備えています。 ## WordPress 統合 -WordPress プロジェクトで Flight を使用したいですか? そのための便利なプラグインがあります! +WordPress プロジェクトで Flight を使用したいですか?そのための便利なプラグインがあります! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - この WordPress プラグインにより、WordPress と並行して Flight を実行できます。Flight フレームワークを使用して WordPress サイトにカスタム API、マイクロサービス、または完全なアプリを追加するのに最適です。両方の世界の最高のものを手に入れたい場合に超便利です! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - この WordPress プラグインにより、WordPress と Flight を並行して実行できます。Flight フレームワークを使用して WordPress サイトにカスタム API、マイクロサービス、または完全なアプリを追加するのに最適です。両方の世界の最高のものを手に入れたい場合に超便利です! ## 貢献 -共有したいプラグインがありますか? リストに追加するためのプルリクエストを送信してください! \ No newline at end of file +共有したいプラグインがありますか?リストに追加するためのプルリクエストを送信してください! \ No newline at end of file diff --git a/content/v3/ja/awesome-plugins/comment_template.md b/content/v3/ja/awesome-plugins/comment_template.md index a5c528dd..cee679b6 100644 --- a/content/v3/ja/awesome-plugins/comment_template.md +++ b/content/v3/ja/awesome-plugins/comment_template.md @@ -1,14 +1,14 @@ # CommentTemplate -[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) は、強力な PHP テンプレートエンジンで、アセットのコンパイル、テンプレートの継承、変数の処理を備えています。組み込みの CSS/JS 最小化とキャッシュにより、シンプルで柔軟なテンプレート管理を提供します。 +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) は、強力な PHP テンプレートエンジンで、アセットのコンパイル、テンプレートの継承、変数の処理を備えています。ビルトインの CSS/JS 最小化とキャッシュにより、シンプルで柔軟なテンプレート管理を提供します。 ## 機能 - **テンプレートの継承**: レイアウトを使用し、他のテンプレートを含める -- **アセットのコンパイル**: CSS/JS の自動最小化とキャッシュ +- **アセットのコンパイル**: 自動 CSS/JS 最小化とキャッシュ - **変数の処理**: フィルターとコマンド付きのテンプレート変数 - **Base64 エンコーディング**: アセットをデータ URI としてインライン化 -- **Flight Framework 統合**: Flight PHP フレームワークとのオプションの統合 +- **Flight Framework との統合**: Flight PHP フレームワークとのオプションの統合 ## インストール @@ -33,16 +33,16 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // ルートディレクトリ(index.phpがある場所)- Webアプリケーションのドキュメントルート + // ルートディレクトリ(index.php が存在する場所) - Web アプリケーションのドキュメントルート $engine->setPublicPath(__DIR__); - // テンプレートファイルディレクトリ - 相対パスと絶対パスの両方をサポート - $engine->setSkinPath('views'); // パブリックパス基準の相対パス + // テンプレートファイルのディレクトリ - 相対パスと絶対パスの両方をサポート + $engine->setSkinPath('views'); // パブリックパスに対する相対パス - // コンパイルされたアセットが保存される場所 - 相対パスと絶対パスの両方をサポート - $engine->setAssetPath('assets'); // パブリックパス基準の相対パス + // コンパイルされたアセットの保存場所 - 相対パスと絶対パスの両方をサポート + $engine->setAssetPath('assets'); // パブリックパスに対する相対パス - // テンプレートファイル拡張子 + // テンプレートファイルの拡張子 $engine->setFileExtension('.php'); }); @@ -63,10 +63,10 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__, // publicPath - ルートディレクトリ(index.phpがある場所) - 'views', // skinPath - テンプレートパス(相対/絶対パスをサポート) - 'assets', // assetPath - コンパイルされたアセットパス(相対/絶対パスをサポート) - '.php' // fileExtension - テンプレートファイル拡張子 + __DIR__, // publicPath - ルートディレクトリ(index.php が存在する場所) + 'views', // skinPath - テンプレートパス(相対/絶対をサポート) + 'assets', // assetPath - コンパイルされたアセットパス(相対/絶対をサポート) + '.php' // fileExtension - テンプレートファイルの拡張子 ]); $app->map('render', function(string $template, array $data) use ($app): void { @@ -76,27 +76,27 @@ $app->map('render', function(string $template, array $data) use ($app): void { ## パス設定 -CommentTemplate は相対パスと絶対パスの両方に対するインテリジェントなパス処理を提供します: +CommentTemplate は、相対パスと絶対パスの両方に対してインテリジェントなパス処理を提供します: ### パブリックパス -**パブリックパス**は、通常 `index.php` が配置されている Web アプリケーションのルートディレクトリです。これは Web サーバーがファイルを提供するドキュメントルートです。 +**パブリックパス** は、Web アプリケーションのルートディレクトリで、通常 `index.php` が存在する場所です。これは Web サーバーがファイルを配信するドキュメントルートです。 ```php -// 例: index.phpが /var/www/html/myapp/index.php にある場合 +// 例: index.php が /var/www/html/myapp/index.php にある場合 $template->setPublicPath('/var/www/html/myapp'); // ルートディレクトリ -// Windows例: index.phpが C:\xampp\htdocs\myapp\index.php にある場合 +// Windows の例: index.php が C:\xampp\htdocs\myapp\index.php にある場合 $template->setPublicPath('C:\\xampp\\htdocs\\myapp'); ``` ### テンプレートパス設定 -テンプレートパスは相対パスと絶対パスの両方をサポートします: +テンプレートパスは、相対パスと絶対パスの両方をサポートします: ```php $template = new Engine(); -$template->setPublicPath('/var/www/html/myapp'); // ルートディレクトリ(index.phpがある場所) +$template->setPublicPath('/var/www/html/myapp'); // ルートディレクトリ(index.php が存在する場所) // 相対パス - パブリックパスと自動的に結合 $template->setSkinPath('views'); // → /var/www/html/myapp/views/ @@ -106,11 +106,11 @@ $template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/ $template->setSkinPath('/var/www/templates'); // → /var/www/templates/ $template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ -// Windows絶対パス +// Windows 絶対パス $template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ $template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ -// UNCパス(Windowsネットワーク共有) +// UNC パス(Windows ネットワーク共有) $template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ ``` @@ -127,83 +127,33 @@ $template->setAssetPath('static/files'); // → /var/www/html/myapp/static/file $template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ $template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ -// Windows絶対パス +// Windows 絶対パス $template->setAssetPath('C:\\www\\static'); // → C:\www\static\ $template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ -// UNCパス(Windowsネットワーク共有) +// UNC パス(Windows ネットワーク共有) $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ ``` -**スマートパス検出:** - -- **相対パス**: 先頭の区切り文字(`/`、`\`)やドライブ文字なし -- **Unix絶対**: `/` で始まる(例:`/var/www/assets`) -- **Windows絶対**: ドライブ文字で始まる(例:`C:\www`、`D:/assets`) -- **UNCパス**: `\\` で始まる(例:`\\server\share`) - -**動作方法:** - -- すべてのパスはタイプに基づいて自動的に解決されます(相対 vs 絶対) -- 相対パスはパブリックパスと結合されます -- `@css` と `@js` は以下の場所に最小化されたファイルを作成します:`{resolvedAssetPath}/css/` または `{resolvedAssetPath}/js/` -- `@asset` は単一ファイルを以下の場所にコピーします:`{resolvedAssetPath}/{relativePath}` -- `@assetDir` はディレクトリを以下の場所にコピーします:`{resolvedAssetPath}/{relativePath}` -- スマートキャッシュ: ソースが宛先より新しい場合のみファイルがコピーされます - -```php -register('view', Engine::class, [], function (Engine $engine) use ($app) { - // テンプレートファイルが保存される場所 - $engine->setTemplatesPath(__DIR__ . '/views'); - - // パブリックアセットが提供される場所 - $engine->setPublicPath(__DIR__ . '/public'); - - // コンパイルされたアセットが保存される場所 - $engine->setAssetPath('assets'); - - // テンプレートファイルの拡張子 - $engine->setFileExtension('.php'); -}); - -$app->map('render', function(string $template, array $data) use ($app): void { - echo $app->view()->render($template, $data); -}); -``` - -### 方法 2: コンストラクタパラメータを使用 - -```php -register('view', Engine::class, [ - __DIR__ . '/public', // publicPath - アセットが提供される場所 - __DIR__ . '/views', // skinPath - テンプレートファイルが保存される場所 - 'assets', // assetPath - コンパイルされたアセットが保存される場所 - '.php' // fileExtension - テンプレートファイルの拡張子 -]); +**仕組み:** -$app->map('render', function(string $template, array $data) use ($app): void { - echo $app->view()->render($template, $data); -}); -``` +- すべてのパスはタイプ(相対 vs 絶対)に基づいて自動的に解決される +- 相対パスはパブリックパスと結合される +- `@css` と `@js` は最小化されたファイルを `{resolvedAssetPath}/css/` または `{resolvedAssetPath}/js/` に作成 +- `@asset` は単一ファイルを `{resolvedAssetPath}/{relativePath}` にコピー +- `@assetDir` はディレクトリを `{resolvedAssetPath}/{relativePath}` にコピー +- スマートキャッシュ: ソースがデスティネーションより新しい場合のみファイルをコピー ## テンプレートディレクティブ -### レイアウトの継承 +### レイアウト継承 共通の構造を作成するためにレイアウトを使用します: @@ -252,12 +202,11 @@ CommentTemplate は異なる JavaScript 読み込み戦略をサポートしま #### CSS/JS ファイル内のアセットディレクティブ -CommentTemplate はコンパイル中に CSS と JavaScript ファイル内のアセットディレクティブも処理します: +CommentTemplate は、コンパイル中に CSS と JavaScript ファイル内のアセットディレクティブも処理します: -**CSS の例:** +**CSS の例:** ```css -/* CSS ファイル内 */ -/* フォントファイル */ +/* あなたの CSS ファイル内で */ @font-face { font-family: 'CustomFont'; src: url('') format('woff2'); @@ -272,18 +221,18 @@ CommentTemplate はコンパイル中に CSS と JavaScript ファイル内の } ``` -**JavaScript の例:** +**JavaScript の例:** ```javascript -/* JS ファイル内 */ +/* あなたの JS ファイル内で */ const fontUrl = ''; const imageData = ''; ``` #### Base64 エンコーディング ```html - + ``` -**例:** +**例:** ```html Logo @@ -294,16 +243,16 @@ const imageData = ''; #### アセットのコピー ```html - - + + ``` -**例:** +**例:** ```html Hero Banner -パンフレットダウンロード +ブロシュアをダウンロード - + ``` @@ -312,17 +261,17 @@ const imageData = ''; ```html ``` -**例:** +**例:** ```html
          -

          ウェブサイトへようこそ

          +

          当社のウェブサイトへようこそ

          -

          メインコンテンツはここ...

          +

          ここにメインコンテンツ...

          @@ -355,30 +304,30 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### 複数フィルターのチェーン +#### 変数コマンド ```html {$content|striptag|trim|escape} ``` ### コメント -テンプレートコメントは出力から完全に削除され、最終的な HTML には表示されません: +テンプレートコメントは出力から完全に削除され、最終的な HTML に表示されません: ```html -{* これは単一行のテンプレートコメントです *} +{* これは1行のテンプレートコメントです *} {* - これは複数行にわたる - マルチライン - テンプレートコメントです + これは複数行の + テンプレートコメントです + 複数行にわたります *}

          {$title}

          -{* デバッグコメント: title変数が動作するかチェック *} +{* デバッグコメント: title 変数が動作するかを確認 *}

          {$content}

          ``` -**注記**: テンプレートコメント `{* ... *}` は HTML コメント `` とは異なります。テンプレートコメントは処理中に削除され、ブラウザには届きません。 +**注意**: テンプレートコメント `{* ... *}` は HTML コメント `` と異なります。テンプレートコメントは処理中に削除され、ブラウザに到達しません。 ## 例のプロジェクト構造 diff --git a/content/v3/ja/awesome-plugins/runway.md b/content/v3/ja/awesome-plugins/runway.md index 1046db4a..a54c0738 100644 --- a/content/v3/ja/awesome-plugins/runway.md +++ b/content/v3/ja/awesome-plugins/runway.md @@ -1,12 +1,12 @@ -# ランウェイ +# Runway -ランウェイはCLIアプリケーションで、Flightアプリケーションの管理を支援します。コントローラを生成したり、すべてのルートを表示したりすることができます。優れた[adhocore/php-cli](https://github.com/adhocore/php-cli)ライブラリに基づいています。 +Runway は、Flight アプリケーションを管理するのに役立つ CLI アプリケーションです。コントローラーを生成したり、すべてのルートを表示したり、その他さまざまな機能を提供します。これは優れた [adhocore/php-cli](https://github.com/adhocore/php-cli) ライブラリを基にしています。 -[こちらをクリック](https://github.com/flightphp/runway)して、コードを表示してください。 +コードを見るには [こちら](https://github.com/flightphp/runway) をクリックしてください。 ## インストール -Composerを使用してインストールしてください。 +Composer でインストールします。 ```bash composer require flightphp/runway @@ -14,40 +14,40 @@ composer require flightphp/runway ## 基本設定 -ランウェイを実行する最初の回は、セットアッププロセスを進め、プロジェクトのルートに`.runway.json`構成ファイルを作成します。このファイルには、ランウェイが正しく動作するために必要ないくつかの構成が含まれています。 +Runway を初めて実行すると、セットアッププロセスを実行し、プロジェクトのルートに `.runway.json` 設定ファイルを作成します。このファイルには、Runway が正常に動作するために必要な設定が含まれています。 -## 使用法 +## 使用方法 -ランウェイには、Flightアプリケーションを管理するために使用できる複数のコマンドがあります。ランウェイを使用する方法は2つあります。 +Runway には、Flight アプリケーションを管理するためのさまざまなコマンドがあります。Runway を使用する簡単な方法は 2 つあります。 1. スケルトンプロジェクトを使用している場合、プロジェクトのルートから `php runway [command]` を実行できます。 -1. Composerを介してインストールされたパッケージとしてRunwayを使用している場合、プロジェクトのルートから `vendor/bin/runway [command]` を実行できます。 +1. Composer 経由でインストールしたパッケージとして Runway を使用している場合、プロジェクトのルートから `vendor/bin/runway [command]` を実行できます。 -任意のコマンドに対して、`--help`フラグを渡すと、そのコマンドの使用方法に関するより詳細な情報を取得できます。 +任意のコマンドに対して、`--help` フラグを渡すことで、そのコマンドの使用方法についての詳細情報を取得できます。 ```bash php runway routes --help ``` -以下はいくつかの例です。 +以下にいくつかの例を示します: -### コントローラを生成する +### コントローラーの生成 -`.runway.json`ファイルの構成に基づいて、デフォルトの場所は `app/controllers/` ディレクトリにコントローラを生成します。 +`.runway.json` ファイルの設定に基づいて、デフォルトの場所に `app/controllers/` ディレクトリでコントローラーを生成します。 ```bash php runway make:controller MyController ``` -### アクティブレコードモデルを生成する +### Active Record モデルの生成 -`.runway.json`ファイルの構成に基づいて、デフォルトの場所は `app/records/` ディレクトリにコントローラを生成します。 +`.runway.json` ファイルの設定に基づいて、デフォルトの場所に `app/records/` ディレクトリでコントローラーを生成します。 ```bash php runway make:record users ``` -たとえば、次のスキーマを持つ `users` テーブルがある場合:`id`、`name`、`email`、`created_at`、`updated_at`、`app/records/UserRecord.php` ファイルに類似したファイルが作成されます: +たとえば、`users` テーブルに以下のスキーマがある場合:`id`、`name`、`email`、`created_at`、`updated_at`、`app/records/UserRecord.php` ファイルに以下の類似したファイルが作成されます: ```php $config .runway-config.jsonからのJSON構成 + * @param array $config .runway-config.json からの JSON 設定 */ public function __construct(array $config) { - parent::__construct('make:example', 'ドキュメントの例を作成', $config); - $this->argument('', '面白いGIFの名前'); + parent::__construct('make:example', 'ドキュメント用の例を作成', $config); + $this->argument('', '面白い GIF の名前'); } /** @@ -138,17 +138,56 @@ class ExampleCommand extends AbstractBaseCommand * * @return void */ - public function execute(string $controller) + public function execute() { $io = $this->app()->io(); - $io->info('例を作成します...'); + $io->info('例を作成中...'); - // ここで何かを実行 + // ここで何かをします $io->ok('例が作成されました!'); } } ``` -独自のカスタムコマンドをFlightアプリケーションに組み込む方法については、[adhocore/php-cliドキュメント](https://github.com/adhocore/php-cli)を参照してください! \ No newline at end of file +Flight アプリケーションに独自のカスタムコマンドを構築する方法についての詳細は、[adhocore/php-cli ドキュメント](https://github.com/adhocore/php-cli) を参照してください! + +### 設定 + +Runway の設定をカスタマイズする必要がある場合、プロジェクトのルートに `.runway-config.json` ファイルを作成できます。以下に設定できる追加の設定を示します: + +```js +{ + + // アプリケーション ディレクトリが配置されている場所 + "app_root": "app/", + + // ルート index ファイルが配置されているディレクトリ + "index_root": "public/", + + // 他のプロジェクトのルートへのパス + "root_paths": [ + "/home/user/different-project", + "/var/www/another-project" + ], + + // ベース パスは通常設定する必要はありませんが、必要に応じて使用できます + "base_paths": { + "/includes/libs/vendor", // vendor ディレクトリなどのユニークなパスがある場合 + }, + + // 最終パスは、コマンド ファイルを検索するプロジェクト内の場所 + "final_paths": { + "src/diff-path/commands", + "app/module/admin/commands", + }, + + // フルパスを追加したい場合、問題ありません(プロジェクト ルートからの絶対パスまたは相対パス) + "paths": [ + "/home/user/different-project/src/diff-path/commands", + "/var/www/another-project/app/module/admin/commands", + "app/my-unique-commands" + ] +} +``` \ No newline at end of file diff --git a/content/v3/ja/examples.md b/content/v3/ja/examples.md index 881ab74e..bf3efc04 100644 --- a/content/v3/ja/examples.md +++ b/content/v3/ja/examples.md @@ -1,26 +1,27 @@ # クイックスタートが必要ですか? -新しい Flight プロジェクトを始めるために、2つのオプションがあります: +新しい Flight プロジェクトを始めるための 2 つのオプションがあります: -- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): コントローラーとビューを含む、より充実した例。 +- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): コントローラーとビューを含む、より完全な例。 - [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): アプリを単一のシンプルなファイルで実行するために必要なすべてを含む単一ファイル。 コミュニティ提供の例: -- [flightravel](https://github.com/fadrian06-templates/flighravel): Laravel ディレクトリ付きの FlightPHP、PHP ツール + GH Actions -- [fleact](https://github.com/flightphp/fleact) - ReactJS 統合の FlightPHP スターターキット。 -- [flastro](https://github.com/flightphp/flastro) - Astro 統合の FlightPHP スターターキット。 -- [velt](https://github.com/flightphp/velt) - Velt は FlightPHP バックエンド付きの Svelte スターターテンプレートで、クイックで簡単です。 +- [flightravel](https://github.com/fadrian06-templates/flighravel): Laravel ディレクトリ、PHP ツール + GH Actions を備えた FlightPHP。 +- [fleact](https://github.com/flightphp/fleact) - ReactJS 統合を備えた FlightPHP スターターキット。 +- [flastro](https://github.com/flightphp/flastro) - Astro 統合を備えた FlightPHP スターターキット。 +- [velt](https://github.com/flightphp/velt) - Velt は FlightPHP バックエンドを備えた迅速で簡単な Svelte スターターテンプレートです。 ## インスピレーションが必要ですか? -これらは Flight チームの公式スポンサーではありませんが、Flight で構築した自分のプロジェクトの構造についてのアイデアを提供する可能性があります! +これらは Flight チームの公式スポンサーではありませんが、Flight で構築した独自のプロジェクトの構造化方法についてのアイデアを提供する可能性があります! +- [ASC REST API Spell Checker](https://github.com/AlMosahih-ASC/asc-api-sample) - FlightPHP と ArPHP ライブラリを使用して構築された、アラビア語のスペルチェックのための軽量 REST API。この API は、誤字検出と修正提案を含むアラビア語テキストのスペルチェック機能を提供します。 - [Eventify](https://github.com/ilhanklisura/eventify) - Eventify はイベント主催者と参加者を結ぶシングルページアプリです。PHP (FlightPHP)、JavaScript、MySQL で構築され、JWT 認証、イベント管理、OpenAPI を使用した RESTful API ドキュメントを備えています。 -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental は PHP (FlightPHP)、JavaScript、MySQL で構築されたシングルページのモバイルフレンドリーなカーレンタルウェブアプリケーションです。ユーザー登録、閲覧、車の予約をサポートし、管理者は車、ユーザー、予約を管理できます。アプリには REST API、JWT 認証、モダンなレンタル体験のためのレスポンシブデザインが備わっています。 -- [Decay](https://github.com/boxybird/decay) - ゾンビに関する HTMX と SleekDB 付きの Flight v3!([Demo](https://decay.andrewrhyand.com)) -- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - ミドルウェア、コントローラー、Active Record、Latte 付きの Flight v3。 -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Flight フレームワークを使用したシンプルな CRUD API プロジェクトで、新しいユーザーが CRUD 操作とデータベース接続付きの PHP アプリケーションを迅速にセットアップするための基本構造を提供します。このプロジェクトは RESTful API 開発のための Flight の使用方法を示し、初心者向けの学習ツールおよびより経験豊富な開発者向けの便利なスターターキットとして理想的です。 +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental は PHP (FlightPHP)、JavaScript、MySQL で構築された、シングルページのモバイルフレンドリーなカーレンタルウェブアプリケーションです。ユーザー登録、閲覧、車の予約をサポートし、管理者は車、ユーザー、予約を管理できます。アプリには REST API、JWT 認証、モダンなレンタル体験のためのレスポンシブデザインが備わっています。 +- [Decay](https://github.com/boxybird/decay) - ゾンビに関する HTMX と SleekDB を備えた Flight v3!([Demo](https://decay.andrewrhyand.com)) +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - ミドルウェア、コントローラー、Active Record、Latte を備えた Flight v3。 +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Flight フレームワークを使用したシンプルな CRUD API プロジェクトで、新しいユーザーが迅速に PHP アプリケーションを CRUD 操作とデータベース接続でセットアップするための基本構造を提供します。このプロジェクトは RESTful API 開発のための Flight の使用方法を示し、初心者向けの学習ツールおよび経験豊富な開発者向けの便利なスターターキットとして理想的です。 - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -31,7 +32,7 @@ - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 数週間の開発時間を節約する本番環境対応の認証フレームワーク。エンタープライズグレードのセキュリティ機能:2FA/TOTP、LDAP 統合、Azure SSO、インテリジェントなレート制限、セッション指紋認証、ブルートフォース保護、セキュリティ分析ダッシュボード、包括的な監査ログ、グラニュラーなロールベースアクセス制御。 +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 開発の数週間を節約する本番環境対応の認証フレームワーク。エンタープライズグレードのセキュリティを備えています:2FA/TOTP、LDAP 統合、Azure SSO、インテリジェントなレート制限、セッション指紋認証、ブルートフォース保護、セキュリティ分析ダッシュボード、包括的な監査ログ、細かなロールベースのアクセス制御。 ## 自分の例を共有したいですか? diff --git a/content/v3/ko/awesome-plugins/active_record.md b/content/v3/ko/awesome-plugins/active_record.md index 13de0393..abcd20fb 100644 --- a/content/v3/ko/awesome-plugins/active_record.md +++ b/content/v3/ko/awesome-plugins/active_record.md @@ -1,12 +1,12 @@ # Flight Active Record -액티브 레코드는 데이터베이스 엔티티를 PHP 객체에 매핑하는 것입니다. 간단히 말해, 데이터베이스에 사용자 테이블이 있다면, 해당 테이블의 행을 `User` 클래스와 코드베이스의 `$user` 객체로 "변환"할 수 있습니다. [기본 예제](#basic-example)를 참조하세요. +액티브 레코드는 데이터베이스 엔티티를 PHP 객체에 매핑하는 것입니다. 간단히 말해, 데이터베이스에 users 테이블이 있으면 테이블의 행을 코드베이스의 `User` 클래스와 `$user` 객체로 "번역"할 수 있습니다. [기본 예제](#basic-example)를 참조하세요. -GitHub에서 [여기](https://github.com/flightphp/active-record)를 클릭하여 저장소를 확인하세요. +GitHub의 저장소를 보려면 [여기](https://github.com/flightphp/active-record)를 클릭하세요. ## 기본 예제 -다음과 같은 테이블이 있다고 가정해 봅시다: +다음과 같은 테이블이 있다고 가정해 보겠습니다: ```sql CREATE TABLE users ( @@ -16,13 +16,13 @@ CREATE TABLE users ( ); ``` -이제 이 테이블을 나타내는 새로운 클래스를 설정할 수 있습니다: +이제 이 테이블을 나타내는 새 클래스를 설정할 수 있습니다: ```php /** - * 액티브 레코드 클래스는 일반적으로 단수형입니다. + * ActiveRecord 클래스는 보통 단수형입니다 * - * 테이블의 속성을 여기에 주석으로 추가하는 것이 강력히 권장됩니다. + * 테이블의 속성을 주석으로 여기에 추가하는 것이 강력히 권장됩니다 * * @property int $id * @property string $name @@ -31,7 +31,7 @@ CREATE TABLE users ( class User extends flight\ActiveRecord { public function __construct($database_connection) { - // 이렇게 설정할 수 있습니다. + // 이렇게 설정할 수 있습니다 parent::__construct($database_connection, 'users'); // 또는 이렇게 parent::__construct($database_connection, null, [ 'table' => 'users']); @@ -39,18 +39,18 @@ class User extends flight\ActiveRecord { } ``` -이제 마법이 일어나는 걸 지켜보세요! +이제 마법이 일어나는 것을 보세요! ```php -// sqlite용 -$database_connection = new PDO('sqlite:test.db'); // 이는 예시일 뿐이며, 실제 데이터베이스 연결을 사용할 것입니다. +// sqlite의 경우 +$database_connection = new PDO('sqlite:test.db'); // 이것은 예제일 뿐입니다. 실제 데이터베이스 연결을 사용할 가능성이 큽니다 -// mysql용 +// mysql의 경우 $database_connection = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'username', 'password'); // 또는 mysqli $database_connection = new mysqli('localhost', 'username', 'password', 'test_db'); -// 또는 객체 기반 생성 없이 mysqli +// 또는 객체 기반이 아닌 mysqli 생성 $database_connection = mysqli_connect('localhost', 'username', 'password', 'test_db'); $user = new User($database_connection); @@ -64,35 +64,35 @@ echo $user->id; // 1 $user->name = 'Joseph Mamma'; $user->password = password_hash('some cool password again!!!'); $user->insert(); -// 여기서 $user->save()를 사용할 수 없습니다. 그렇게 하면 업데이트로 인식됩니다! +// 여기서 $user->save()를 사용할 수 없으며, 업데이트로 인식할 것입니다! echo $user->id; // 2 ``` -이렇게 간단하게 새로운 사용자를 추가할 수 있었습니다! 데이터베이스에 사용자 행이 생겼으니, 어떻게 그것을 꺼낼 수 있을까요? +새 사용자를 추가하는 것이 이렇게 쉬웠습니다! 이제 데이터베이스에 사용자 행이 있으므로, 이를 어떻게 가져오나요? ```php -$user->find(1); // 데이터베이스에서 id = 1을 찾아서 반환합니다. +$user->find(1); // 데이터베이스에서 id = 1을 찾아 반환합니다. echo $user->name; // 'Bobby Tables' ``` -모든 사용자를 찾고 싶다면 어떻게 할까요? +모든 사용자를 찾고 싶다면? ```php $users = $user->findAll(); ``` -특정 조건과 함께라면 어떻게 할까요? +특정 조건으로? ```php $users = $user->like('name', '%mamma%')->findAll(); ``` -이것이 얼마나 재미있나요? 설치하고 시작해봅시다! +얼마나 재미있나요? 설치하고 시작해 보세요! ## 설치 -Composer로 간단히 설치합니다. +Composer로 간단히 설치하세요 ```php composer require flightphp/active-record @@ -100,43 +100,43 @@ composer require flightphp/active-record ## 사용법 -이 라이브러리는 독립 실행형 라이브러리로 사용할 수도 있고 Flight PHP Framework와 함께 사용할 수도 있습니다. 완전히 당신의 선택입니다. +이것은 독립 라이브러리로 사용하거나 Flight PHP Framework와 함께 사용할 수 있습니다. 완전히 당신의 선택입니다. -### 독립형 -생성자에 PDO 연결을 전달해야 합니다. +### 독립 사용 +생성자에 PDO 연결을 전달하기만 하세요. ```php -$pdo_connection = new PDO('sqlite:test.db'); // 이는 예시일 뿐이며, 실제 데이터베이스 연결을 사용할 것입니다. +$pdo_connection = new PDO('sqlite:test.db'); // 이것은 예제일 뿐입니다. 실제 데이터베이스 연결을 사용할 가능성이 큽니다 $User = new User($pdo_connection); ``` -> 항상 생성자에 데이터베이스 연결을 설정하고 싶지 않으신가요? 다른 아이디어는 [데이터베이스 연결 관리](#database-connection-management)를 참조하세요! +> 생성자에서 항상 데이터베이스 연결을 설정하지 않으려면? [데이터베이스 연결 관리](#database-connection-management)를 참조하세요! -### Flight에서 메소드로 등록하기 -Flight PHP Framework를 사용하고 있다면, ActiveRecord 클래스를 서비스로 등록할 수 있지만, 꼭 해야 하는 건 아닙니다. +### Flight에서 메서드로 등록 +Flight PHP Framework를 사용 중이라면, ActiveRecord 클래스를 서비스로 등록할 수 있지만, 꼭 해야 하는 것은 아닙니다. ```php Flight::register('user', 'User', [ $pdo_connection ]); -// 그러면 컨트롤러, 함수 등에서 이렇게 사용할 수 있습니다. +// 그런 다음 컨트롤러, 함수 등에서 이렇게 사용할 수 있습니다. Flight::user()->find(1); ``` -## `runway` 메소드 +## `runway` 메서드 -[runway](/awesome-plugins/runway)는 이 라이브러리를 위한 사용자 정의 명령이 있는 Flight의 CLI 도구입니다. +[runway](/awesome-plugins/runway)는 Flight를 위한 CLI 도구로, 이 라이브러리에 대한 사용자 지정 명령어를 가지고 있습니다. ```bash # 사용법 php runway make:record database_table_name [class_name] -# 예시 +# 예제 php runway make:record users ``` -이렇게 하면 `app/records/` 디렉토리에 `UserRecord.php`라는 새로운 클래스가 다음과 같은 내용으로 생성됩니다: +이것은 `app/records/` 디렉토리에 `UserRecord.php`로 새 클래스를 생성하며, 다음과 같은 내용을 포함합니다: ```php notNull('password')->orderBy('id DESC')->find(); // 특정 id로 레코드 찾기 @@ -195,7 +195,7 @@ $user->find($id); #### `findAll(): array` -지정한 테이블에서 모든 레코드를 찾습니다. +지정된 테이블의 모든 레코드를 찾습니다. ```php $user->findAll(); @@ -203,7 +203,7 @@ $user->findAll(); #### `isHydrated(): boolean` (v0.4.0) -현재 레코드가 수분이 공급된 경우 `true`를 반환합니다 (데이터베이스에서 가져온 경우). +현재 레코드가 데이터베이스에서 로드(hydrated)되었는지 `true`를 반환합니다. ```php $user->find(1); @@ -224,7 +224,7 @@ $user->insert(); ##### 텍스트 기반 기본 키 -UUID와 같은 텍스트 기반 기본 키가 있는 경우, 삽입 전에 두 가지 방법 중 하나로 기본 키 값을 설정할 수 있습니다. +텍스트 기반 기본 키(예: UUID)가 있으면, 삽입 전에 기본 키 값을 두 가지 방법 중 하나로 설정할 수 있습니다. ```php $user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]); @@ -234,24 +234,24 @@ $user->password = md5('demo'); $user->insert(); // 또는 $user->save(); ``` -또는 이벤트를 통해 기본 키가 자동으로 생성되도록 할 수 있습니다. +또는 이벤트를 통해 기본 키를 자동으로 생성할 수 있습니다. ```php class User extends flight\ActiveRecord { public function __construct($database_connection) { parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]); - // 배열 대신 이렇게 기본 키를 설정할 수도 있습니다. + // 위 배열 대신 이렇게 기본 키를 설정할 수도 있습니다. $this->primaryKey = 'uuid'; } protected function beforeInsert(self $self) { - $self->uuid = uniqid(); // 또는 필요에 따라 고유 ID를 생성하는 방법 + $self->uuid = uniqid(); // 또는 고유 ID를 생성하는 방법에 따라 } } ``` -삽입 전에 기본 키를 설정하지 않으면 `rowid`로 설정되며 데이터베이스가 대신 생성하지만, 그 필드는 테이블에 존재하지 않을 수 있으므로 지속되지 않습니다. 따라서 이벤트를 사용하여 자동으로 처리하는 것이 권장됩니다. +삽입 전에 기본 키를 설정하지 않으면 `rowid`로 설정되고 데이터베이스가 생성하지만, 테이블에 해당 필드가 없으면 지속되지 않습니다. 따라서 이벤트를 사용해 자동으로 처리하는 것이 권장됩니다. #### `update(): boolean|ActiveRecord` @@ -265,7 +265,7 @@ $user->update(); #### `save(): boolean|ActiveRecord` -현재 레코드를 데이터베이스에 삽입하거나 업데이트합니다. 레코드에 id가 있으면 업데이트하고, 그렇지 않으면 삽입합니다. +현재 레코드를 데이터베이스에 삽입하거나 업데이트합니다. 레코드에 id가 있으면 업데이트하고, 없으면 삽입합니다. ```php $user = new User($pdo_connection); @@ -274,7 +274,7 @@ $user->password = md5('demo'); $user->save(); ``` -**참고:** 클래스에 관계가 정의되어 있다면, 정의되고 인스턴스화되며 업데이트할 더러워진 데이터가 있는 경우에도 해당 관계를 재귀적으로 저장합니다. (v0.4.0 이상) +**참고:** 클래스에 관계가 정의되어 있으면, 정의되고 인스턴스화된 관계 중 업데이트할 더티 데이터가 있는 경우 재귀적으로 저장합니다. (v0.4.0 이상) #### `delete(): boolean` @@ -285,7 +285,7 @@ $user->gt('id', 0)->orderBy('id desc')->find(); $user->delete(); ``` -사전 검색을 수행한 후 여러 레코드를 삭제할 수도 있습니다. +사전에 검색을 실행하여 여러 레코드를 삭제할 수도 있습니다. ```php $user->like('name', 'Bob%')->delete(); @@ -293,20 +293,20 @@ $user->like('name', 'Bob%')->delete(); #### `dirty(array $dirty = []): ActiveRecord` -더러운 데이터란 레코드에서 변경된 데이터를 의미합니다. +더티 데이터는 레코드에서 변경된 데이터를 가리킵니다. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); -// 이 시점에서 아무것도 "더럽지" 않습니다. +// 이 시점에서 아무것도 "더티"하지 않습니다. -$user->email = 'test@example.com'; // 이제 이메일은 변경되었으므로 "더럽다"라고 간주됩니다. +$user->email = 'test@example.com'; // 이제 이메일이 변경되어 "더티"로 간주됩니다. $user->update(); -// 이제 데이터베이스에 업데이트되고 지속되었기 때문에 더러운 데이터는 없습니다. +// 이제 업데이트되어 데이터베이스에 지속되었으므로 더티 데이터가 없습니다 -$user->password = password_hash('newpassword'); // 이제 이것은 더럽습니다. -$user->dirty(); // 아무것도 전달하지 않으면 모든 더러운 항목이 삭제됩니다. -$user->update(); // 캡처된 더러운 항목이 없으므로 아무것도 업데이트되지 않습니다. +$user->password = password_hash()'newpassword'); // 이제 이것이 더티입니다 +$user->dirty(); // 아무것도 전달하지 않으면 모든 더티 항목을 지웁니다. +$user->update(); // 아무것도 업데이트되지 않습니다. 더티로 캡처된 것이 없기 때문입니다. $user->dirty([ 'name' => 'something', 'password' => password_hash('a different password') ]); $user->update(); // 이름과 비밀번호가 모두 업데이트됩니다. @@ -314,7 +314,7 @@ $user->update(); // 이름과 비밀번호가 모두 업데이트됩니다. #### `copyFrom(array $data): ActiveRecord` (v0.4.0) -이는 `dirty()` 메소드의 별칭입니다. 더 명확하게 무엇을 하고 있는지 알 수 있습니다. +`dirty()` 메서드의 별칭입니다. 무엇을 하는지 더 명확합니다. ```php $user->copyFrom([ 'name' => 'something', 'password' => password_hash('a different password') ]); @@ -323,7 +323,7 @@ $user->update(); // 이름과 비밀번호가 모두 업데이트됩니다. #### `isDirty(): boolean` (v0.4.0) -현재 레코드가 변경된 경우 `true`를 반환합니다. +현재 레코드가 변경되었는지 `true`를 반환합니다. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); @@ -333,14 +333,15 @@ $user->isDirty(); // true #### `reset(bool $include_query_data = true): ActiveRecord` -현재 레코드를 초기 상태로 재설정합니다. 이는 반복 유형의 동작에 매우 유용합니다. `true`를 전달하면 현재 객체를 찾기 위해 사용된 쿼리 데이터도 재설정합니다 (기본 동작). +현재 레코드를 초기 상태로 재설정합니다. 루프 유형 동작에서 사용하기 좋습니다. +`true`를 전달하면 현재 객체를 찾는 데 사용된 쿼리 데이터도 재설정합니다 (기본 동작). ```php $users = $user->greaterThan('id', 0)->orderBy('id desc')->find(); $user_company = new UserCompany($pdo_connection); foreach($users as $user) { - $user_company->reset(); // 깨끗한 슬레이트로 시작합니다. + $user_company->reset(); // 깨끗한 상태로 시작 $user_company->user_id = $user->id; $user_company->company_id = $some_company_id; $user_company->insert(); @@ -349,12 +350,12 @@ foreach($users as $user) { #### `getBuiltSql(): string` (v0.4.1) -`find()`, `findAll()`, `insert()`, `update()`, 또는 `save()` 메소드를 실행한 후에 생성된 SQL을 가져와서 디버깅 목적으로 사용할 수 있습니다. +`find()`, `findAll()`, `insert()`, `update()`, 또는 `save()` 메서드를 실행한 후 생성된 SQL을 가져와 디버깅에 사용할 수 있습니다. -## SQL 쿼리 메소드 +## SQL 쿼리 메서드 #### `select(string $field1 [, string $field2 ... ])` -원하는 경우 테이블의 일부 열만 선택할 수 있습니다(많은 열이 있는 매우 넓은 테이블에서는 성능상 더 유리합니다). +테이블의 일부 컬럼만 선택할 수 있습니다 (많은 컬럼이 있는 넓은 테이블에서 더 성능이 좋습니다) ```php $user->select('id', 'name')->find(); @@ -362,7 +363,7 @@ $user->select('id', 'name')->find(); #### `from(string $table)` -기술적으로 다른 테이블도 선택할 수 있습니다! 왜 안 되죠?! +기술적으로 다른 테이블을 선택할 수도 있습니다! 왜 안 되나요?! ```php $user->select('id', 'name')->from('user')->find(); @@ -370,7 +371,7 @@ $user->select('id', 'name')->from('user')->find(); #### `join(string $table_name, string $join_condition)` -데이터베이스에서 다른 테이블에 조인할 수도 있습니다. +데이터베이스의 다른 테이블에 조인할 수도 있습니다. ```php $user->join('contacts', 'contacts.user_id = users.id')->find(); @@ -378,13 +379,13 @@ $user->join('contacts', 'contacts.user_id = users.id')->find(); #### `where(string $where_conditions)` -일부 사용자 정의 WHERE 인수를 설정할 수 있습니다(이 WHERE 문에서 매개변수를 설정할 수 없습니다). +사용자 지정 where 인수를 설정할 수 있습니다 (이 where 문에서 params를 설정할 수 없습니다) ```php $user->where('id=1 AND name="demo"')->find(); ``` -**보안 참고:** `$user->where("id = '{$id}' AND name = '{$name}'")->find();`와 같은 것을 하고 싶을 수 있지만, 절대 이렇게 하지 마세요! 이는 SQL 인젝션 공격에 취약합니다. 온라인에 많은 기사들이 있습니다. "sql injection attacks php"를 구글하세요. 이 라이브러리로 처리하는 올바른 방법은 이 `where()` 메소드 대신 `$user->eq('id', $id)->eq('name', $name)->find();`와 같이 하는 것입니다. 반드시 이렇게 해야 한다면, `PDO` 라이브러리는 `$pdo->quote($var)`로 이를 이스케이프합니다. `quote()`를 사용한 후에야 `where()` 문에서 사용할 수 있습니다. +**보안 주의** - `$user->where("id = '{$id}' AND name = '{$name}'")->find();`처럼 할 수 있지만, 절대 이렇게 하지 마세요!!! 이것은 SQL 인젝션 공격에 취약합니다. 온라인에 많은 기사가 있습니다. "sql injection attacks php"를 Google하면 이 주제에 대한 많은 기사를 찾을 수 있습니다. 이 라이브러리에서 이를 처리하는 올바른 방법은 `where()` 메서드 대신 `$user->eq('id', $id)->eq('name', $name)->find();`처럼 하는 것입니다. 반드시 이렇게 해야 한다면, `PDO` 라이브러리의 `$pdo->quote($var)`를 사용해 이스케이프하세요. `quote()`를 사용한 후에만 `where()` 문에서 사용할 수 있습니다. #### `group(string $group_by_statement)/groupBy(string $group_by_statement)` @@ -404,7 +405,7 @@ $user->orderBy('name DESC')->find(); #### `limit(string $limit)/limit(int $offset, int $limit)` -반환된 레코드 수를 제한합니다. 정수 두 개가 주어지면 SQL처럼 오프셋과 제한을 설정합니다. +반환되는 레코드 수를 제한합니다. 두 번째 int가 주어지면 SQL처럼 offset, limit이 됩니다. ```php $user->orderby('name DESC')->limit(0, 10)->findAll(); @@ -413,7 +414,7 @@ $user->orderby('name DESC')->limit(0, 10)->findAll(); ## WHERE 조건 #### `equal(string $field, mixed $value) / eq(string $field, mixed $value)` -`field = $value`인 경우 +Where `field = $value` ```php $user->eq('id', 1)->find(); @@ -421,7 +422,7 @@ $user->eq('id', 1)->find(); #### `notEqual(string $field, mixed $value) / ne(string $field, mixed $value)` -`field <> $value`인 경우 +Where `field <> $value` ```php $user->ne('id', 1)->find(); @@ -429,14 +430,14 @@ $user->ne('id', 1)->find(); #### `isNull(string $field)` -`field IS NULL`인 경우 +Where `field IS NULL` ```php $user->isNull('id')->find(); ``` #### `isNotNull(string $field) / notNull(string $field)` -`field IS NOT NULL`인 경우 +Where `field IS NOT NULL` ```php $user->isNotNull('id')->find(); @@ -444,7 +445,7 @@ $user->isNotNull('id')->find(); #### `greaterThan(string $field, mixed $value) / gt(string $field, mixed $value)` -`field > $value`인 경우 +Where `field > $value` ```php $user->gt('id', 1)->find(); @@ -452,21 +453,21 @@ $user->gt('id', 1)->find(); #### `lessThan(string $field, mixed $value) / lt(string $field, mixed $value)` -`field < $value`인 경우 +Where `field < $value` ```php $user->lt('id', 1)->find(); ``` #### `greaterThanOrEqual(string $field, mixed $value) / ge(string $field, mixed $value) / gte(string $field, mixed $value)` -`field >= $value`인 경우 +Where `field >= $value` ```php $user->ge('id', 1)->find(); ``` #### `lessThanOrEqual(string $field, mixed $value) / le(string $field, mixed $value) / lte(string $field, mixed $value)` -`field <= $value`인 경우 +Where `field <= $value` ```php $user->le('id', 1)->find(); @@ -474,7 +475,7 @@ $user->le('id', 1)->find(); #### `like(string $field, mixed $value) / notLike(string $field, mixed $value)` -`field LIKE $value` 또는 `field NOT LIKE $value`인 경우 +Where `field LIKE $value` 또는 `field NOT LIKE $value` ```php $user->like('name', 'de')->find(); @@ -482,7 +483,7 @@ $user->like('name', 'de')->find(); #### `in(string $field, array $values) / notIn(string $field, array $values)` -`field IN($value)` 또는 `field NOT IN($value)`인 경우 +Where `field IN($value)` 또는 `field NOT IN($value)` ```php $user->in('id', [1, 2])->find(); @@ -490,7 +491,7 @@ $user->in('id', [1, 2])->find(); #### `between(string $field, array $values)` -`field BETWEEN $value AND $value1`인 경우 +Where `field BETWEEN $value AND $value1` ```php $user->between('id', [1, 2])->find(); @@ -498,48 +499,48 @@ $user->between('id', [1, 2])->find(); ### OR 조건 -조건을 OR 문으로 감싸는 것이 가능합니다. 이는 `startWrap()` 및 `endWrap()` 메소드를 사용하거나 필드 및 값 뒤에 조건의 세 번째 매개변수를 채우는 방식으로 이루어집니다. +조건을 OR 문으로 감쌀 수 있습니다. `startWrap()`와 `endWrap()` 메서드를 사용하거나 필드와 값 다음에 조건의 3번째 매개변수를 채워서 합니다. ```php // 방법 1 $user->eq('id', 1)->startWrap()->eq('name', 'demo')->or()->eq('name', 'test')->endWrap('OR')->find(); -// 이는 `id = 1 AND (name = 'demo' OR name = 'test')`로 평가됩니다. +// 이는 `id = 1 AND (name = 'demo' OR name = 'test')`로 평가됩니다 // 방법 2 $user->eq('id', 1)->eq('name', 'demo', 'OR')->find(); -// 이는 `id = 1 OR name = 'demo'`로 평가됩니다. +// 이는 `id = 1 OR name = 'demo'`로 평가됩니다 ``` ## 관계 -이 라이브러리를 사용하여 여러 종류의 관계를 설정할 수 있습니다. 테이블 간에 일대다 및 일대일 관계를 설정할 수 있습니다. 이를 위해 클래스 내에서 조금 추가 설정이 필요합니다. +이 라이브러스를 사용해 여러 종류의 관계를 설정할 수 있습니다. 테이블 간 one->many 및 one->one 관계를 설정할 수 있습니다. 이는 클래스에서 약간의 추가 설정이 필요합니다. -`$relations` 배열을 설정하는 것은 어렵지 않지만 올바른 구문을 추측하기 어려울 수 있습니다. +`$relations` 배열 설정은 어렵지 않지만, 올바른 구문을 추측하는 것은 혼란스러울 수 있습니다. ```php protected array $relations = [ - // 키의 이름을 원하는 대로 지정할 수 있습니다. 액티브 레코드의 이름이 적합할 것입니다. 예: user, contact, client + // 키 이름을 원하는 대로 지정할 수 있습니다. ActiveRecord 이름이 좋습니다. 예: user, contact, client 'user' => [ // 필수 // self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO - self::HAS_ONE, // 이것이 관계의 유형입니다. + self::HAS_ONE, // 이는 관계 유형입니다 // 필수 - 'Some_Class', // 이 관계를 참조할 "다른" 액티브 레코드 클래스 + 'Some_Class', // 이는 참조할 "다른" ActiveRecord 클래스입니다 // 필수 - // 관계 유형에 따라 - // self::HAS_ONE = 조인을 참조하는 외래 키 - // self::HAS_MANY = 조인을 참조하는 외래 키 - // self::BELONGS_TO = 조인을 참조하는 로컬 키 + // 관계 유형에 따라 다름 + // self::HAS_ONE = 조인 참조 외래 키 + // self::HAS_MANY = 조인 참조 외래 키 + // self::BELONGS_TO = 조인 참조 로컬 키 'local_or_foreign_key', - // 참고: 이것은 "다른" 모델의 기본 키만 조인됩니다. + // 참고로, 이는 "다른" 모델의 기본 키에만 조인됩니다 - // 선택 사항 - [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // 관계를 조인할 때 원하는 추가 조건 + // 선택 + [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // 관계 조인 시 원하는 추가 조건 // $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5)) - // 선택 사항 - 'back_reference_name' // 자신으로 이 관계를 되돌아 참조하려면. 예: $user->contact->user; + // 선택 + 'back_reference_name' // 이 관계를 다시 자신으로 백 참조하려면 예: $user->contact->user; ]; ] ``` @@ -569,41 +570,142 @@ class Contact extends ActiveRecord{ } ``` -이제 참조가 설정되어 있으므로 이를 매우 쉽게 사용할 수 있습니다! +이제 참조가 설정되었으므로 매우 쉽게 사용할 수 있습니다! ```php $user = new User($pdo_connection); -// 가장 최근 사용자를 찾습니다. +// 가장 최근 사용자 찾기. $user->notNull('id')->orderBy('id desc')->find(); -// 관계를 사용하여 연락처 가져오기: +// 관계를 사용해 연락처 가져오기: foreach($user->contacts as $contact) { echo $contact->id; } -// 또는 다른 방향으로 갈 수 있습니다. +// 또는 반대로 할 수 있습니다. $contact = new Contact(); -// 연락처 하나 찾기 +// 하나의 연락처 찾기 $contact->find(); -// 관계를 사용하여 사용자 가져오기: -echo $contact->user->name; // 사용자의 이름입니다. +// 관계를 사용해 사용자 가져오기: +echo $contact->user->name; // 이는 사용자 이름입니다 ``` -멋지네요, 그렇죠? +꽤 멋지지 않나요? -## 사용자 정의 데이터 설정 -때때로 사용자 정의 계산과 같이 ActiveRecord에 고유한 것을 붙여야 할 필요가 있을 수 있습니다. 이는 템플릿에 전달할 객체에 첨부하는 것이 더 쉬울 수 있습니다. +### Eager Loading + +#### 개요 +Eager loading은 관계를 미리 로드하여 N+1 쿼리 문제를 해결합니다. 각 레코드의 관계에 대해 별도의 쿼리를 실행하는 대신, 관계당 하나의 추가 쿼리로 모든 관련 데이터를 가져옵니다. + +> **참고:** Eager loading은 v0.7.0 이상에서만 사용할 수 있습니다. + +#### 기본 사용법 +`with()` 메서드를 사용해 eager load할 관계를 지정하세요: +```php +// N+1 대신 2개의 쿼리로 사용자와 연락처 로드 +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + foreach ($u->contacts as $contact) { + echo $contact->email; // 추가 쿼리 없음! + } +} +``` + +#### 다중 관계 +한 번에 여러 관계 로드: +```php +$users = $user->with(['contacts', 'profile', 'settings'])->findAll(); +``` + +#### 관계 유형 + +##### HAS_MANY +```php +// 각 사용자에 대한 모든 연락처 eager load +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + // $u->contacts는 이미 배열로 로드됨 + foreach ($u->contacts as $contact) { + echo $contact->email; + } +} +``` +##### HAS_ONE +```php +// 각 사용자에 대한 하나의 연락처 eager load +$users = $user->with('contact')->findAll(); +foreach ($users as $u) { + // $u->contact는 이미 객체로 로드됨 + echo $u->contact->email; +} +``` + +##### BELONGS_TO +```php +// 모든 연락처에 대한 부모 사용자 eager load +$contacts = $contact->with('user')->findAll(); +foreach ($contacts as $c) { + // $c->user는 이미 로드됨 + echo $c->user->name; +} +``` +##### find()와 함께 +Eager loading은 +findAll() + 및 +find() +와 모두 작동합니다: + +```php +$user = $user->with('contacts')->find(1); +// 사용자와 모든 연락처가 2개의 쿼리로 로드됨 +``` +#### 성능 이점 +Eager loading 없이 (N+1 문제): +```php +$users = $user->findAll(); // 1 쿼리 +foreach ($users as $u) { + $contacts = $u->contacts; // N 쿼리 (사용자당 하나!) +} +// 총: 1 + N 쿼리 +``` + +Eager loading과 함께: + +```php +$users = $user->with('contacts')->findAll(); // 총 2 쿼리 +foreach ($users as $u) { + $contacts = $u->contacts; // 추가 쿼리 0! +} +// 총: 2 쿼리 (사용자 1 + 모든 연락처 1) +``` +10명의 사용자에 대해 쿼리를 11개에서 2개로 줄여 82% 감소! + +#### 중요한 주의사항 +- Eager loading은 완전히 선택적입니다 - lazy loading은 이전처럼 작동합니다 +- 이미 로드된 관계는 자동으로 건너뜁니다 +- 백 참조는 eager loading과 작동합니다 +- 관계 콜백은 eager loading 중 존중됩니다 + +#### 제한사항 +- 중첩 eager loading (예: +with(['contacts.addresses']) +)은 현재 지원되지 않습니다 +- 클로저를 통한 eager load 제약은 이 버전에서 지원되지 않습니다 + +## 사용자 지정 데이터 설정 +때때로 ActiveRecord에 고유한 것을 첨부해야 할 수 있습니다. 예를 들어 템플릿에 전달될 객체에 간단히 첨부할 수 있는 사용자 지정 계산입니다. #### `setCustomData(string $field, mixed $value)` -`setCustomData()` 메소드를 사용하여 사용자 정의 데이터를 첨부합니다. +`setCustomData()` 메서드로 사용자 지정 데이터를 첨부하세요. ```php $user->setCustomData('page_view_count', $page_view_count); ``` -그런 다음 일반 객체 속성처럼 참조할 수 있습니다. +그런 다음 일반 객체 속성처럼 참조하세요. ```php echo $user->page_view_count; @@ -611,11 +713,11 @@ echo $user->page_view_count; ## 이벤트 -이 라이브러리의 또 다른 슈퍼 멋진 기능은 이벤트에 대한 것입니다. 이벤트는 여러분이 호출하는 특정 메소드에 따라 특정 시간에 발생합니다. 이들은 데이터를 자동으로 설정하는 데 매우 유용합니다. +이 라이브러리의 또 다른 멋진 기능은 이벤트에 관한 것입니다. 이벤트는 호출하는 특정 메서드에 기반해 특정 시점에 트리거됩니다. 데이터를 자동으로 설정하는 데 매우 유용합니다. #### `onConstruct(ActiveRecord $ActiveRecord, array &config)` -기본 연결을 설정해야 할 경우 정말 유용합니다. +기본 연결을 설정해야 할 때 매우 유용합니다. ```php // index.php 또는 bootstrap.php @@ -629,12 +731,12 @@ Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); class User extends flight\ActiveRecord { protected function onConstruct(self $self, array &$config) { // & 참조를 잊지 마세요 - // 이렇게 연결을 자동으로 설정할 수 있습니다. + // 연결을 자동으로 설정하려면 이렇게 할 수 있습니다 $config['connection'] = Flight::db(); // 또는 이렇게 $self->transformAndPersistConnection(Flight::db()); - // 이렇게 테이블 이름을 설정할 수도 있습니다. + // 테이블 이름도 이렇게 설정할 수 있습니다. $config['table'] = 'users'; } } @@ -642,7 +744,7 @@ class User extends flight\ActiveRecord { #### `beforeFind(ActiveRecord $ActiveRecord)` -이는 쿼리 조작이 필요한 경우에만 유용합니다. +각 쿼리 조작이 필요할 때만 유용할 것입니다. ```php class User extends flight\ActiveRecord { @@ -653,7 +755,7 @@ class User extends flight\ActiveRecord { } protected function beforeFind(self $self) { - // 항상 id >= 0으로 실행합니다. + // id >= 0을 항상 실행하려면 $self->gte('id', 0); } } @@ -661,7 +763,7 @@ class User extends flight\ActiveRecord { #### `afterFind(ActiveRecord $ActiveRecord)` -이것은 매번 이 레코드가 가져올 때마다 무언가 논리를 실행해야 할 때 더 유용합니다. 무언가를 복호화해야 하나요? 매번 사용자 지정 카운트 쿼리를 실행해야 하나요? (성능상 비효율적이지만 그건 그렇고)? +이 레코드가 가져올 때마다 항상 로직을 실행해야 할 때 더 유용할 것입니다. 무언가를 복호화해야 하나요? 매번 사용자 지정 카운트 쿼리를 실행해야 하나요 (성능이 좋지 않지만 어쨌든)? ```php class User extends flight\ActiveRecord { @@ -672,10 +774,10 @@ class User extends flight\ActiveRecord { } protected function afterFind(self $self) { - // 무언가를 복호화합니다. + // 무언가 복호화 $self->secret = yourDecryptFunction($self->secret, $some_key); - // 아마도 쿼리와 같이 무언가를 저장합니다??? + // 쿼리처럼 사용자 지정 무언가를 저장? $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']; } } @@ -683,7 +785,7 @@ class User extends flight\ActiveRecord { #### `beforeFindAll(ActiveRecord $ActiveRecord)` -이것은 매번 쿼리 조작이 필요한 경우에만 유용합니다. +각 쿼리 조작이 필요할 때만 유용할 것입니다. ```php class User extends flight\ActiveRecord { @@ -694,7 +796,7 @@ class User extends flight\ActiveRecord { } protected function beforeFindAll(self $self) { - // 항상 id >= 0으로 실행합니다. + // id >= 0을 항상 실행하려면 $self->gte('id', 0); } } @@ -702,7 +804,7 @@ class User extends flight\ActiveRecord { #### `afterFindAll(array $results)` -`afterFind()`와 유사하지만 모든 레코드에 대해 수행할 수 있습니다! +`afterFind()`와 유사하지만 모든 레코드에 적용할 수 있습니다! ```php class User extends flight\ActiveRecord { @@ -715,7 +817,7 @@ class User extends flight\ActiveRecord { protected function afterFindAll(array $results) { foreach($results as $self) { - // afterFind()처럼 무언가 멋진 일을 합니다. + // afterFind()처럼 멋진 일을 하세요 } } } @@ -723,7 +825,7 @@ class User extends flight\ActiveRecord { #### `beforeInsert(ActiveRecord $ActiveRecord)` -매번 일부 기본 값을 설정해야 할 필요가 있을 때 정말 유용합니다. +매번 기본 값을 설정해야 할 때 매우 유용합니다. ```php class User extends flight\ActiveRecord { @@ -734,7 +836,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // 일부 유용한 기본 값을 설정합니다. + // 합리적인 기본값 설정 if(!$self->created_date) { $self->created_date = gmdate('Y-m-d'); } @@ -748,7 +850,7 @@ class User extends flight\ActiveRecord { #### `afterInsert(ActiveRecord $ActiveRecord)` -레코드가 삽입된 후 데이터를 변경해야 할 경우가 있을 수 있습니다. +삽입 후 데이터를 변경해야 하는 사용 사례가 있나요? ```php class User extends flight\ActiveRecord { @@ -759,16 +861,16 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // 당신이 할 일을 하세요. + // 당신의 방식대로 하세요 Flight::cache()->set('most_recent_insert_id', $self->id); - // 또는 뭐든지... + // 또는 무엇이든.... } } ``` #### `beforeUpdate(ActiveRecord $ActiveRecord)` -매번 업데이트 시 일부 기본 값을 설정해야 할 필요가 있을 때 정말 유용합니다. +업데이트 시 매번 기본 값을 설정해야 할 때 매우 유용합니다. ```php class User extends flight\ActiveRecord { @@ -779,7 +881,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // 유용한 기본 값을 설정합니다. + // 합리적인 기본값 설정 if(!$self->updated_date) { $self->updated_date = gmdate('Y-m-d'); } @@ -789,7 +891,7 @@ class User extends flight\ActiveRecord { #### `afterUpdate(ActiveRecord $ActiveRecord)` -업데이트 후 데이터를 변경해야 할 경우가 있을 수 있습니다. +업데이트 후 데이터를 변경해야 하는 사용 사례가 있나요? ```php class User extends flight\ActiveRecord { @@ -800,16 +902,16 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // 당신이 할 일을 하세요. + // 당신의 방식대로 하세요 Flight::cache()->set('most_recently_updated_user_id', $self->id); - // 또는 뭐든지... + // 또는 무엇이든.... } } ``` #### `beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)` -이것은 삽입 또는 업데이트가 발생할 때 이벤트를 발생시켜야 할 경우 유용합니다. 설명을 생략하겠습니다. 하지만 충분히 추측하실 수 있을 것입니다. +삽입 또는 업데이트 시 이벤트가 발생하기를 원할 때 유용합니다. 긴 설명은 생략하겠지만, 무엇인지 추측할 수 있을 것입니다. ```php class User extends flight\ActiveRecord { @@ -827,7 +929,7 @@ class User extends flight\ActiveRecord { #### `beforeDelete(ActiveRecord $ActiveRecord)/afterDelete(ActiveRecord $ActiveRecord)` -여기서 무엇을 하시고 싶을지 모르겠지만, 여기서 아무 판단도 하지 않을 것입니다! 마음껏 하세요! +여기서 무엇을 하고 싶은지 모르겠지만, 판단하지 않습니다! 해보세요! ```php class User extends flight\ActiveRecord { @@ -838,17 +940,17 @@ class User extends flight\ActiveRecord { } protected function beforeDelete(self $self) { - echo '그는 용감한 전사였습니다... :cry-face:'; + echo 'He was a brave soldier... :cry-face:'; } } ``` ## 데이터베이스 연결 관리 -이 라이브러리를 사용할 때 데이터베이스 연결을 몇 가지 방법으로 설정할 수 있습니다. 생성자에서 연결을 설정하거나 구성 변수 `$config['connection']`를 통해 설정하거나 `setDatabaseConnection()`(v0.4.1)을 통해 설정할 수 있습니다. +이 라이브러리를 사용할 때 데이터베이스 연결을 여러 방식으로 설정할 수 있습니다. 생성자에서 연결을 설정하거나, `$config['connection']` 설정 변수로 설정하거나 `setDatabaseConnection()` (v0.4.1)을 사용할 수 있습니다. ```php -$pdo_connection = new PDO('sqlite:test.db'); // 예시를 위해 +$pdo_connection = new PDO('sqlite:test.db'); // 예제용 $user = new User($pdo_connection); // 또는 $user = new User(null, [ 'connection' => $pdo_connection ]); @@ -857,11 +959,11 @@ $user = new User(); $user->setDatabaseConnection($pdo_connection); ``` -매번 액티브 레코드를 호출할 때마다 `$database_connection`을 설정하는 것을 피하고 싶다면 방안이 있습니다! +액티브 레코드를 호출할 때마다 항상 `$database_connection`을 설정하지 않으려면, 이를 피할 방법이 있습니다! ```php // index.php 또는 bootstrap.php -// Flight에서 이 클래스를 등록합니다. +// Flight에서 등록된 클래스로 설정 Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php @@ -874,24 +976,24 @@ class User extends flight\ActiveRecord { } } -// 이제, 인자가 필요 없습니다! +// 이제 인수 불필요! $user = new User(); ``` -> **참고:** 단위 테스트를 계획하고 있다면, 이렇게 하면 단위 테스트에 일부 도전과제가 발생할 수 있지만, 전체적으로 `setDatabaseConnection()` 또는 `$config['connection']`로 연결을 주입할 수 있기 때문에 큰 문제는 아닙니다. +> **참고:** 단위 테스트를 계획 중이라면, 이 방식은 단위 테스트에 약간의 도전을 추가할 수 있지만, `setDatabaseConnection()` 또는 `$config['connection']`으로 연결을 주입할 수 있으므로 전체적으로 나쁘지 않습니다. -장시간 CLI 스크립트를 실행하면서 연결을 새로 고쳐야 하는 경우, `$your_record->setDatabaseConnection($pdo_connection)`로 연결을 다시 설정할 수 있습니다. +데이터베이스 연결을 새로 고쳐야 할 때, 예를 들어 장기 실행 CLI 스크립트를 실행 중이고 연결을 주기적으로 새로 고쳐야 한다면, `$your_record->setDatabaseConnection($pdo_connection)`으로 재설정할 수 있습니다. ## 기여 -부탁드립니다. :D +참여해 주세요. :D ### 설정 -기여할 때는 `composer test-coverage`를 실행하여 100% 테스트 커버리지를 유지하세요 (이것은 진정한 단위 테스트 커버리지가 아니라, 더 통합 테스트에 가깝습니다). +기여할 때 `composer test-coverage`를 실행해 100% 테스트 커버리지를 유지하세요 (이것은 진짜 단위 테스트 커버리지가 아니라 통합 테스트에 가깝습니다). -또한 `composer beautify` 및 `composer phpcs`를 실행하여 어떤 린트 오류를 수정하세요. +또한 `composer beautify`와 `composer phpcs`를 실행해 린팅 오류를 수정하세요. -## 라이센스 +## 라이선스 MIT \ No newline at end of file diff --git a/content/v3/ko/awesome-plugins/apm.md b/content/v3/ko/awesome-plugins/apm.md index ca3fbf3b..5f18c557 100644 --- a/content/v3/ko/awesome-plugins/apm.md +++ b/content/v3/ko/awesome-plugins/apm.md @@ -1,14 +1,14 @@ # FlightPHP APM 문서 -FlightPHP APM에 오신 것을 환영합니다—앱의 개인 성능 코치입니다! 이 가이드는 FlightPHP와 함께 Application Performance Monitoring (APM)을 설정하고, 사용하며, 마스터하는 로드맵입니다. 느린 요청을 추적하든 지연 차트에 열중하든, 우리는 모든 것을 다루고 있습니다. 앱을 더 빠르게 만들고, 사용자를 더 행복하게 하며, 디버깅 세션을 쉽게 만들어 보겠습니다! +FlightPHP APM에 오신 것을 환영합니다—앱의 개인 성능 코치입니다! 이 가이드는 FlightPHP와 함께 Application Performance Monitoring (APM)을 설정, 사용, 마스터하는 로드맵입니다. 느린 요청을 추적하든 지연 차트에 몰두하든, 모든 것을 다루겠습니다. 앱을 더 빠르게, 사용자를 더 행복하게, 디버깅 세션을 쉽게 만들어 보겠습니다! -Flight Docs 사이트의 대시보드 [데모](https://flightphp-docs-apm.sky-9.com/apm/dashboard)를 확인하세요. +Flight Docs 사이트의 대시보드 데모를 [여기](https://flightphp-docs-apm.sky-9.com/apm/dashboard)에서 확인하세요. ![FlightPHP APM](/images/apm.png) ## APM이 중요한 이유 -이 장면을 상상해 보세요: 앱이 바쁜 레스토랑입니다. 주문이 얼마나 걸리는지나 주방이 어디서 느려지는지 추적할 방법이 없으면, 고객이 왜 불만족스럽게 떠나는지 추측할 수밖에 없습니다. APM은 당신의 수석 셰프입니다—들어오는 요청부터 데이터베이스 쿼리까지 모든 단계를 감시하고, 느려지는 부분을 표시합니다. 느린 페이지는 사용자를 잃습니다 (연구에 따르면 사이트 로딩이 3초를 초과하면 53%가 이탈합니다!), 그리고 APM은 이러한 문제를 *미리* 포착하여 아프기 전에 도와줍니다. 이는 사전적 안심입니다—더 적은 “이게 왜 고장 났어?” 순간, 더 많은 “이게 얼마나 부드럽게 돌아가!” 승리. +이 장면을 상상해 보세요: 앱이 바쁜 레스토랑입니다. 주문 처리 시간이 얼마나 걸리는지나 주방이 어디서 지연되는지 추적할 방법이 없으면, 고객이 왜 불만족스럽게 떠나는지 추측할 수밖에 없습니다. APM은 부주방장 역할을 합니다—들어오는 요청부터 데이터베이스 쿼리까지 모든 단계를 감시하고, 속도를 늦추는 것을 플래그합니다. 느린 페이지는 사용자를 잃게 만듭니다 (연구에 따르면 사이트 로딩이 3초 이상 걸리면 53%가 이탈합니다!), APM은 이러한 문제를 *미리* 잡아줍니다. 사전적 안심—더 적은 "이게 왜 고장 났지?" 순간, 더 많은 "이게 얼마나 부드럽게 작동하나 봐!" 승리입니다. ## 설치 @@ -26,10 +26,10 @@ composer require flightphp/apm FlightPHP APM은 현재 메트릭을 저장하기 위해 다음 데이터베이스를 지원합니다: -- **SQLite3**: 간단하고 파일 기반이며, 로컬 개발이나 작은 앱에 훌륭합니다. 대부분의 설정에서 기본 옵션입니다. -- **MySQL/MariaDB**: 더 큰 프로젝트나 프로덕션 환경에서 강력하고 확장 가능한 저장소가 필요한 경우 이상적입니다. +- **SQLite3**: 간단하고 파일 기반으로, 로컬 개발이나 작은 앱에 적합합니다. 대부분의 설정에서 기본 옵션입니다. +- **MySQL/MariaDB**: 더 큰 프로젝트나 프로덕션 환경에 이상적이며, 강력하고 확장 가능한 저장소를 필요로 합니다. -구성 단계(아래 참조)에서 데이터베이스 유형을 선택할 수 있습니다. PHP 환경에 필요한 확장(예: `pdo_sqlite` 또는 `pdo_mysql`)이 설치되어 있는지 확인하세요. +구성 단계(아래 참조)에서 데이터베이스 유형을 선택할 수 있습니다. PHP 환경에 필요한 확장(pdo_sqlite 또는 pdo_mysql 등)이 설치되어 있는지 확인하세요. ## 시작하기 @@ -41,6 +41,7 @@ APM의 멋진 단계별 가이드입니다: ```php use flight\apm\logger\LoggerFactory; +use flight\database\PdoWrapper; use flight\Apm; $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); @@ -54,18 +55,18 @@ $Apm->addPdoConnection($pdo); ``` **여기서 무슨 일이 일어나나요?** -- `LoggerFactory::create()`는 구성(곧 더 자세히)을 가져와 로거를 설정합니다—기본적으로 SQLite입니다. +- `LoggerFactory::create()`는 구성(곧 자세히 설명)을 가져와 로거를 설정합니다—기본적으로 SQLite입니다. - `Apm`은 스타입니다—Flight의 이벤트(요청, 라우트, 오류 등)를 듣고 메트릭을 수집합니다. -- `bindEventsToFlightInstance($app)`은 이를 Flight 앱에 연결합니다. +- `bindEventsToFlightInstance($app)`은 모든 것을 Flight 앱에 연결합니다. **프로 팁: 샘플링** -앱이 바쁘면 *모든* 요청을 로깅하면 과부하가 될 수 있습니다. 샘플 레이트(0.0에서 1.0)를 사용하세요: +앱이 바쁘면 *모든* 요청을 로깅하면 과부하가 올 수 있습니다. 샘플 레이트(0.0에서 1.0)를 사용하세요: ```php -$Apm = new Apm($ApmLogger, 0.1); // 10% 요청 로깅 +$Apm = new Apm($ApmLogger, 0.1); // 요청의 10%를 로깅합니다 ``` -이렇게 하면 성능을 유지하면서도 견고한 데이터를 제공합니다. +이렇게 하면 성능을 유지하면서도 견고한 데이터를 얻을 수 있습니다. ### 2. 구성 @@ -75,8 +76,8 @@ $Apm = new Apm($ApmLogger, 0.1); // 10% 요청 로깅 php vendor/bin/runway apm:init ``` -**이게 무슨 일이에요?** -- 원시 메트릭의 출처(소스)와 처리된 데이터의 목적지(대상)에 대한 마법사를 실행합니다. +**이게 뭘 하나요?** +- 원시 메트릭의 출처(소스)와 처리된 데이터의 목적지(대상)를 묻는 마법사를 시작합니다. - 기본은 SQLite—예: 소스에 `sqlite:/tmp/apm_metrics.sqlite`, 대상에 다른 하나. - 다음과 같은 구성으로 끝납니다: ```json @@ -90,10 +91,10 @@ php vendor/bin/runway apm:init } ``` -> 이 과정에서 이 설정에 대한 마이그레이션을 실행할지 묻습니다. 처음 설정하는 경우 답은 yes입니다. +> 이 과정에서 이 설정에 대한 마이그레이션을 실행할지 물어봅니다. 처음 설정하는 경우 답은 yes입니다. **왜 두 위치인가요?** -원시 메트릭은 빠르게 쌓입니다(필터링되지 않은 로그 생각). 워커가 이를 구조화된 대상으로 처리하여 대시보드를 유지합니다. 깔끔하게 유지합니다! +원시 메트릭은 빠르게 쌓입니다(필터링되지 않은 로그를 생각하세요). 워커가 이를 구조화된 대상으로 처리하여 대시보드를 위한 것입니다. 깔끔하게 유지합니다! ### 3. 워커로 메트릭 처리 @@ -103,13 +104,13 @@ php vendor/bin/runway apm:init php vendor/bin/runway apm:worker ``` -**무슨 일을 하나요?** +**무엇을 하나요?** - 소스(예: `apm_metrics.sqlite`)에서 읽습니다. -- 최대 100 메트릭(기본 배치 크기)을 대상으로 처리합니다. -- 완료되거나 메트릭이 없으면 중지합니다. +- 최대 100개 메트릭(기본 배치 크기)을 대상으로 처리합니다. +- 완료되거나 메트릭이 없을 때 중지합니다. -**실행 유지** -라이브 앱의 경우 지속적인 처리가 필요합니다. 옵션은 다음과 같습니다: +**지속 실행** +라이브 앱의 경우 지속적인 처리를 원할 것입니다. 옵션은 다음과 같습니다: - **데몬 모드**: ```bash @@ -118,7 +119,7 @@ php vendor/bin/runway apm:worker 영원히 실행되며, 메트릭이 오면 처리합니다. 개발이나 작은 설정에 좋습니다. - **Crontab**: - crontab(`crontab -e`)에 추가하세요: + 크론탭(`crontab -e`)에 추가하세요: ```bash * * * * * php /path/to/project/vendor/bin/runway apm:worker ``` @@ -131,29 +132,29 @@ php vendor/bin/runway apm:worker php vendor/bin/runway apm:worker --daemon # Ctrl+B, 그 다음 D로 분리; `tmux attach -t apm-worker`로 재연결 ``` - 로그아웃해도 실행을 유지합니다. + 로그아웃해도 실행됩니다. - **커스텀 조정**: ```bash php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 ``` - - `--batch_size 50`: 한 번에 50 메트릭 처리. - - `--max_messages 1000`: 1000 메트릭 후 중지. + - `--batch_size 50`: 한 번에 50개 메트릭 처리. + - `--max_messages 1000`: 1000개 메트릭 후 중지. - `--timeout 300`: 5분 후 종료. -**왜 신경 써야 하나요?** +**왜 신경 쓰나요?** 워커 없이 대시보드는 비어 있습니다. 원시 로그와 실행 가능한 인사이트 사이의 다리입니다. ### 4. 대시보드 실행 -앱의 활력을 확인하세요: +앱의 생체 신호를 확인하세요: ```bash php vendor/bin/runway apm:dashboard ``` -**이게 뭐예요?** -- `http://localhost:8001/apm/dashboard`에서 PHP 서버를 실행합니다. +**이게 뭔가요?** +- `http://localhost:8001/apm/dashboard`에서 PHP 서버를 시작합니다. - 요청 로그, 느린 라우트, 오류 비율 등을 보여줍니다. **커스터마이징**: @@ -162,43 +163,43 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l ``` - `--host 0.0.0.0`: 모든 IP에서 접근 가능(원격 보기 편함). - `--port 8080`: 8001이 사용 중이면 다른 포트 사용. -- `--php-path`: PATH에 없으면 PHP를 가리킵니다. +- `--php-path`: PATH에 없으면 PHP를 가리키세요. 브라우저에서 URL을 열고 탐색하세요! #### 프로덕션 모드 -프로덕션에서 대시보드를 실행하려면 방화벽과 기타 보안 조치가 있으므로 몇 가지 기술을 시도해야 할 수 있습니다. 몇 가지 옵션: +프로덕션에서 대시보드를 실행하려면 방화벽과 기타 보안 조치로 인해 몇 가지 기술을 시도해야 할 수 있습니다. 몇 가지 옵션: -- **리버스 프록시 사용**: Nginx 또는 Apache를 설정하여 대시보드로 요청을 전달합니다. -- **SSH 터널**: 서버에 SSH로 접근할 수 있으면 `ssh -L 8080:localhost:8001 youruser@yourserver`를 사용하여 대시보드를 로컬 머신으로 터널링합니다. -- **VPN**: 서버가 VPN 뒤에 있으면 연결하고 대시보드를 직접 접근합니다. -- **방화벽 구성**: IP나 서버 네트워크에 대해 포트 8001을 열습니다. (또는 설정한 포트). -- **Apache/Nginx 구성**: 애플리케이션 앞에 웹 서버가 있으면 도메인이나 서브도메인으로 구성할 수 있습니다. 이렇게 하면 문서 루트를 `/path/to/your/project/vendor/flightphp/apm/dashboard`로 설정합니다. +- **리버스 프록시 사용**: Nginx나 Apache를 설정하여 요청을 대시보드로 전달. +- **SSH 터널**: 서버에 SSH로 접속할 수 있으면 `ssh -L 8080:localhost:8001 youruser@yourserver`를 사용하여 대시보드를 로컬 머신으로 터널링. +- **VPN**: 서버가 VPN 뒤에 있으면 연결 후 직접 접근. +- **방화벽 구성**: 8001 포트를 IP나 서버 네트워크에 열기(또는 설정한 포트). +- **Apache/Nginx 구성**: 애플리케이션 앞에 웹 서버가 있으면 도메인이나 서브도메인으로 구성. 이 경우 문서 루트를 `/path/to/your/project/vendor/flightphp/apm/dashboard`로 설정. #### 다른 대시보드를 원하나요? -원하면 자신의 대시보드를 만들 수 있습니다! vendor/flightphp/apm/src/apm/presenter 디렉토리를 보고 자신의 대시보드에 데이터를 제시하는 아이디어를 얻으세요! +원하는 대시보드를 직접 만들 수 있습니다! 데이터를 제시하는 방법에 대한 아이디어를 위해 vendor/flightphp/apm/src/apm/presenter 디렉토리를 확인하세요! ## 대시보드 기능 대시보드는 APM 본부입니다—여기서 볼 수 있는 것: -- **요청 로그**: 타임스탬프, URL, 응답 코드, 총 시간과 함께 모든 요청. “상세”를 클릭하여 미들웨어, 쿼리, 오류 확인. -- **가장 느린 요청**: 시간 소모 상위 5개 요청(예: “/api/heavy” 2.5s). +- **요청 로그**: 타임스탬프, URL, 응답 코드, 총 시간과 함께 모든 요청. "Details"를 클릭하여 미들웨어, 쿼리, 오류 확인. +- **가장 느린 요청**: 시간 많이 소모하는 상위 5개 요청(예: "/api/heavy" 2.5s). - **가장 느린 라우트**: 평균 시간 기준 상위 5개 라우트—패턴 발견에 좋음. - **오류 비율**: 실패한 요청 비율(예: 2.3% 500s). -- **지연 백분위**: 95번째(p95)와 99번째(p99) 응답 시간—최악 시나리오를 알기. +- **지연 백분위**: 95번째(p95)와 99번째(p99) 응답 시간—최악 시나리오 알기. - **응답 코드 차트**: 시간에 따른 200s, 404s, 500s 시각화. - **긴 쿼리/미들웨어**: 느린 데이터베이스 호출과 미들웨어 레이어 상위 5개. -- **캐시 히트/미스**: 캐시가 얼마나 자주 구하는지. +- **캐시 히트/미스**: 캐시가 얼마나 자주 도움이 되는지. -**추가 기능**: -- “지난 시간,” “지난 날,” 또는 “지난 주”로 필터링. +**추가**: +- "Last Hour," "Last Day," 또는 "Last Week"로 필터. - 늦은 밤 세션에 다크 모드 토글. **예시**: -`/users` 요청은 다음과 같이 표시될 수 있습니다: +`/users` 요청은 다음과 같이 보일 수 있음: - 총 시간: 150ms - 미들웨어: `AuthMiddleware->handle` (50ms) - 쿼리: `SELECT * FROM users` (80ms) @@ -206,7 +207,7 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l ## 커스텀 이벤트 추가 -API 호출이나 결제 프로세스처럼 아무거나 추적하세요: +API 호출이나 결제 프로세스처럼 아무거나 추적: ```php use flight\apm\CustomEvent; @@ -218,8 +219,8 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ])); ``` -**어디에 표시되나요?** -대시보드의 요청 상세에서 “커스텀 이벤트” 아래—예쁜 JSON 형식으로 확장 가능. +**어디에 나타나나요?** +대시보드의 요청 세부 정보에서 "Custom Events" 아래—예쁜 JSON 형식으로 확장 가능. **사용 사례**: ```php @@ -231,11 +232,11 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -이제 그 API가 앱을 끌어내리는지 확인할 수 있습니다! +이제 그 API가 앱을 끌어내리는지 볼 수 있습니다! ## 데이터베이스 모니터링 -PDO 쿼리를 이렇게 추적하세요: +PDO 쿼리를 이렇게 추적: ```php use flight\database\PdoWrapper; @@ -251,8 +252,8 @@ $Apm->addPdoConnection($pdo); **주의**: - **선택적**: DB 추적이 필요 없으면 건너뛰기. -- **PdoWrapper만**: 코어 PDO는 아직 연결되지 않음—기대하세요! -- **성능 경고**: DB 중심 사이트에서 모든 쿼리를 로깅하면 느려질 수 있습니다. 샘플링(`$Apm = new Apm($ApmLogger, 0.1)`)으로 부하를 줄이세요. +- **PdoWrapper만**: 코어 PDO는 아직 연결되지 않음—기다려 주세요! +- **성능 경고**: DB 중심 사이트에서 모든 쿼리를 로깅하면 느려질 수 있음. 부하를 줄이기 위해 샘플링(`$Apm = new Apm($ApmLogger, 0.1)`) 사용. **예시 출력**: - 쿼리: `SELECT name FROM products WHERE price > 100` @@ -261,22 +262,22 @@ $Apm->addPdoConnection($pdo); ## 워커 옵션 -취향에 맞게 워커를 조정하세요: +워커를 원하는 대로 조정: - `--timeout 300`: 5분 후 중지—테스트에 좋음. -- `--max_messages 500`: 500 메트릭으로 제한—유한하게 유지. -- `--batch_size 200`: 한 번에 200 처리—속도와 메모리 균형. +- `--max_messages 500`: 500개 메트릭으로 제한—유한하게 유지. +- `--batch_size 200`: 한 번에 200개 처리—속도와 메모리 균형. - `--daemon`: 중단 없이 실행—라이브 모니터링에 이상적. **예시**: ```bash php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ``` -한 시간 동안 실행되며, 한 번에 100 메트릭 처리. +한 시간 동안 실행되며, 한 번에 100개 메트릭 처리. ## 앱의 요청 ID -각 요청은 추적을 위한 고유 요청 ID를 가집니다. 앱에서 이 ID를 사용하여 로그와 메트릭을 상관관계지을 수 있습니다. 예를 들어 오류 페이지에 요청 ID를 추가할 수 있습니다: +각 요청은 추적을 위한 고유 요청 ID를 가집니다. 앱에서 이 ID를 사용하여 로그와 메트릭을 상관관계지을 수 있습니다. 예를 들어 오류 페이지에 요청 ID를 추가: ```php Flight::map('error', function($message) { @@ -284,7 +285,7 @@ Flight::map('error', function($message) { $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); // 추가로 Flight 변수에서 가져올 수 있음 - // swoole나 다른 비동기 플랫폼에서는 이 방법이 잘 작동하지 않습니다. + // swoole나 다른 비동기 플랫폼에서는 이 방법이 잘 작동하지 않음. // $requestId = Flight::get('apm.request_id'); echo "Error: $message (Request ID: $requestId)"; @@ -293,24 +294,34 @@ Flight::map('error', function($message) { ## 업그레이드 -APM의 최신 버전으로 업그레이드할 때 데이터베이스 마이그레이션을 실행해야 할 수 있습니다. 다음 명령으로 이를 할 수 있습니다: +APM의 최신 버전으로 업그레이드할 때 데이터베이스 마이그레이션이 필요할 수 있습니다. 다음 명령으로 실행: ```bash php vendor/bin/runway apm:migrate ``` -이것은 데이터베이스 스키마를 최신 버전으로 업데이트하는 데 필요한 모든 마이그레이션을 실행합니다. +이것은 데이터베이스 스키마를 최신 버전으로 업데이트하기 위해 필요한 모든 마이그레이션을 실행합니다. + +**참고:** APM 데이터베이스가 크면 이 마이그레이션은 시간이 걸릴 수 있습니다. 피크 시간 외에 실행하는 것이 좋습니다. + +### 0.4.3 -> 0.5.0 업그레이드 + +0.4.3에서 0.5.0으로 업그레이드할 때 다음 명령을 실행: + +```bash +php vendor/bin/runway apm:config-migrate +``` -**참고:** APM 데이터베이스가 크면 이러한 마이그레이션이 실행되는 데 시간이 걸릴 수 있습니다. 피크 시간 외에 이 명령을 실행하는 것이 좋습니다. +이것은 `.runway-config.json` 파일을 사용하는 이전 형식에서 `config.php` 파일에 키/값을 저장하는 새 형식으로 구성을 마이그레이션합니다. ## 오래된 데이터 삭제 -데이터베이스를 깔끔하게 유지하려면 오래된 데이터를 삭제할 수 있습니다. 이는 바쁜 앱을 실행 중이고 데이터베이스 크기를 관리하려는 경우 특히 유용합니다. -다음 명령으로 이를 할 수 있습니다: +데이터베이스를 깔끔하게 유지하려면 오래된 데이터를 삭제할 수 있습니다. 특히 바쁜 앱을 실행 중이고 데이터베이스 크기를 관리하려면 유용합니다. +다음 명령으로 실행: ```bash php vendor/bin/runway apm:purge ``` -이것은 데이터베이스에서 30일 이상 된 모든 데이터를 제거합니다. `--days` 옵션에 다른 값을 전달하여 일 수를 조정할 수 있습니다: +이것은 데이터베이스에서 30일 이상 된 모든 데이터를 제거합니다. `--days` 옵션으로 다른 값을 전달하여 일수 조정: ```bash php vendor/bin/runway apm:purge --days 7 @@ -319,20 +330,20 @@ php vendor/bin/runway apm:purge --days 7 ## 문제 해결 -막혔나요? 다음을 시도하세요: +막혔나요? 다음을 시도: - **대시보드 데이터 없음?** - 워커가 실행 중인가요? `ps aux | grep apm:worker` 확인. - - 구성 경로가 일치하나요? `.runway-config.json` DSN이 실제 파일을 가리키는지 확인. - - 보류 중인 메트릭을 처리하려면 `php vendor/bin/runway apm:worker`를 수동으로 실행. + - 구성 경로가 맞나요? `.runway-config.json` DSN이 실제 파일을 가리키는지 확인. + - 보류 중인 메트릭을 처리하려면 `php vendor/bin/runway apm:worker`를 수동 실행. - **워커 오류?** - SQLite 파일 확인(예: `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - PHP 로그에서 스택 트레이스 확인. - **대시보드 시작 안 됨?** - - 포트 8001 사용 중? `--port 8080` 사용. - - PHP 없음? `--php-path /usr/bin/php` 사용. + - 8001 포트 사용 중? `--port 8080` 사용. + - PHP 찾을 수 없음? `--php-path /usr/bin/php` 사용. - 방화벽 차단? 포트 열기 또는 `--host localhost` 사용. - **너무 느림?** @@ -340,7 +351,7 @@ php vendor/bin/runway apm:purge --days 7 - 배치 크기 줄이기: `--batch_size 20`. - **예외/오류 추적 안 됨?** - - 프로젝트에 [Tracy](https://tracy.nette.org/)가 활성화되어 있으면 Flight의 오류 처리를 재정의합니다. Tracy를 비활성화하고 `Flight::set('flight.handle_errors', true);`가 설정되어 있는지 확인하세요. + - 프로젝트에 [Tracy](https://tracy.nette.org/)가 활성화되어 있으면 Flight의 오류 처리를 재정의합니다. Tracy를 비활성화하고 `Flight::set('flight.handle_errors', true);`가 설정되어 있는지 확인. - **데이터베이스 쿼리 추적 안 됨?** - 데이터베이스 연결에 `PdoWrapper`를 사용 중인지 확인. diff --git a/content/v3/ko/awesome-plugins/awesome_plugins.md b/content/v3/ko/awesome-plugins/awesome_plugins.md index 9505da10..bb0e94df 100644 --- a/content/v3/ko/awesome-plugins/awesome_plugins.md +++ b/content/v3/ko/awesome-plugins/awesome_plugins.md @@ -1,42 +1,42 @@ # 멋진 플러그인 -Flight는 놀라울 정도로 확장 가능합니다. Flight 애플리케이션에 기능을 추가하는 데 사용할 수 있는 여러 플러그인이 있습니다. 일부는 Flight 팀에서 공식적으로 지원하며, 다른 일부는 시작하는 데 도움이 되는 마이크로/라이트 라이브러리입니다. +Flight는 놀라울 정도로 확장 가능합니다. Flight 애플리케이션에 기능을 추가하는 데 사용할 수 있는 여러 플러그인이 있습니다. 일부는 Flight 팀에서 공식적으로 지원하며, 다른 일부는 시작하는 데 도움을 주는 마이크로/라이트 라이브러리입니다. -## API 문서화 +## API 문서 -API 문서화는 모든 API에 필수적입니다. 개발자들이 API와 상호 작용하는 방법을 이해하고 반환되는 것을 기대할 수 있도록 도와줍니다. Flight 프로젝트를 위한 API 문서화를 생성하는 데 도움이 되는 몇 가지 도구가 있습니다. +API 문서는 모든 API에 필수적입니다. 개발자들이 API와 상호 작용하는 방법을 이해하고 반환되는 것을 예상할 수 있도록 돕습니다. Flight 프로젝트를 위한 API 문서를 생성하는 데 도움을 주는 몇 가지 도구가 있습니다. - [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber가 작성한 블로그 포스트로, OpenAPI 사양을 FlightPHP와 함께 사용하여 API 우선 접근 방식을 통해 API를 구축하는 방법에 대해 설명합니다. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI는 Flight 프로젝트를 위한 API 문서화를 생성하는 데 훌륭한 도구입니다. 사용하기 매우 쉽고 필요에 맞게 사용자 지정할 수 있습니다. 이는 Swagger 문서화를 생성하는 데 도움이 되는 PHP 라이브러리입니다. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI는 Flight 프로젝트를 위한 API 문서를 생성하는 데 훌륭한 도구입니다. 사용하기 매우 쉽고 필요에 맞게 사용자 정의할 수 있습니다. 이는 Swagger 문서를 생성하는 데 도움을 주는 PHP 라이브러리입니다. ## 애플리케이션 성능 모니터링 (APM) -애플리케이션 성능 모니터링 (APM)은 모든 애플리케이션에 필수적입니다. 애플리케이션이 어떻게 작동하는지 이해하고 병목 현상이 어디에 있는지 파악하는 데 도움이 됩니다. Flight와 함께 사용할 수 있는 여러 APM 도구가 있습니다. -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM은 Flight 애플리케이션을 모니터링하는 데 사용할 수 있는 간단한 APM 라이브러리입니다. 애플리케이션의 성능을 모니터링하고 병목 현상을 식별하는 데 도움이 됩니다. +애플릭케이션 성능 모니터링 (APM)은 모든 애플리케이션에 필수적입니다. 애플리케이션이 어떻게 작동하는지 이해하고 병목 현상이 어디에 있는지 파악하는 데 도움이 됩니다. Flight와 함께 사용할 수 있는 여러 APM 도구가 있습니다. +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM은 Flight 애플리케이션을 모니터링하는 데 사용할 수 있는 간단한 APM 라이브러리입니다. 애플리케이션 성능을 모니터링하고 병목 현상을 식별하는 데 도움이 됩니다. ## 비동기 -Flight는 이미 빠른 프레임워크이지만, 터보 엔진을 장착하면 모든 것이 더 재미있고 (그리고 도전적) 됩니다! +Flight는 이미 빠른 프레임워크이지만, 터보 엔진을 장착하면 모든 것이 더 재미있고 (도전적) 됩니다! -- [flightphp/async](/awesome-plugins/async) - 공식 Flight Async 라이브러리. 이 라이브러리는 애플리케이션에 비동기 처리를 추가하는 간단한 방법입니다. Swoole/Openswoole을 내부적으로 사용하여 작업을 비동기적으로 실행하는 간단하고 효과적인 방법을 제공합니다. +- [flightphp/async](/awesome-plugins/async) - 공식 Flight Async 라이브러리입니다. 이 라이브러리는 애플리케이션에 비동기 처리를 추가하는 간단한 방법입니다. Swoole/Openswoole을 내부적으로 사용하여 작업을 비동기적으로 실행하는 간단하고 효과적인 방법을 제공합니다. ## 권한 부여/권한 권한 부여와 권한은 누가 무엇에 접근할 수 있는지에 대한 제어가 필요한 모든 애플리케이션에 필수적입니다. -- official [flightphp/permissions](/awesome-plugins/permissions) - 공식 Flight Permissions 라이브러리. 이 라이브러리는 애플리케이션에 사용자 및 애플리케이션 수준의 권한을 추가하는 간단한 방법입니다. +- official [flightphp/permissions](/awesome-plugins/permissions) - 공식 Flight Permissions 라이브러리입니다. 이 라이브러리는 애플리케이션에 사용자 및 애플리케이션 수준의 권한을 추가하는 간단한 방법입니다. ## 캐싱 캐싱은 애플리케이션을 가속화하는 훌륭한 방법입니다. Flight와 함께 사용할 수 있는 여러 캐싱 라이브러리가 있습니다. -- official [flightphp/cache](/awesome-plugins/php-file-cache) - 가볍고 간단하며 독립적인 PHP 파일 내 캐싱 클래스 +- official [flightphp/cache](/awesome-plugins/php-file-cache) - 가볍고 간단하며 독립적인 PHP 인파일 캐싱 클래스 ## CLI CLI 애플리케이션은 애플리케이션과 상호 작용하는 훌륭한 방법입니다. 컨트롤러 생성, 모든 경로 표시 등에 사용할 수 있습니다. -- official [flightphp/runway](/awesome-plugins/runway) - Runway는 Flight 애플리케이션을 관리하는 데 도움이 되는 CLI 애플리케이션입니다. +- official [flightphp/runway](/awesome-plugins/runway) - Runway는 Flight 애플리케이션을 관리하는 데 도움을 주는 CLI 애플리케이션입니다. ## 쿠키 @@ -48,49 +48,49 @@ CLI 애플리케이션은 애플리케이션과 상호 작용하는 훌륭한 로컬 환경에서 개발할 때 디버깅은 필수적입니다. 디버깅 경험을 향상시킬 수 있는 몇 가지 플러그인이 있습니다. -- [tracy/tracy](/awesome-plugins/tracy) - Flight와 함께 사용할 수 있는 완전한 기능을 갖춘 오류 핸들러입니다. 애플리케이션을 디버깅하는 데 도움이 되는 여러 패널을 가지고 있습니다. 확장하고 자체 패널을 추가하기도 매우 쉽습니다. -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) 오류 핸들러와 함께 사용되며, 이 플러그인은 Flight 프로젝트를 위한 디버깅을 돕기 위해 몇 가지 추가 패널을 추가합니다. +- [tracy/tracy](/awesome-plugins/tracy) - Flight와 함께 사용할 수 있는 완전한 기능을 갖춘 오류 핸들러입니다. 애플리케이션을 디버깅하는 데 도움이 되는 여러 패널을 가지고 있습니다. 확장하고 자신의 패널을 추가하기도 매우 쉽습니다. +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) 오류 핸들러와 함께 사용되며, Flight 프로젝트를 위한 디버깅을 돕기 위해 몇 가지 추가 패널을 제공합니다. ## 데이터베이스 -데이터베이스는 대부분의 애플리케이션의 핵심입니다. 데이터를 저장하고 검색하는 방법입니다. 일부 데이터베이스 라이브러리는 쿼리를 작성하는 단순한 래퍼이고, 일부는 완전한 ORMs입니다. +데이터베이스는 대부분의 애플리케이션의 핵심입니다. 데이터를 저장하고 검색하는 방법입니다. 일부 데이터베이스 라이브러리는 쿼리를 작성하는 단순한 래퍼이고, 일부는 완전한 ORM입니다. -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 핵심의 일부인 공식 Flight PDO Wrapper. 쿼리를 작성하고 실행하는 과정을 단순화하는 데 도움이 되는 간단한 래퍼입니다. ORM이 아닙니다. -- official [flightphp/active-record](/awesome-plugins/active-record) - 공식 Flight ActiveRecord ORM/Mapper. 데이터베이스에서 데이터를 쉽게 검색하고 저장하는 훌륭한 작은 라이브러리입니다. -- [byjg/php-migration](/awesome-plugins/migrations) - 프로젝트의 모든 데이터베이스 변경 사항을 추적하는 플러그인. +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 코어의 일부인 공식 Flight PDO Wrapper입니다. 쿼리를 작성하고 실행하는 과정을 단순화하는 데 도움을 주는 간단한 래퍼입니다. ORM이 아닙니다. +- official [flightphp/active-record](/awesome-plugins/active-record) - 공식 Flight ActiveRecord ORM/Mapper입니다. 데이터베이스에서 데이터를 쉽게 검색하고 저장하는 훌륭한 작은 라이브러리입니다. +- [byjg/php-migration](/awesome-plugins/migrations) - 프로젝트의 모든 데이터베이스 변경 사항을 추적하는 플러그인입니다. ## 암호화 -암호화는 민감한 데이터를 저장하는 모든 애플리케이션에 필수적입니다. 데이터를 암호화하고 복호화하는 것은 그리 어렵지 않지만, 암호화 키를 적절히 저장하는 [것](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [은](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [어렵습니다](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). 가장 중요한 것은 암호화 키를 공개 디렉토리에 저장하지 않거나 코드 저장소에 커밋하지 않는 것입니다. +암호화는 민감한 데이터를 저장하는 모든 애플리케이션에 필수적입니다. 데이터를 암호화하고 복호화하는 것은 그리 어렵지 않지만, 암호화 키를 적절히 저장하는 것은 [어렵습니다](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [수 있습니다](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [것입니다](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). 가장 중요한 것은 암호화 키를 공개 디렉토리에 저장하지 않거나 코드 저장소에 커밋하지 않는 것입니다. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - 데이터를 암호화하고 복호화하는 데 사용할 수 있는 라이브러리입니다. 데이터를 암호화하고 복호화하는 데 시작하기 위해 설정하는 것은 상당히 간단합니다. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - 데이터를 암호화하고 복호화하는 데 사용할 수 있는 라이브러리입니다. 데이터를 암호화하고 복호화하는 데 시작하기 위해 실행하는 것이 상당히 간단합니다. ## 작업 큐 -작업 큐는 작업을 비동기적으로 처리하는 데 매우 유용합니다. 이메일 보내기, 이미지 처리 또는 실시간으로 수행할 필요가 없는 모든 작업에 사용할 수 있습니다. +작업 큐는 작업을 비동기적으로 처리하는 데 매우 도움이 됩니다. 이메일 보내기, 이미지 처리 또는 실시간으로 처리할 필요가 없는 모든 것에 사용할 수 있습니다. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue는 작업을 비동기적으로 처리하는 데 사용할 수 있는 라이브러리입니다. beanstalkd, MySQL/MariaDB, SQLite 및 PostgreSQL과 함께 사용할 수 있습니다. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue는 작업을 비동기적으로 처리하는 데 사용할 수 있는 라이브러리입니다. beanstalkd, MySQL/MariaDB, SQLite, PostgreSQL과 함께 사용할 수 있습니다. ## 세션 -세션은 API에는 정말 유용하지 않지만, 웹 애플리케이션을 구축할 때 상태와 로그인 정보를 유지하는 데 세션이 필수적일 수 있습니다. +세션은 API에는 정말 유용하지 않지만, 웹 애플리케이션을 구축할 때 상태와 로그인 정보를 유지하는 데 필수적일 수 있습니다. -- official [flightphp/session](/awesome-plugins/session) - 공식 Flight Session 라이브러리. 세션 데이터를 저장하고 검색하는 데 사용할 수 있는 간단한 세션 라이브러리입니다. PHP의 내장 세션 처리를 사용합니다. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 세션 관리자 (비차단, 플래시, 세그먼트, 세션 암호화). 세션 데이터의 선택적 암호화/복호화를 위해 PHP open_ssl을 사용합니다. +- official [flightphp/session](/awesome-plugins/session) - 공식 Flight Session 라이브러리입니다. 세션 데이터를 저장하고 검색하는 데 사용할 수 있는 간단한 세션 라이브러리입니다. PHP의 내장 세션 처리 방식을 사용합니다. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 세션 관리자 (비동기 차단 없음, 플래시, 세그먼트, 세션 암호화). 세션 데이터의 선택적 암호화/복호화를 위해 PHP open_ssl을 사용합니다. ## 템플릿 템플릿은 UI가 있는 모든 웹 애플리케이션의 핵심입니다. Flight와 함께 사용할 수 있는 여러 템플릿 엔진이 있습니다. -- deprecated [flightphp/core View](/learn#views) - 핵심의 일부인 매우 기본적인 템플릿 엔진입니다. 프로젝트에 몇 페이지 이상이 있다면 사용하지 않는 것이 좋습니다. -- [latte/latte](/awesome-plugins/latte) - Latte는 사용하기 매우 쉽고 Twig나 Smarty보다 PHP 구문에 더 가까운 느낌의 완전한 기능을 갖춘 템플릿 엔진입니다. 확장하고 자체 필터와 함수를 추가하기도 매우 쉽습니다. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate는 자산 컴파일, 템플릿 상속 및 변수 처리를 갖춘 강력한 PHP 템플릿 엔진입니다. 자동 CSS/JS 최소화, 캐싱, Base64 인코딩 및 선택적 Flight PHP 프레임워크 통합 기능을 제공합니다. +- deprecated [flightphp/core View](/learn#views) - 코어의 일부인 매우 기본적인 템플릿 엔진입니다. 프로젝트에 몇 페이지 이상이 있다면 사용하지 않는 것이 좋습니다. +- [latte/latte](/awesome-plugins/latte) - Latte는 사용하기 매우 쉽고 Twig나 Smarty보다 PHP 구문에 더 가까운 느낌을 주는 완전한 기능을 갖춘 템플릿 엔진입니다. 확장하고 자신의 필터와 함수를 추가하기도 매우 쉽습니다. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate는 자산 컴파일, 템플릿 상속, 변수 처리 기능을 가진 강력한 PHP 템플릿 엔진입니다. 자동 CSS/JS 최소화, 캐싱, Base64 인코딩, 선택적 Flight PHP 프레임워크 통합 기능을 제공합니다. ## WordPress 통합 WordPress 프로젝트에서 Flight를 사용하고 싶으신가요? 이를 위한 편리한 플러그인이 있습니다! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 이 WordPress 플러그인은 WordPress와 함께 Flight를 실행할 수 있게 합니다. WordPress 사이트에 Flight 프레임워크를 사용하여 사용자 지정 API, 마이크로서비스 또는 전체 앱을 추가하는 데 완벽합니다. 두 세계의 장점을 모두 누리고 싶다면 매우 유용합니다! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 이 WordPress 플러그인은 Flight를 WordPress와 함께 실행할 수 있게 합니다. WordPress 사이트에 사용자 정의 API, 마이크로서비스 또는 전체 앱을 Flight 프레임워크를 사용하여 추가하는 데 완벽합니다. 두 세계의 장점을 모두 누리고 싶다면 매우 유용합니다! ## 기여 diff --git a/content/v3/ko/awesome-plugins/comment_template.md b/content/v3/ko/awesome-plugins/comment_template.md index a419aec9..2da0b23c 100644 --- a/content/v3/ko/awesome-plugins/comment_template.md +++ b/content/v3/ko/awesome-plugins/comment_template.md @@ -1,11 +1,11 @@ # CommentTemplate -[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate)은 자산 컴파일, 템플릿 상속, 변수 처리 기능을 갖춘 강력한 PHP 템플릿 엔진입니다. 내장된 CSS/JS 압축 및 캐싱으로 템플릿을 간단하면서도 유연하게 관리할 수 있습니다. +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate)은 자산 컴파일, 템플릿 상속, 변수 처리 기능을 갖춘 강력한 PHP 템플릿 엔진입니다. 내장된 CSS/JS 최소화 및 캐싱을 통해 템플릿을 간단하고 유연하게 관리할 수 있습니다. ## 기능 - **템플릿 상속**: 레이아웃 사용 및 다른 템플릿 포함 -- **자산 컴파일**: 자동 CSS/JS 압축 및 캐싱 +- **자산 컴파일**: 자동 CSS/JS 최소화 및 캐싱 - **변수 처리**: 필터와 명령어를 사용한 템플릿 변수 - **Base64 인코딩**: 데이터 URI로 인라인 자산 - **Flight 프레임워크 통합**: Flight PHP 프레임워크와의 선택적 통합 @@ -20,7 +20,7 @@ composer require knifelemon/comment-template ## 기본 구성 -시작하기 위한 기본 구성 옵션이 있습니다. 이에 대해 자세한 내용은 [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate)를 참조하세요. +시작하기 위한 기본 구성 옵션이 있습니다. 이에 대해 더 자세히 읽으려면 [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate)를 참조하세요. ### 방법 1: 콜백 함수 사용 @@ -37,10 +37,10 @@ $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { $engine->setPublicPath(__DIR__); // 템플릿 파일 디렉토리 - 상대 경로와 절대 경로 모두 지원 - $engine->setSkinPath('views'); // 공용 경로 기준 상대 경로 + $engine->setSkinPath('views'); // 공용 경로에 상대적 - // 컴파일된 자산이 저장되는 위치 - 상대 경로와 절대 경로 모두 지원 - $engine->setAssetPath('assets'); // 공용 경로 기준 상대 경로 + // 컴파일된 자산이 저장될 위치 - 상대 경로와 절대 경로 모두 지원 + $engine->setAssetPath('assets'); // 공용 경로에 상대적 // 템플릿 파일 확장자 $engine->setFileExtension('.php'); @@ -74,13 +74,13 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` -## 경로 설정 +## 경로 구성 -CommentTemplate은 상대 경로와 절대 경로 모두에 대한 지능형 경로 처리를 제공합니다: +CommentTemplate은 상대 경로와 절대 경로 모두에 대한 지능적인 경로 처리를 제공합니다: ### 공용 경로 -**공용 경로**는 일반적으로 `index.php`가 있는 웹 애플리케이션의 루트 디렉토리입니다. 이는 웹 서버가 파일을 제공하는 문서 루트입니다. +**공용 경로**는 웹 애플리케이션의 루트 디렉토리로, 일반적으로 `index.php`가 있는 위치입니다. 이는 웹 서버가 파일을 제공하는 문서 루트입니다. ```php // 예: index.php가 /var/www/html/myapp/index.php에 있는 경우 @@ -90,9 +90,9 @@ $template->setPublicPath('/var/www/html/myapp'); // 루트 디렉토리 $template->setPublicPath('C:\\xampp\\htdocs\\myapp'); ``` -### 템플릿 경로 설정 +### 템플릿 경로 구성 -템플릿 경로는 상대 경로와 절대 경로를 모두 지원합니다: +템플릿 경로는 상대 경로와 절대 경로 모두를 지원합니다: ```php $template = new Engine(); @@ -114,9 +114,9 @@ $template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ $template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ ``` -### 자산 경로 설정 +### 자산 경로 구성 -자산 경로도 상대 경로와 절대 경로를 모두 지원합니다: +자산 경로도 상대 경로와 절대 경로 모두를 지원합니다: ```php // 상대 경로 - 공용 경로와 자동으로 결합 @@ -137,19 +137,19 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse **스마트 경로 감지:** -- **상대 경로**: 선행 구분자(`/`, `\`)나 드라이브 문자가 없음 +- **상대 경로**: 선행 구분자 (`/`, `\`) 또는 드라이브 문자 없음 - **Unix 절대**: `/`로 시작 (예: `/var/www/assets`) - **Windows 절대**: 드라이브 문자로 시작 (예: `C:\www`, `D:/assets`) - **UNC 경로**: `\\`로 시작 (예: `\\server\share`) **작동 방식:** -- 모든 경로는 유형에 따라 자동으로 해결됩니다 (상대 vs 절대) +- 모든 경로는 유형(상대 vs 절대)에 따라 자동으로 해결됩니다 - 상대 경로는 공용 경로와 결합됩니다 -- `@css`와 `@js`는 다음 위치에 압축된 파일을 생성합니다: `{resolvedAssetPath}/css/` 또는 `{resolvedAssetPath}/js/` -- `@asset`은 단일 파일을 다음 위치에 복사합니다: `{resolvedAssetPath}/{relativePath}` -- `@assetDir`은 디렉토리를 다음 위치에 복사합니다: `{resolvedAssetPath}/{relativePath}` -- 스마트 캐싱: 소스가 대상보다 최신인 경우에만 파일이 복사됩니다 +- `@css`와 `@js`는 `{resolvedAssetPath}/css/` 또는 `{resolvedAssetPath}/js/`에 최소화된 파일을 생성합니다 +- `@asset`은 단일 파일을 `{resolvedAssetPath}/{relativePath}`로 복사합니다 +- `@assetDir`은 디렉토리를 `{resolvedAssetPath}/{relativePath}`로 복사합니다 +- 스마트 캐싱: 소스 파일이 대상 파일보다 최신일 때만 파일이 복사됩니다 ## 템플릿 지시어 @@ -181,23 +181,23 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse #### CSS 파일 ```html - - + + ``` #### JavaScript 파일 CommentTemplate은 다양한 JavaScript 로딩 전략을 지원합니다: ```html - - - - - - - - - + + + + + + + + + ``` #### CSS/JS 파일 내 자산 지시어 @@ -207,7 +207,7 @@ CommentTemplate은 컴파일 중 CSS 및 JavaScript 파일 내 자산 지시어 **CSS 예시:** ```css /* CSS 파일 내 */ -/* @font-face { +@font-face { font-family: 'CustomFont'; src: url('') format('woff2'); } @@ -271,7 +271,7 @@ const imageData = '';
          -

          메인 콘텐츠가 여기에...

          +

          여기에 주요 콘텐츠...

          @@ -304,7 +304,7 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### 다중 필터 체인 +#### 변수 명령어 ```html {$content|striptag|trim|escape} ``` @@ -317,9 +317,9 @@ const imageData = ''; {* 이것은 한 줄 템플릿 주석입니다 *} {* - 이것은 여러 줄에 걸친 - 다중 줄 - 템플릿 주석입니다 + 이것은 여러 줄 + 템플릿 주석입니다 + 여러 줄에 걸칩니다 *}

          {$title}

          @@ -327,7 +327,7 @@ const imageData = '';

          {$content}

          ``` -**참고**: 템플릿 주석 `{* ... *}`은 HTML 주석 ``과 다릅니다. 템플릿 주석은 처리 중에 제거되며 브라우저에 전달되지 않습니다. +**참고**: 템플릿 주석 `{* ... *}`은 HTML 주석 ``과 다릅니다. 템플릿 주석은 처리 중 제거되며 브라우저에 도달하지 않습니다. ## 예시 프로젝트 구조 diff --git a/content/v3/ko/awesome-plugins/runway.md b/content/v3/ko/awesome-plugins/runway.md index 54dea054..8319aa93 100644 --- a/content/v3/ko/awesome-plugins/runway.md +++ b/content/v3/ko/awesome-plugins/runway.md @@ -1,29 +1,29 @@ -# 런웨이 +# Runway -런웨이는 Flight 어플리케이션을 관리하는 데 도움이 되는 CLI 어플리케이션입니다. 컨트롤러를 생성하고 모든 라우트를 표시할 수 있습니다. 이 라이브러리는 훌륭한 [adhocore/php-cli](https://github.com/adhocore/php-cli) 라이브러리를 기반으로 합니다. +Runway는 Flight 애플리케이션을 관리하는 데 도움을 주는 CLI 애플리케이션입니다. 컨트롤러를 생성하고, 모든 경로를 표시하며, 그 외 더 많은 기능을 제공합니다. 이는 우수한 [adhocore/php-cli](https://github.com/adhocore/php-cli) 라이브러리를 기반으로 합니다. -[여기](https://github.com/flightphp/runway)를 클릭하여 코드를 확인하십시오. +코드 보기 [여기](https://github.com/flightphp/runway) 클릭. -## 설치 +## Installation -컴포저로 설치합니다. +composer를 사용하여 설치하세요. ```bash composer require flightphp/runway ``` -## 기본 구성 +## Basic Configuration -런웨이를 처음 실행하면 설정 프로세스를 진행하고 프로젝트 루트에 `.runway.json` 구성 파일을 생성합니다. 이 파일에는 런웨이가 올바르게 작동하기 위한 일부 필수 구성이 포함되어 있습니다. +Runway를 처음 실행할 때, 설정 프로세스를 안내하고 프로젝트 루트에 `.runway.json` 설정 파일을 생성합니다. 이 파일은 Runway가 제대로 작동하기 위한 필요한 설정을 포함합니다. -## 사용법 +## Usage -런웨이에는 Flight 어플리케이션을 관리하는 데 사용할 수 있는 여러 명령이 있습니다. 런웨이를 사용하는 두 가지 쉬운 방법이 있습니다. +Runway에는 Flight 애플리케이션을 관리하는 데 사용할 수 있는 여러 명령어가 있습니다. Runway를 사용하는 두 가지 쉬운 방법이 있습니다. -1. 스켈레톤 프로젝트를 사용하는 경우 프로젝트의 루트에서 `php runway [command]`를 실행할 수 있습니다. -1. 컴포저를 통해 설치된 패키지로 런웨이를 사용하는 경우 프로젝트의 루트에서 `vendor/bin/runway [command]`를 실행할 수 있습니다. +1. 스켈레톤 프로젝트를 사용 중이라면, 프로젝트 루트에서 `php runway [command]`를 실행할 수 있습니다. +1. composer를 통해 설치된 패키지로 Runway를 사용 중이라면, 프로젝트 루트에서 `vendor/bin/runway [command]`를 실행할 수 있습니다. -어떤 명령이든 `--help` 플래그를 전달하여 명령어 사용 방법에 대한 자세한 정보를 얻을 수 있습니다. +모든 명령어에 대해 `--help` 플래그를 전달하여 명령어 사용 방법에 대한 더 많은 정보를 얻을 수 있습니다. ```bash php runway routes --help @@ -31,17 +31,17 @@ php runway routes --help 다음은 몇 가지 예시입니다: -### 컨트롤러 생성 +### Generate a Controller -`.runway.json` 파일의 구성에 따라 기본 위치는 `app/controllers/` 디렉토리에 컨트롤러를 생성합니다. +`.runway.json` 파일의 설정에 따라, 기본 위치에 `app/controllers/` 디렉토리에서 컨트롤러를 생성합니다. ```bash php runway make:controller MyController ``` -### Active Record 모델 생성 +### Generate an Active Record Model -`.runway.json` 파일의 구성에 따라 기본 위치는 `app/records/` 디렉토리에 컨트롤러를 생성합니다. +`.runway.json` 파일의 설정에 따라, 기본 위치에 `app/records/` 디렉토리에서 컨트롤러를 생성합니다. ```bash php runway make:record users @@ -57,7 +57,7 @@ declare(strict_types=1); namespace app\records; /** - * users 테이블을 위한 ActiveRecord 클래스. + * users 테이블에 대한 ActiveRecord 클래스. * @link https://docs.flightphp.com/awesome-plugins/active-record * * @property int $id @@ -65,20 +65,20 @@ namespace app\records; * @property string $email * @property string $created_at * @property string $updated_at - * // 관계를 정의한 후 $relations 배열에 정의할 수 있습니다. - * @property CompanyRecord $company 관계의 예시 + * // $relations 배열에 관계를 정의한 후 여기에 관계를 추가할 수도 있습니다 + * @property CompanyRecord $company 관계 예시 */ class UserRecord extends \flight\ActiveRecord { /** - * @var array $relations 모델의 관계 설정 + * @var array $relations 모델에 대한 관계 설정 * https://docs.flightphp.com/awesome-plugins/active-record#relationships */ protected array $relations = []; /** * 생성자 - * @param mixed $databaseConnection 데이터베이스에 대한 연결 + * @param mixed $databaseConnection 데이터베이스 연결 */ public function __construct($databaseConnection) { @@ -87,31 +87,31 @@ class UserRecord extends \flight\ActiveRecord } ``` -### 모든 라우트 표시 +### Display All Routes -현재 Flight에 등록된 모든 라우트를 표시합니다. +이 명령어는 현재 Flight에 등록된 모든 경로를 표시합니다. ```bash php runway routes ``` -특정 라우트만 보고 싶은 경우 플래그를 전달하여 라우트를 필터링할 수 있습니다. +특정 경로만 보려면 플래그를 전달하여 경로를 필터링할 수 있습니다. ```bash -# GET 라우트만 표시 +# GET 경로만 표시 php runway routes --get -# POST 라우트만 표시 +# POST 경로만 표시 php runway routes --post # 등. ``` -## 런웨이 사용자 정의 +## Customizing Runway -Flight용 패키지를 생성하거나 프로젝트에 사용자 정의 명령을 추가하려면 프로젝트/패키지에 `src/commands/`, `flight/commands/`, `app/commands/`, 또는 `commands/` 디렉토리를 만들어야 합니다. +Flight용 패키지를 생성하거나 프로젝트에 사용자 지정 명령어를 추가하려면, 프로젝트/패키지에 `src/commands/`, `flight/commands/`, `app/commands/`, 또는 `commands/` 디렉토리를 생성할 수 있습니다. 추가 커스터마이징이 필요하다면 아래 설정 섹션을 참조하세요. -명령을 만들려면 `AbstractBaseCommand` 클래스를 확장하고 최소한 `__construct` 메서드와 `execute` 메서드를 구현하면 됩니다. +명령어를 생성하려면 `AbstractBaseCommand` 클래스를 확장하고, 최소 `__construct` 메서드와 `execute` 메서드를 구현하면 됩니다. ```php $config .runway-config.json에서의 JSON 구성 + * @param array $config .runway-config.json에서 가져온 JSON 설정 */ public function __construct(array $config) { - parent::__construct('make:example', '문서에 예제 생성', $config); - $this->argument('', '웃긴 GIF의 이름'); + parent::__construct('make:example', '문서에 대한 예시 생성', $config); + $this->argument('', '재미있는 GIF의 이름'); } /** @@ -138,17 +138,56 @@ class ExampleCommand extends AbstractBaseCommand * * @return void */ - public function execute(string $controller) + public function execute() { $io = $this->app()->io(); - $io->info('예제 생성 중...'); + $io->info('예시 생성 중...'); - // 여기에 코드 추가 + // 여기에 작업 수행 - $io->ok('예제가 생성되었습니다!'); + $io->ok('예시 생성 완료!'); } } ``` -Flight 어플리케이션에 사용자 정의 명령어를 구축하는 방법에 대해 자세히 알아보려면 [adhocore/php-cli 문서](https://github.com/adhocore/php-cli)를 참조하십시오! \ No newline at end of file +Flight 애플리케이션에 사용자 지정 명령어를 빌드하는 방법에 대한 자세한 정보는 [adhocore/php-cli Documentation](https://github.com/adhocore/php-cli)을 참조하세요! + +### Configuration + +Runway 설정을 커스터마이징해야 한다면, 프로젝트 루트에 `.runway-config.json` 파일을 생성할 수 있습니다. 아래는 설정할 수 있는 추가 설정입니다: + +```js +{ + + // 애플리케이션 디렉토리가 위치한 곳 + "app_root": "app/", + + // 루트 인덱스 파일이 위치한 디렉토리 + "index_root": "public/", + + // 다른 프로젝트의 루트 경로 + "root_paths": [ + "/home/user/different-project", + "/var/www/another-project" + ], + + // 기본 경로는 대부분 설정할 필요가 없지만, 필요 시 여기에 있음 + "base_paths": { + "/includes/libs/vendor", // vendor 디렉토리에 특이한 경로가 있는 경우 등 + }, + + // 최종 경로는 프로젝트 내 명령어 파일을 검색할 위치 + "final_paths": { + "src/diff-path/commands", + "app/module/admin/commands", + }, + + // 전체 경로를 추가하려면 그대로 진행 (프로젝트 루트에 대한 절대 또는 상대 경로) + "paths": [ + "/home/user/different-project/src/diff-path/commands", + "/var/www/another-project/app/module/admin/commands", + "app/my-unique-commands" + ] +} +``` \ No newline at end of file diff --git a/content/v3/ko/examples.md b/content/v3/ko/examples.md index 861b6eb1..2a79ef63 100644 --- a/content/v3/ko/examples.md +++ b/content/v3/ko/examples.md @@ -2,25 +2,26 @@ 새로운 Flight 프로젝트를 시작하는 데 두 가지 옵션이 있습니다: -- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): 컨트롤러와 뷰가 포함된 더 완전한 예제입니다. -- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): 앱을 단일 간단한 파일로 실행하는 데 필요한 모든 것을 포함한 단일 파일입니다. +- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): 컨트롤러와 뷰가 포함된 더 완전한 예제. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): 앱을 단일 간단한 파일로 실행하는 데 필요한 모든 것을 포함한 단일 파일. -커뮤니티가 기여한 예제: +커뮤니티 기여 예제: -- [flightravel](https://github.com/fadrian06-templates/flighravel): Laravel 디렉토리와 PHP 도구 + GH Actions를 사용한 FlightPHP입니다. -- [fleact](https://github.com/flightphp/fleact) - ReactJS 통합을 포함한 FlightPHP 스타터 키트입니다. -- [flastro](https://github.com/flightphp/flastro) - Astro 통합을 포함한 FlightPHP 스타터 키트입니다. -- [velt](https://github.com/flightphp/velt) - Velt는 FlightPHP 백엔드를 사용하는 빠르고 쉬운 Svelte 스타터 템플릿입니다. +- [flightravel](https://github.com/fadrian06-templates/flighravel): Laravel 디렉토리와 PHP 도구 + GH Actions를 사용한 FlightPHP. +- [fleact](https://github.com/flightphp/fleact) - ReactJS 통합을 위한 FlightPHP 스타터 키트. +- [flastro](https://github.com/flightphp/flastro) - Astro 통합을 위한 FlightPHP 스타터 키트. +- [velt](https://github.com/flightphp/velt) - FlightPHP 백엔드를 사용한 빠르고 쉬운 Svelte 스타터 템플릿인 Velt. ## 영감을 얻고 싶으신가요? -이것들은 Flight 팀에서 공식적으로 후원하지 않지만, Flight로 구축된 자신의 프로젝트를 구조화하는 데 아이디어를 줄 수 있습니다! +이것들은 Flight 팀에서 공식적으로 후원하지는 않지만, Flight로 구축된 자신의 프로젝트를 구조화하는 데 아이디어를 줄 수 있습니다! -- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify는 이벤트 주최자와 참석자를 연결하는 단일 페이지 앱입니다. PHP (FlightPHP), JavaScript, MySQL로 구축되었으며, JWT 인증, 이벤트 관리, OpenAPI를 사용한 RESTful API 문서를 특징으로 합니다. -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental은 PHP (FlightPHP), JavaScript, MySQL로 구축된 단일 페이지, 모바일 친화적인 자동차 대여 웹 애플리케이션입니다. 사용자 등록, 차량 검색, 예약을 지원하며, 관리자는 차량, 사용자, 예약을 관리할 수 있습니다. 앱은 REST API, JWT 인증, 현대적인 대여 경험을 위한 반응형 디자인을 특징으로 합니다. -- [Decay](https://github.com/boxybird/decay) - 좀비에 관한 Flight v3, HTMX 및 SleekDB! ([Demo](https://decay.andrewrhyand.com)) +- [ASC REST API Spell Checker](https://github.com/AlMosahih-ASC/asc-api-sample) - FlightPHP와 ArPHP 라이브러리를 사용한 가벼운 REST API로 아랍어 철자 검사를 제공합니다. 이 API는 오타 감지와 수정 제안을 포함한 아랍어 텍스트 철자 검사 기능을 제공합니다. +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify는 이벤트 주최자와 참석자를 연결하는 싱글 페이지 앱입니다. PHP (FlightPHP), JavaScript, MySQL로 구축되었으며, JWT 인증, 이벤트 관리, OpenAPI를 사용한 RESTful API 문서를 특징으로 합니다. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental은 PHP (FlightPHP), JavaScript, MySQL로 구축된 싱글 페이지, 모바일 친화적인 자동차 대여 웹 애플리케이션입니다. 사용자 등록, 자동차 검색, 예약을 지원하며, 관리자는 자동차, 사용자, 예약을 관리할 수 있습니다. 앱은 REST API, JWT 인증, 현대적인 대여 경험을 위한 반응형 디자인을 특징으로 합니다. +- [Decay](https://github.com/boxybird/decay) - 좀비에 관한 HTMX와 SleekDB를 사용한 Flight v3! ([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - 미들웨어, 컨트롤러, Active Record, Latte를 사용한 Flight v3. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Flight 프레임워크를 사용한 간단한 CRUD API 프로젝트로, 새로운 사용자가 CRUD 작업과 데이터베이스 연결을 포함한 PHP 애플리케이션을 빠르게 설정할 수 있는 기본 구조를 제공합니다. 프로젝트는 RESTful API 개발을 위한 Flight 사용 방법을 보여주며, 초보자에게 이상적인 학습 도구이자 경험이 많은 개발자에게 유용한 스타터 키트입니다. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Flight 프레임워크를 사용한 간단한 CRUD API 프로젝트로, 신규 사용자가 CRUD 작업과 데이터베이스 연결이 포함된 PHP 애플리케이션을 빠르게 설정할 수 있는 기본 구조를 제공합니다. 이 프로젝트는 RESTful API 개발을 위한 Flight 사용 방법을 보여주며, 초보자에게 이상적인 학습 도구이자 경험이 많은 개발자에게 유용한 스타터 키트입니다. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -31,7 +32,7 @@ - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 개발 주를 절약해주는 프로덕션 준비 인증 프레임워크입니다. 엔터프라이즈급 보안 기능: 2FA/TOTP, LDAP 통합, Azure SSO, 지능형 속도 제한, 세션 지문 인식, 무차별 대입 공격 보호, 보안 분석 대시보드, 포괄적인 감사 로깅, 세분화된 역할 기반 액세스 제어. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 개발 주를 절약해주는 프로덕션 준비 인증 프레임워크. 기업급 보안 기능: 2FA/TOTP, LDAP 통합, Azure SSO, 지능형 속도 제한, 세션 지문 인식, 무차별 대입 공격 보호, 보안 분석 대시보드, 포괄적인 감사 로깅, 세밀한 역할 기반 액세스 제어. ## 자신의 예제를 공유하고 싶으신가요? diff --git a/content/v3/lv/awesome-plugins/active_record.md b/content/v3/lv/awesome-plugins/active_record.md index 64afbddb..2cfb6abe 100644 --- a/content/v3/lv/awesome-plugins/active_record.md +++ b/content/v3/lv/awesome-plugins/active_record.md @@ -1,12 +1,12 @@ -# Flight Aktīvais Ieraksts +# Flight Active Record -Aktīvais ieraksts ir datubāzes entitātes kartēšana uz PHP objektu. Sakot vienkārši, ja jums ir lietotāju tabula jūsu datubāzē, jūs varat "tulkot" rindu šajā tabulā uz `User` klasi un `$user` objektu jūsu kodā. Skatiet [pamatu piemēru](#pamatu-piemērs). +Aktīvs ieraksts ir datubāzes entītijas kartēšana uz PHP objektu. Vienkārši izteikts, ja jums ir lietotāju tabula datubāzē, jūs varat "tulkot" rindas šajā tabulā uz `User` klasi un `$user` objektu jūsu koda bāzē. Skatiet [pamatinstanci](#basic-example). -Noklikšķiniet [šeit](https://github.com/flightphp/active-record) uz noliktavas GitHub. +Noklikšķiniet [šeit](https://github.com/flightphp/active-record), lai iegūtu repozitoriju GitHub. -## Pamatu Piemērs +## Pamatinstance -Pieņemam, ka jums ir šāda tabula: +Pieņemsim, ka jums ir šāda tabula: ```sql CREATE TABLE users ( @@ -20,9 +20,9 @@ Tagad jūs varat izveidot jaunu klasi, lai attēlotu šo tabulu: ```php /** - * Aktīvā ieraksta klase parasti ir vienskaitļa formā + * ActiveRecord klase parasti ir vienskaitlī * - * Ieteicams pievienot tabulas īpašības kā komentārus šeit + * Ļoti ieteicams pievienot tabulas īpašības kā komentārus šeit * * @property int $id * @property string $name @@ -31,66 +31,66 @@ Tagad jūs varat izveidot jaunu klasi, lai attēlotu šo tabulu: class User extends flight\ActiveRecord { public function __construct($database_connection) { - // jūs to varat iestatīt šādā veidā + // jūs varat iestatīt to šādi parent::__construct($database_connection, 'users'); - // vai šādā veidā + // vai šādi parent::__construct($database_connection, null, [ 'table' => 'users']); } } ``` -Tagad skatiet, kā notiek burvība! +Tagad vērojiet, kā notiek burvība! ```php // sqlite gadījumā -$database_connection = new PDO('sqlite:test.db'); // tas ir tikai piemēram, jūs, iespējams, izmantotu reālu datubāzes savienojumu +$database_connection = new PDO('sqlite:test.db'); // tas ir tikai piemēram, jūs droši vien izmantosiet īstu datubāzes savienojumu // mysql gadījumā $database_connection = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'username', 'password'); // vai mysqli $database_connection = new mysqli('localhost', 'username', 'password', 'test_db'); -// vai mysqli bez objektu balstīta izveidošana +// vai mysqli ar neobjekta bāzētu izveidi $database_connection = mysqli_connect('localhost', 'username', 'password', 'test_db'); $user = new User($database_connection); $user->name = 'Bobby Tables'; -$user->password = password_hash('kāds foršs parole'); +$user->password = password_hash('some cool password'); $user->insert(); // vai $user->save(); echo $user->id; // 1 $user->name = 'Joseph Mamma'; -$user->password = password_hash('kāds foršs parole atkal!!!'); +$user->password = password_hash('some cool password again!!!'); $user->insert(); -// šeit nevar izmantot $user->save(), jo tas domās, ka tas ir atjauninājums! +// šeit nevar izmantot $user->save(), pretējā gadījumā tas domās, ka tas ir atjauninājums! echo $user->id; // 2 ``` -Un bija tik viegli pievienot jaunu lietotāju! Tagad, kad datubāzē ir lietotāja rinda, kā to izvilkt? +Un tik viegli bija pievienot jaunu lietotāju! Tagad, kad datubāzē ir lietotāja rinda, kā jūs to izvilksiet? ```php $user->find(1); // atrast id = 1 datubāzē un atgriezt to. echo $user->name; // 'Bobby Tables' ``` -Un kas notiks, ja vēlaties atrast visus lietotājus? +Un kas, ja jūs vēlaties atrast visus lietotājus? ```php $users = $user->findAll(); ``` -Ko teikt par noteiktu nosacījumu? +Ko darīt ar noteiktu nosacījumu? ```php $users = $user->like('name', '%mamma%')->findAll(); ``` -Redzat, cik tas ir aizraujoši? Instalēsim to un sāksim! +Redziet, cik jautri tas ir? Instalēsim to un sāksim! -## Instalācija +## Instalēšana Vienkārši instalējiet ar Composer @@ -98,45 +98,45 @@ Vienkārši instalējiet ar Composer composer require flightphp/active-record ``` -## Izmantošana +## Lietošana -To var izmantot kā patstāvīgu bibliotēku vai kopā ar Flight PHP rāmci. Pilnīgi atkarīgs no jums. +To var izmantot kā neatkarīgu bibliotēku vai ar Flight PHP Framework. Pilnībā atkarīgs no jums. -### Patstāvīgi -Vienkārši pārliecinieties, ka nododat PDO savienojumu konstruktoram. +### Neatkarīgi +Vienkārši pārliecinieties, ka konstruktoram nododat PDO savienojumu. ```php -$pdo_connection = new PDO('sqlite:test.db'); // tas ir tikai piemēram, jūs, iespējams, izmantotu reālu datubāzes savienojumu +$pdo_connection = new PDO('sqlite:test.db'); // tas ir tikai piemēram, jūs droši vien izmantosiet īstu datubāzes savienojumu $User = new User($pdo_connection); ``` -> Negribiet katru reizi iestatīt savu datubāzes savienojumu konstruktorā? Skatiet [Datubāzes Savienojuma Pārvaldība](#datubāzes-savienojuma-pārvaldība) citām idejām! +> Vai nevēlaties vienmēr iestatīt datubāzes savienojumu konstruktorā? Skatiet [Datubāzes savienojuma pārvaldību](#database-connection-management) citiem variantiem! -### Reģistrēt kā metodi Flight -Ja jūs izmantojat Flight PHP rāmi, varat reģistrēt aktīvā ieraksta klasi kā pakalpojumu, bet jums to patiesībā nav jāizdara. +### Reģistrēšana kā metode Flight +Ja izmantojat Flight PHP Framework, jūs varat reģistrēt ActiveRecord klasi kā servisu, bet patiesībā nav obligāti. ```php Flight::register('user', 'User', [ $pdo_connection ]); -// tad jūs varat to izmantot šādi kontrolierī, funkcijā utt. +// tad jūs varat izmantot to šādi kontrolierī, funkcijā utt. Flight::user()->find(1); ``` ## `runway` Metodes -[runway](/awesome-plugins/runway) ir CLI rīks Flight, kas ir izstrādāts ar īpašu komandu šai bibliotēkai. +[runway](/awesome-plugins/runway) ir CLI rīks Flight, kas ir ar pielāgotu komandu šai bibliotēkai. ```bash -# Izmantošana +# Lietošana php runway make:record database_table_name [class_name] # Piemērs php runway make:record users ``` -Tas izveidos jaunu klasi mapē `app/records/` kā `UserRecord.php` ar sekojošo saturu: +Tas izveidos jaunu klasi `app/records/` direktorijā kā `UserRecord.php` ar šādu saturu: ```php notNull('password')->orderBy('id DESC')->find(); -// atrast ierakstu pēc noteikta id +// atrast ierakstu pēc specifiska id $id = 123; $user->find($id); ``` #### `findAll(): array` -Atrast visus ierakstus tabulā, kuru jūs norādāt. +Atrast visus ierakstus tabulā, ko jūs norādāt. ```php $user->findAll(); @@ -203,11 +203,11 @@ $user->findAll(); #### `isHydrated(): boolean` (v0.4.0) -Atgriež `true`, ja pašreizējais ieraksts ir bijis hidrogenizēts (iegūts no datubāzes). +Atgriež `true`, ja pašreizējais ieraksts ir hidratēts (iegūts no datubāzes). ```php $user->find(1); -// ja ir atrasts ieraksts ar datiem... +// ja ieraksts ir atrasts ar datiem... $user->isHydrated(); // true ``` @@ -222,9 +222,9 @@ $user->password = md5('demo'); $user->insert(); ``` -##### Teksta balstītas primārās atslēgas +##### Teksta bāzētas primārās atslēgas -Ja jums ir teksta balstīta primārā atslēga (piemēram, UUID), jūs varat iestatīt primārās atslēgas vērtību pirms ievietošanas vienā no diviem veidiem. +Ja jums ir teksta bāzēta primārā atslēga (piemēram, UUID), jūs varat iestatīt primārās atslēgas vērtību pirms ievietošanas divos veidos. ```php $user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]); @@ -234,24 +234,24 @@ $user->password = md5('demo'); $user->insert(); // vai $user->save(); ``` -vai jūs varat ļaut primārajai atslēgai automātiski tikt ģenerētai jūsu vietā. +vai jūs varat ļaut primārajai atslēgai automātiski ģenerēties caur notikumiem. ```php class User extends flight\ActiveRecord { public function __construct($database_connection) { parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]); - // jūs varat arī iestatīt primāro atslēgu šādā veidā, nevis augstāk norādītajā masīvā. + // jūs varat iestatīt primaryKey arī šādi, nevis ar masīvu iepriekš. $this->primaryKey = 'uuid'; } protected function beforeInsert(self $self) { - $self->uuid = uniqid(); // vai kā citādi nepieciešams ģenerēt jūsu unikālos id + $self->uuid = uniqid(); // vai kā jūs ģenerējat savas unikālās id } } ``` -Ja jūs neiestatāt primāro atslēgu pirms ievietošanas, tā tiks iestatīta uz `rowid` un datubāze to ģenerēs jums, taču tā neuzturēsies, jo šis lauks var nepastāvēt jūsu tabulā. Tāpēc ieteicams izmantot notikumu, lai automātiski to apstrādātu. +Ja jūs neiestatāt primāro atslēgu pirms ievietošanas, tā tiks iestatīta uz `rowid` un datubāze to ģenerēs jums, bet tā nepastāvēs, jo tas lauks var nepastāvēt jūsu tabulā. Tāpēc ieteicams izmantot notikumu, lai automātiski apstrādātu to. #### `update(): boolean|ActiveRecord` @@ -265,7 +265,7 @@ $user->update(); #### `save(): boolean|ActiveRecord` -Ievieto vai atjaunina pašreizējo ierakstu datubāzē. Ja ierakstam ir id, tas atjauninās, citādi tas ievietos. +Ievieto vai atjaunina pašreizējo ierakstu datubāzē. Ja ierakstam ir id, tas atjauninās, citādi ievietos. ```php $user = new User($pdo_connection); @@ -274,7 +274,7 @@ $user->password = md5('demo'); $user->save(); ``` -**Piezīme:** Ja jums ir attiecības, kas definētas klasē, tās tiek rekurzīvi saglabātas, ja tās ir bijušas definētas, instancētas un ir netīri dati, ko atjaunināt. (v0.4.0 un augstāks) +**Piezīme:** Ja jums ir definētas attiecības klasē, tas rekursīvi saglabās tās attiecības, ja tās ir definētas, instance un ir netīri dati atjaunināšanai. (v0.4.0 un augstāk) #### `delete(): boolean` @@ -285,7 +285,7 @@ $user->gt('id', 0)->orderBy('id desc')->find(); $user->delete(); ``` -Jūs arī varat dzēst vairākus ierakstus, veicot meklēšanu iepriekš. +Jūs varat arī dzēst vairākus ierakstus, izpildot meklēšanu iepriekš. ```php $user->like('name', 'Bob%')->delete(); @@ -298,27 +298,27 @@ Netīri dati attiecas uz datiem, kas ir mainīti ierakstā. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); -// šajā brīdī nav "netīru" datu. +// līdz šim nekas nav "netīrs". -$user->email = 'test@example.com'; // tagad e-pasts tiek uzskatīts par "netīru", jo tas ir mainījies. +$user->email = 'test@example.com'; // tagad email tiek uzskatīts par "netīru", jo tas ir mainīts. $user->update(); -// tagad nav nevienu datu, kas ir netīri, jo tie ir atjaunināti un uzglabāti datubāzē +// tagad nav datu, kas ir netīri, jo tie ir atjaunināti un saglabāti datubāzē -$user->password = password_hash('jaunā parole'); // tagad šis ir netīrs -$user->dirty(); // neko nenododot, tiks notīrīti visi netīrie ieraksti. -$user->update(); // nekas netiks atjaunināts, jo nekas netika sagūstīts kā netīrs. +$user->password = password_hash()'newpassword'); // tagad tas ir netīrs +$user->dirty(); // neko nepadojot, tas notīrīs visus netīros ierakstus. +$user->update(); // nekas netiks atjaunināts, jo nekas netika uztverts kā netīrs. -$user->dirty([ 'name' => 'kaut kas', 'password' => password_hash('cita parole') ]); -$user->update(); // gan vārds, gan parole tiek atjaunināti. +$user->dirty([ 'name' => 'something', 'password' => password_hash('a different password') ]); +$user->update(); // gan name, gan password tiks atjaunināti. ``` #### `copyFrom(array $data): ActiveRecord` (v0.4.0) -Tas ir alias `dirty()` metodei. Tas ir nedaudz vairāk skaidrāks par to, ko jūs darāt. +Tas ir alias `dirty()` metodei. Tas ir nedaudz skaidrāks, ko jūs darāt. ```php -$user->copyFrom([ 'name' => 'kaut kas', 'password' => password_hash('cita parole') ]); -$user->update(); // abi vārds un parole tiek atjaunināti. +$user->copyFrom([ 'name' => 'something', 'password' => password_hash('a different password') ]); +$user->update(); // gan name, gan password tiks atjaunināti. ``` #### `isDirty(): boolean` (v0.4.0) @@ -333,15 +333,14 @@ $user->isDirty(); // true #### `reset(bool $include_query_data = true): ActiveRecord` -Atjauno pašreizējo ierakstu tā sākotnējā stāvoklī. Tas ir ļoti labi izmantot ciklu tipa uzvedībā. -Ja nododat `true`, tas arī atiestatīs vaicājuma datus, kas tika izmantoti, lai atrastu pašreizējo objektu (pamatuzvedība). +Atiestata pašreizējo ierakstu uz tā sākotnējo stāvokli. Tas ir patiešām labs lietošanai cilpas veida uzvedībās. Ja padojat `true`, tas arī atiestatīs vaicājuma datus, kas tika izmantoti, lai atrastu pašreizējo objektu (noklusējuma uzvedība). ```php $users = $user->greaterThan('id', 0)->orderBy('id desc')->find(); $user_company = new UserCompany($pdo_connection); foreach($users as $user) { - $user_company->reset(); // sāk ar tīru lapu + $user_company->reset(); // sākt ar tīru lapu $user_company->user_id = $user->id; $user_company->company_id = $some_company_id; $user_company->insert(); @@ -350,12 +349,12 @@ foreach($users as $user) { #### `getBuiltSql(): string` (v0.4.1) -Pēc tam, kad esat izpildījis `find()`, `findAll()`, `insert()`, `update()`, vai `save()` metodi, jūs varat iegūt SQL, kas tika izveidots un izmantot to problēmu risināšanai. +Pēc tam, kad izpildāt `find()`, `findAll()`, `insert()`, `update()` vai `save()` metodi, jūs varat iegūt SQL, kas tika izveidots, un izmantot to atkļūdošanas nolūkos. -## SQL Vaicājumu Metodes +## SQL vaicājuma metodes #### `select(string $field1 [, string $field2 ... ])` -Jūs varat atlasīt tikai dažus no kolonnām tabulā, ja vēlaties (tas ir efektīvāk tiešām plašām tabulām ar daudzām kolonnām) +Jūs varat atlasīt tikai dažas kolonnas tabulā, ja vēlaties (tas ir efektīvāks patiešām plašās tabulās ar daudzām kolonnām) ```php $user->select('id', 'name')->find(); @@ -363,7 +362,7 @@ $user->select('id', 'name')->find(); #### `from(string $table)` -Tehniski jūs varat izvēlēties arī citu tabulu! Kāpēc gan ne?! +Jūs tehniski varat izvēlēties arī citu tabulu! Kāpēc gan ne?! ```php $user->select('id', 'name')->from('user')->find(); @@ -371,7 +370,7 @@ $user->select('id', 'name')->from('user')->find(); #### `join(string $table_name, string $join_condition)` -Jūs pat varat pievienot citu tabulu datubāzē. +Jūs pat varat pievienoties citai tabulai datubāzē. ```php $user->join('contacts', 'contacts.user_id = users.id')->find(); @@ -385,11 +384,11 @@ Jūs varat iestatīt dažus pielāgotus where argumentus (jūs nevarat iestatīt $user->where('id=1 AND name="demo"')->find(); ``` -**Drošības Piezīme** - Iespējams, ka jūs sadarbojas ar kaut ko līdzīgu `$user->where("id = '{$id}' AND name = '{$name}'")->find();`. Lūdzu, NEDARĪT TO!!! Tas var būt pakļauts tam, ko sauc par SQL injekcijas uzbrukumiem. Ir daudz rakstu tiešsaistē, lūdzu, Google "sql injekcijas uzbrukumi php" un jūs atradīsiet daudz rakstu par šo tēmu. Pareizā metode, kā to apstrādāt ar šo bibliotēku, ir tā, ka, nevis šo `where()` metodi, jūs to darītu vairāk līdzīgi `$user->eq('id', $id)->eq('name', $name)->find();`. Ja jums ir absolūti jādara tā, `PDO` bibliotēkai ir `$pdo->quote($var)`, lai to izdzēstu priekš jums. Tikai pēc tam, kad esat izmantojuši `quote()`, varat to izmantot `where()` paziņojumā. +**Drošības piezīme** - Jūs varētu būt kārdināts darīt kaut ko līdzīgu `$user->where("id = '{$id}' AND name = '{$name}'")->find();`. Lūdzu, NEDARIET TO!!! Tas ir pakļauts tam, ko sauc par SQL injekcijas uzbrukumiem. Ir daudz rakstu tiešsaistē, lūdzu, meklējiet Google "sql injection attacks php" un atradīsit daudz rakstu par šo tēmu. Pareizais veids, kā apstrādāt to ar šo bibliotēku, ir, nevis izmantot šo `where()` metodi, bet gan kaut ko līdzīgu `$user->eq('id', $id)->eq('name', $name)->find();` Ja jums absolūti jāto dara, `PDO` bibliotēkai ir `$pdo->quote($var)`, lai aizbēgtu to jums. Tikai pēc `quote()` izmantošanas jūs varat izmantot to `where()` paziņojumā. #### `group(string $group_by_statement)/groupBy(string $group_by_statement)` -Grupējiet savus rezultātus pēc noteikta nosacījuma. +Grupēt jūsu rezultātus pēc noteikta nosacījuma. ```php $user->select('COUNT(*) as count')->groupBy('name')->findAll(); @@ -405,7 +404,7 @@ $user->orderBy('name DESC')->find(); #### `limit(string $limit)/limit(int $offset, int $limit)` -Ierobežojiet atgriezto ierakstu skaitu. Ja tiek norādīta otrā int, tā būs offset, limits tieši tāpat kā SQL. +Ierobežot atgriezto ierakstu skaitu. Ja dots otrais int, tas būs nobīde, ierobežojums tieši kā SQL. ```php $user->orderby('name DESC')->limit(0, 10)->findAll(); @@ -497,50 +496,50 @@ Kur `field BETWEEN $value AND $value1` $user->between('id', [1, 2])->find(); ``` -### OR Nosacījumi +### OR nosacījumi -Ir iespējams savus nosacījumus ietīt OR paziņojumā. To var izdarīt, izmantojot `startWrap()` un `endWrap()` metodi vai norādīt 3. parametru nosacījumam pēc lauka un vērtības. +Ir iespējams apvijināt jūsu nosacījumus OR paziņojumā. Tas tiek darīts ar `startWrap()` un `endWrap()` metodi vai aizpildot 3. parametru nosacījumā pēc lauka un vērtības. ```php // Metode 1 $user->eq('id', 1)->startWrap()->eq('name', 'demo')->or()->eq('name', 'test')->endWrap('OR')->find(); -// Tas novērtēs `id = 1 AND (name = 'demo' OR name = 'test')` +// Tas tiks novērtēts kā `id = 1 AND (name = 'demo' OR name = 'test')` // Metode 2 $user->eq('id', 1)->eq('name', 'demo', 'OR')->find(); -// Tas novērtēs `id = 1 OR name = 'demo'` +// Tas tiks novērtēts kā `id = 1 OR name = 'demo'` ``` ## Attiecības -Jūs varat iestatīt vairākus veidus attiecības, izmantojot šo bibliotēku. Jūs varat iestatīt vienu->daudz un vienu->vienu attiecības starp tabulām. Tas prasa mazliet papildus sagatavošanu klasē iepriekš. +Jūs varat iestatīt vairākas attiecību veidus, izmantojot šo bibliotēku. Jūs varat iestatīt one->many un one->one attiecības starp tabulām. Tas prasa nedaudz papildu iestatījumu klasē iepriekš. -Iestatīt `$relations` masīvu nav grūti, bet pareizā sintakse var būt mulsinoša. +Iestatot `$relations` masīvu nav grūti, bet pareizās sintakses minēšana var būt mulsinoša. ```php protected array $relations = [ - // jūs varat nosaukt atslēgu kā vēlaties. Aktīvā ieraksta nosaukums, iespējams, ir labs. Piemērs: lietotājs, kontakts, klients + // jūs varat nosaukt atslēgu jebkā vēlaties. ActiveRecord nosaukums droši vien ir labs. Piem: user, contact, client 'user' => [ // obligāti // self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO - self::HAS_ONE, // šis ir attiecību veids + self::HAS_ONE, // tas ir attiecību veids // obligāti - 'Some_Class', // šī ir 'otra' Aktīvā ieraksta klase, uz kuru atsaucas + 'Some_Class', // tas ir "cits" ActiveRecord klase, uz kuru tas atsaucas // obligāti // atkarībā no attiecību veida - // self::HAS_ONE = ārējā atslēga, kas atsaucas uz pievienošanu - // self::HAS_MANY = ārējā atslēga, kas atsaucas uz pievienošanu - // self::BELONGS_TO = lokālā atslēga, kas atsaucas uz pievienošanu + // self::HAS_ONE = ārējā atslēga, kas atsaucas uz savienojumu + // self::HAS_MANY = ārējā atslēga, kas atsaucas uz savienojumu + // self::BELONGS_TO = lokālā atslēga, kas atsaucas uz savienojumu 'local_or_foreign_key', - // tikai FYI, tas arī pievienojas tikai uz "otras" modeļa primāro atslēgu + // tikai FYI, tas arī pievienojas tikai uz "citas" modeļa primāro atslēgu // izvēles - [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // papildu nosacījumi, kurus vēlaties, pievienojot attiecību + [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // papildu nosacījumi, ko vēlaties, pievienojoties attiecībai // $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5)) // izvēles - 'back_reference_name' // ja vēlaties atsaukt šo attiecību atpakaļ uz sevi, piemēram, `$user->contact->user`; + 'back_reference_name' // tas ir, ja vēlaties atpakaļatsauce uz šo attiecību atpakaļ uz sevi Piem: $user->contact->user; ]; ] ``` @@ -570,7 +569,7 @@ class Contact extends ActiveRecord{ } ``` -Tagad mums ir atsauces iestatītas, lai mēs varētu tās izmantot ļoti viegli! +Tagad mums ir atsauces iestatītas, lai mēs varētu izmantot tās ļoti viegli! ```php $user = new User($pdo_connection); @@ -583,7 +582,7 @@ foreach($user->contacts as $contact) { echo $contact->id; } -// vai mēs varam doties otrā virzienā. +// vai mēs varam iet otru ceļu. $contact = new Contact(); // atrast vienu kontaktu @@ -593,10 +592,111 @@ $contact->find(); echo $contact->user->name; // tas ir lietotāja vārds ``` -Ļoti jauki, vai ne? +Diezgan forši, vai ne? -## Iestatīt Pielāgotus Datus -Reizēm jums var būt nepieciešams pievienot kaut ko unikālu savam Aktīvam Ierakstam, piemēram, pielāgotu aprēķinu, kas varētu būt vieglāk pievienot objektam, kas pēc tam būtu nodots, piemēram, šablonam. +### Eager Loading + +#### Pārskats +Eager loading atrisina N+1 vaicājuma problēmu, iepriekš ielādējot attiecības. Tā vietā, lai izpildītu atsevišķu vaicājumu katrai ieraksta attiecībai, eager loading iegūst visus saistītos datus tikai vienā papildu vaicājumā uz attiecību. + +> **Piezīme:** Eager loading ir pieejams tikai v0.7.0 un augstāk. + +#### Pamatlietošana +Izmantojiet `with()` metodi, lai norādītu, kuras attiecības eager ielādēt: +```php +// Ielādēt lietotājus ar viņu kontaktiem 2 vaicājumos, nevis N+1 +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + foreach ($u->contacts as $contact) { + echo $contact->email; // Nav papildu vaicājuma! + } +} +``` + +#### Vairākas attiecības +Ielādēt vairākas attiecības uzreiz: +```php +$users = $user->with(['contacts', 'profile', 'settings'])->findAll(); +``` + +#### Attiecību veidi + +##### HAS_MANY +```php +// Eager ielādēt visus kontaktus katram lietotājam +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + // $u->contacts jau ir ielādēts kā masīvs + foreach ($u->contacts as $contact) { + echo $contact->email; + } +} +``` +##### HAS_ONE +```php +// Eager ielādēt vienu kontaktu katram lietotājam +$users = $user->with('contact')->findAll(); +foreach ($users as $u) { + // $u->contact jau ir ielādēts kā objekts + echo $u->contact->email; +} +``` + +##### BELONGS_TO +```php +// Eager ielādēt vecāku lietotājus visiem kontaktiem +$contacts = $contact->with('user')->findAll(); +foreach ($contacts as $c) { + // $c->user jau ir ielādēts + echo $c->user->name; +} +``` +##### Ar find() +Eager loading darbojas ar +findAll() + un +find() +: + +```php +$user = $user->with('contacts')->find(1); +// Lietotājs un visi viņu kontakti ielādēti 2 vaicājumos +``` +#### Veiktspējas priekšrocības +Bez eager loading (N+1 problēma): +```php +$users = $user->findAll(); // 1 vaicājums +foreach ($users as $u) { + $contacts = $u->contacts; // N vaicājumi (viens uz lietotāju!) +} +// Kopā: 1 + N vaicājumi +``` + +Ar eager loading: + +```php +$users = $user->with('contacts')->findAll(); // 2 vaicājumi kopā +foreach ($users as $u) { + $contacts = $u->contacts; // 0 papildu vaicājumi! +} +// Kopā: 2 vaicājumi (1 lietotājiem + 1 visiem kontaktiem) +``` +10 lietotājiem tas samazina vaicājumus no 11 līdz 2 - 82% samazinājums! + +#### Svarīgas piezīmes +- Eager loading ir pilnīgi izvēles - lazy loading joprojām darbojas kā iepriekš +- Jau ielādētās attiecības automātiski tiek izlaistas +- Atpakaļatsauces darbojas ar eager loading +- Attiecību atsauces tiek ievērotas eager loading laikā + +#### Ierobežojumi +- Ieslēgtas eager loading (piem., +with(['contacts.addresses']) +) pašlaik netiek atbalstīts +- Eager load ierobežojumi caur aizvērumiem nav atbalstīti šajā versijā + +## Pielāgota datu iestatīšana +Dažreiz jums var būt nepieciešams pievienot kaut ko unikālu jūsu ActiveRecord, piemēram, pielāgotu aprēķinu, kas varētu būt vieglāk pievienot objektam, kas tad tiks nodots, teiksim, šablonam. #### `setCustomData(string $field, mixed $value)` Jūs pievienojat pielāgoto datu ar `setCustomData()` metodi. @@ -612,11 +712,11 @@ echo $user->page_view_count; ## Notikumi -Vēl viena super jauka funkcija šajā bibliotēkā ir notikumi. Notikumi tiek aktivizēti noteiktos brīžos, pamatojoties uz noteiktām metodēm, ko jūs izsaucat. Tie ir ļoti noderīgi, lai automātiski izveidotu datus jums. +Viens vairāk super lielisks elements par šo bibliotēku ir par notikumiem. Notikumi tiek izraisīti noteiktos laikos, balstoties uz noteiktām metodēm, ko jūs saucat. Tie ir ļoti noderīgi, lai automātiski iestatītu datus jums. #### `onConstruct(ActiveRecord $ActiveRecord, array &config)` -Tas ir ļoti noderīgi, ja nepieciešams iestatīt noklusējuma savienojumu vai kaut ko tamlīdzīgu. +Tas ir patiešām noderīgi, ja jums ir nepieciešams iestatīt noklusējuma savienojumu vai kaut ko tādu. ```php // index.php vai bootstrap.php @@ -629,13 +729,13 @@ Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php class User extends flight\ActiveRecord { - protected function onConstruct(self $self, array &$config) { // neaizmirstiet par & atsauci - // jūs varētu to izdarīt, lai automātiski iestatītu savienojumu + protected function onConstruct(self $self, array &$config) { // neaizmirstiet & atsauci + // jūs varētu to darīt, lai automātiski iestatītu savienojumu $config['connection'] = Flight::db(); - // vai arī šo + // vai to $self->transformAndPersistConnection(Flight::db()); - // jūs varat arī šādi iestatīt tabulas nosaukumu. + // Jūs varat arī iestatīt tabulas nosaukumu šādi. $config['table'] = 'users'; } } @@ -643,7 +743,7 @@ class User extends flight\ActiveRecord { #### `beforeFind(ActiveRecord $ActiveRecord)` -Šis visticamāk ir noderīgs, ja jums nepieciešams vaicājuma manipulācija katru reizi. +Tas, visticamāk, ir noderīgi tikai tad, ja jums ir nepieciešama vaicājuma manipulācija katru reizi. ```php class User extends flight\ActiveRecord { @@ -654,7 +754,7 @@ class User extends flight\ActiveRecord { } protected function beforeFind(self $self) { - // vienmēr palaist id >= 0, ja tā jums patīk + // vienmēr palaidiet id >= 0, ja tas ir jūsu stils $self->gte('id', 0); } } @@ -662,7 +762,7 @@ class User extends flight\ActiveRecord { #### `afterFind(ActiveRecord $ActiveRecord)` -Šis visticamāk ir noderīgāks, ja jums katru reizi ir jāpalaista kāda loģika, kad šis ieraksts tiek iegūts. Vai jums jādešifrē kaut kas? Vai jums katru reizi jāveic pielāgots skaitīšanas vaicājums (neefektīvs, bet, nu...). +Šis, visticamāk, ir noderīgāks, ja jums vienmēr ir jāpalaid kaut kāda loģika katru reizi, kad šis ieraksts tiek iegūts. Vai jums ir jāšifrē kaut kas? Vai jums ir jāpalaid pielāgots skaita vaicājums katru reizi (nav efektīvi, bet nu labi)? ```php class User extends flight\ActiveRecord { @@ -673,10 +773,10 @@ class User extends flight\ActiveRecord { } protected function afterFind(self $self) { - // kaut ko dešifrējot + // šifrēšana kaut kā $self->secret = yourDecryptFunction($self->secret, $some_key); - // varbūt glabājot kaut ko pielāgotu, piemēram, vaicājumu??? + // varbūt saglabājot kaut ko pielāgotu kā vaicājumu??? $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']; } } @@ -684,7 +784,7 @@ class User extends flight\ActiveRecord { #### `beforeFindAll(ActiveRecord $ActiveRecord)` -Šis varētu būt tikai noderīgs, ja jums nepieciešama vaicājuma manipulācija katru reizi. +Tas, visticamāk, ir noderīgi tikai tad, ja jums ir nepieciešama vaicājuma manipulācija katru reizi. ```php class User extends flight\ActiveRecord { @@ -695,7 +795,7 @@ class User extends flight\ActiveRecord { } protected function beforeFindAll(self $self) { - // vienmēr palaist id >= 0, ja tā jums patīk + // vienmēr palaidiet id >= 0, ja tas ir jūsu stils $self->gte('id', 0); } } @@ -703,7 +803,7 @@ class User extends flight\ActiveRecord { #### `afterFindAll(array $results)` -Līdzīgi `afterFind()`, bet jūs varat to izdarīt visiem ierakstiem! +Līdzīgs `afterFind()`, bet jūs varat to darīt visiem ierakstiem! ```php class User extends flight\ActiveRecord { @@ -716,7 +816,7 @@ class User extends flight\ActiveRecord { protected function afterFindAll(array $results) { foreach($results as $self) { - // darīt kaut ko foršu līdzīgi kā afterFind() + // dariet kaut ko foršu kā afterFind() } } } @@ -724,7 +824,7 @@ class User extends flight\ActiveRecord { #### `beforeInsert(ActiveRecord $ActiveRecord)` -Ļoti noderīgi, ja nepieciešams iestatīt noklusējuma vērtības katru reizi. +Patiešām noderīgi, ja jums ir nepieciešams iestatīt noklusējuma vērtības katru reizi. ```php class User extends flight\ActiveRecord { @@ -749,7 +849,7 @@ class User extends flight\ActiveRecord { #### `afterInsert(ActiveRecord $ActiveRecord)` -Varbūt jums ir lietotāja scenārijs, lai mainītu datus pēc ievietošanas? +Varbūt jums ir gadījums, kad mainīt datus pēc ievietošanas? ```php class User extends flight\ActiveRecord { @@ -760,16 +860,16 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // jūs darāt sevi + // dariet, ko vēlaties Flight::cache()->set('most_recent_insert_id', $self->id); - // vai jebkas cits... + // vai ko citu.... } } ``` #### `beforeUpdate(ActiveRecord $ActiveRecord)` -Ļoti noderīgi, ja jums vajag dažas noklusējuma vērtības katru reizi atjaunināšanai. +Patiešām noderīgi, ja jums ir nepieciešams iestatīt noklusējuma vērtības katru reizi atjauninājumā. ```php class User extends flight\ActiveRecord { @@ -790,7 +890,7 @@ class User extends flight\ActiveRecord { #### `afterUpdate(ActiveRecord $ActiveRecord)` -Varbūt jums ir lietotāja gadījums, lai mainītu datus pēc atjaunināšanas? +Varbūt jums ir gadījums, kad mainīt datus pēc atjaunināšanas? ```php class User extends flight\ActiveRecord { @@ -801,16 +901,16 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // jūs darāt sevi + // dariet, ko vēlaties Flight::cache()->set('most_recently_updated_user_id', $self->id); - // vai jebkas cits.... + // vai ko citu.... } } ``` #### `beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)` -Tas ir noderīgi, ja vēlaties, lai notikumi notiktu gan ievietošanas, gan atjaunināšanas laikā. Es ietaupīšu jums garu skaidrojumu, bet, esmu pārliecināts, ka jūs varat uzminēt, kas tas ir. +Tas ir noderīgi, ja vēlaties, lai notikumi notiktu gan ievietošanas, gan atjauninājuma laikā. Es jūs saīsināšu no gara skaidrojuma, bet esmu pārliecināts, ka jūs varat uzminēt, kas tas ir. ```php class User extends flight\ActiveRecord { @@ -828,7 +928,7 @@ class User extends flight\ActiveRecord { #### `beforeDelete(ActiveRecord $ActiveRecord)/afterDelete(ActiveRecord $ActiveRecord)` -Nezinu, ko jūs šeit vēlētos darīt, bet šeit nav spriedumu! Iet uz priekšu! +Neesmu pārliecināts, ko jūs vēlētos darīt šeit, bet bez tiesājumiem! Dodieties! ```php class User extends flight\ActiveRecord { @@ -844,9 +944,9 @@ class User extends flight\ActiveRecord { } ``` -## Datubāzes Savienojuma Pārvaldība +## Datubāzes savienojuma pārvaldība -Kad jūs izmantojat šo bibliotēku, jūs varat iestatīt datubāzes savienojumu dažādos veidos. Jūs varat iestatīt savienojumu konstruktorā, jūs varat iestatīt to caur konfigurācijas mainīgo `$config['connection']` vai jūs varat iestatīt to caur `setDatabaseConnection()` (v0.4.1). +Izmantojot šo bibliotēku, jūs varat iestatīt datubāzes savienojumu dažādos veidos. Jūs varat iestatīt savienojumu konstruktorā, varat iestatīt to caur konfigurācijas mainīgo `$config['connection']` vai varat iestatīt to caur `setDatabaseConnection()` (v0.4.1). ```php $pdo_connection = new PDO('sqlite:test.db'); // piemēram @@ -858,11 +958,11 @@ $user = new User(); $user->setDatabaseConnection($pdo_connection); ``` -Ja vēlaties izvairīties no katra reizes `$database_connection` iestatīšanas, ir veidi, kā to izdarīt! +Ja vēlaties izvairīties no `$database_connection` iestatīšanas katru reizi, kad saucat active record, ir veidi ap to! ```php // index.php vai bootstrap.php -// Iestatiet šo kā reģistrētu klasi Flight +// Iestatīt to kā reģistrētu klasi Flight Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php @@ -875,24 +975,23 @@ class User extends flight\ActiveRecord { } } -// Un tagad, nav nepieciešami argumenti! +// Un tagad nav nepieciešami argumenti! $user = new User(); ``` -> **Piezīme:** Ja plānojat veikt vienību testēšanu, to izdarot, var rasties grūtības, bet kopumā, jo jūs varat injicēt savu -savienojumu ar `setDatabaseConnection()` vai `$config['connection']`, tas nav pārāk slikti. +> **Piezīme:** Ja plānojat veikt unit testēšanu, darot to šādi, tas var pievienot dažus izaicinājumus unit testēšanai, bet kopumā, jo jūs varat injicēt savu savienojumu ar `setDatabaseConnection()` vai `$config['connection']`, tas nav pārāk slikti. -Ja jums nepieciešams atsvaidzināt datubāzes savienojumu, piemēram, ja jūs veicat garu CLI skriptu un periodiski nepieciešams atsvaidzināt savienojumu, jūs varat atkārtoti iestatīt savienojumu ar `$your_record->setDatabaseConnection($pdo_connection)`. +Ja jums ir jāatjauno datubāzes savienojums, piemēram, ja palaižat ilgu CLI skriptu un ir jāatjauno savienojums ik pa laikam, jūs varat atkārtoti iestatīt savienojumu ar `$your_record->setDatabaseConnection($pdo_connection)`. -## Ieteikums +## Iesaiste -Lūdzu, dariet to. :D +Lūdzu, dariet. :D ### Iestatīšana -Kad jūs piedalāties, pārliecinieties, ka izpildāt `composer test-coverage`, lai uzturētu 100% testēšanas pārklājumu (šis nav patiesais vienību testēšanas pārklājums, drīzāk integrācijas testēšana). +Kad jūs iesaistāties, pārliecinieties, ka palaižat `composer test-coverage`, lai uzturētu 100% testa pārklājumu (tas nav īsts unit testa pārklājums, vairāk kā integrācijas testēšana). -Tāpat pārliecinieties, ka izpildāt `composer beautify` un `composer phpcs`, lai novērstu jebkādas linting kļūdas. +Arī pārliecinieties, ka palaižat `composer beautify` un `composer phpcs`, lai labotu jebkādas linting kļūdas. ## Licence diff --git a/content/v3/lv/awesome-plugins/apm.md b/content/v3/lv/awesome-plugins/apm.md index e4d7fb2f..bb990d34 100644 --- a/content/v3/lv/awesome-plugins/apm.md +++ b/content/v3/lv/awesome-plugins/apm.md @@ -1,14 +1,14 @@ # FlightPHP APM Dokumentācija -Laipni lūdzam FlightPHP APM — jūsu lietojumprogrammas personīgais veiktspējas treneris! Šis ceļvedis ir jūsu ceļakarte, lai iestatītu, izmantotu un apgūtu Lietojumprogrammas veiktspējas uzraudzību (APM) ar FlightPHP. Vai nu jūs meklējat lēnus pieprasījumus, vai vienkārši vēlaties iedziļināties latentuma diagrammās, mēs jums palīdzēsim. Padarīsim jūsu lietojumprogrammu ātrāku, jūsu lietotājus laimīgākus un jūsu atkļūdošanas sesijas vieglas! +Laipni lūdzam FlightPHP APM — jūsu lietojumprogrammas personīgais veiktspējas treneris! Šis ceļvedis ir jūsu ceļakarte uz APM (Application Performance Monitoring) uzstādīšanu, izmantošanu un apgūšanu ar FlightPHP. Neatkarīgi no tā, vai jūs medījāt lēnus pieprasījumus vai vienkārši vēlaties iedziļināties latentuma diagrammās, mēs jums palīdzēsim. Padarīsim jūsu lietojumprogrammu ātrāku, jūsu lietotājus laimīgākus un jūsu atkļūdošanas sesijas vieglas! Apskatiet [demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) Flight Docs vietnes panelim. ![FlightPHP APM](/images/apm.png) -## Kāpēc APM ir svarīga +## Kāpēc APM ir svarīgi -Iedomājieties: jūsu lietojumprogramma ir aizņemta restorāns. Bez veida, kā izsekot, cik ilgi aizņem pasūtījumi vai kur virtuvē rodas aizkavēšanās, jūs minaties, kāpēc klienti aiziet neapmierināti. APM ir jūsu pavāra palīgs — tas uzrauga katru soli, no ienākošajiem pieprasījumiem līdz datubāzes vaicājumiem, un atzīmē visu, kas jūs palēnina. Lēnas lapas zaudē lietotājus (pētījumi saka, ka 53% aiziet, ja vietne ielādējas vairāk nekā 3 sekundes!), un APM palīdz jums noķert šīs problēmas *pirms* tās sadod. Tas ir proaktīvs mierinājums — mazāk “kāpēc tas ir salūzis?” brīžu, vairāk “paskatieties, cik gludi tas darbojas!” uzvaru. +Iedomājieties: jūsu lietojumprogramma ir aizņemts restorāns. Bez veida, kā izsekot, cik ilgi tiek apstrādāti pasūtījumi vai kur virtuvē rodas aizkavēšanās, jūs minaties, kāpēc klienti aiziet neapmierināti. APM ir jūsu pavāra palīgs — tas novēro katru soli, no ienākošajiem pieprasījumiem līdz datubāzes vaicājumiem, un atzīmē visu, kas jūs palēnina. Lēnas lapas zaudē lietotājus (pētījumi saka, ka 53% aiziet, ja vietne ielādējas ilgāk par 3 sekundēm!), un APM palīdz jums uztvert šīs problēmas *pirms* tās kaitē. Tas ir proaktīvs mierinājums — mazāk “kāpēc tas ir salūzis?” brīžu, vairāk “paskatieties, cik gludi tas darbojas!” uzvaru. ## Instalācija @@ -20,16 +20,16 @@ composer require flightphp/apm Jums būs nepieciešams: - **PHP 7.4+**: Nodrošina saderību ar LTS Linux izplatījumiem, vienlaikus atbalstot modernu PHP. -- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Vieglā ietvara, ko mēs uzlabojam. +- **[FlightPHP Core](https://github.com/flightphp/core) v3.15+**: Vieglā ietvara versija, ko mēs uzlabojam. ## Atbalstītās datubāzes -FlightPHP APM pašlaik atbalsta šādas datubāzes metriku uzglabāšanai: +FlightPHP APM pašlaik atbalsta šādas datubāzes metrikas uzglabāšanai: -- **SQLite3**: Vienkārša, failu balstīta, lieliska lokālai izstrādei vai mazām lietojumprogrammām. Noklusējuma opcija lielākajā daļā iestatījumu. -- **MySQL/MariaDB**: Ideāla lielākiem projektiem vai produkcijas vidēm, kur nepieciešama robusta, mērogojama uzglabāšana. +- **SQLite3**: Vienkārša, failu balstīta, lieliska lokālai izstrādei vai mazām lietojumprogrammām. Noklusējuma opcija lielākajā daļā uzstādījumu. +- **MySQL/MariaDB**: Ideāla lielākiem projektiem vai ražošanas vidēm, kur nepieciešama robusta, mērogojama uzglabāšana. -Jūs varat izvēlēties datubāzes tipu konfigurācijas solī (skatiet zemāk). Pārliecinieties, ka jūsu PHP videi ir instalētas nepieciešamās paplašinājumi (piem., `pdo_sqlite` vai `pdo_mysql`). +Jūs varat izvēlēties datubāzes tipu konfigurācijas solī (skat. zemāk). Pārliecinieties, ka jūsu PHP videi ir instalētas nepieciešamās paplašinājumi (piem., `pdo_sqlite` vai `pdo_mysql`). ## Sākšana @@ -41,6 +41,7 @@ Ievietojiet to savā `index.php` vai `services.php` failā, lai sāktu izsekoša ```php use flight\apm\logger\LoggerFactory; +use flight\database\PdoWrapper; use flight\Apm; $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); @@ -54,12 +55,12 @@ $Apm->addPdoConnection($pdo); ``` **Kas šeit notiek?** -- `LoggerFactory::create()` paņem jūsu konfigurāciju (vairāk par to drīz) un iestata žurnālu — pēc noklusējuma SQLite. +- `LoggerFactory::create()` paņem jūsu konfigurāciju (vairāk par to drīz) un uzstāda žurnālu — pēc noklusējuma SQLite. - `Apm` ir zvaigzne — tas klausās Flight notikumus (pieprasījumus, maršrutus, kļūdas utt.) un savāc metrikas. - `bindEventsToFlightInstance($app)` saista visu ar jūsu Flight lietojumprogrammu. **Pro Padoms: Paraugšana** -Ja jūsu lietojumprogramma ir aizņemta, žurnālošana *katra* pieprasījuma var pārslodzes. Izmantojiet paraugu (0.0 līdz 1.0): +Ja jūsu lietojumprogramma ir aizņemta, žurnālošana *katram* pieprasījumam var pārslodzes. Izmantojiet paraugu (0.0 līdz 1.0): ```php $Apm = new Apm($ApmLogger, 0.1); // Žurnālo 10% pieprasījumu @@ -69,16 +70,16 @@ Tas saglabā veiktspēju ātru, vienlaikus dodot jums stingrus datus. ### 2. Konfigurējiet to -Palaidiet šo, lai izveidotu jūsu `.runway-config.json`: +Izpildiet to, lai izveidotu jūsu `.runway-config.json`: ```bash php vendor/bin/runway apm:init ``` **Ko tas dara?** -- Palaida vedni, kas jautā, no kurienes nāk neapstrādātās metrikas (avots) un kur iet apstrādātie dati (mērķis). +- Palaista vedni, kas jautā, no kurienes nāk izejmateriālu metrikas (avots) un kur iet apstrādātie dati (mērķis). - Noklusējums ir SQLite — piem., `sqlite:/tmp/apm_metrics.sqlite` avotam, cits mērķim. -- Jūs iegūsiet konfigurāciju kā: +- Jūs iegūsiet konfigurāciju, piemēram: ```json { "apm": { @@ -90,14 +91,14 @@ php vendor/bin/runway apm:init } ``` -> Šis process arī jautās, vai vēlaties palaist migrācijas šim iestatījumam. Ja iestatāt to pirmo reizi, atbilde ir jā. +> Šis process arī jautās, vai vēlaties palaist migrācijas šim uzstādījumam. Ja to uzstādāt pirmo reizi, atbilde ir jā. **Kāpēc divas vietas?** -Neapstrādātās metrikas uzkrājas ātri (domājiet nefiltrētus žurnālus). Darbinieks tās apstrādā strukturētā mērķī panelim. Saglabā visu kārtīgu! +Izejmateriālu metrikas uzkrājas ātri (domājiet nefiltrētus žurnālus). Darbinieks tos apstrādā strukturētā mērķī paneļa vajadzībām. Tas uztur kārtību! ### 3. Apstrādājiet metrikas ar darbinieku -Darbinieks pārvērš neapstrādātās metrikas datus, kas gatavi panelim. Palaidiet to vienreiz: +Darbinieks pārvērš izejmateriālu metrikas par paneļa gataviem datiem. Palaidiet to vienreiz: ```bash php vendor/bin/runway apm:worker @@ -105,44 +106,44 @@ php vendor/bin/runway apm:worker **Ko tas dara?** - Lasīt no jūsu avota (piem., `apm_metrics.sqlite`). -- Apstrādā līdz 100 metriku (noklusējuma partijas lielums) jūsu mērķī. -- Apstājas, kad pabeigts vai ja nav metrikas. +- Apstrādā līdz 100 metrikiem (noklusējuma partijas lielums) jūsu mērķī. +- Apstājas, kad pabeigts vai ja nav atlikušo metriku. **Uzturiet to darbojošos** -Dzīvām lietojumprogrammām vēlaties nepārtrauktu apstrādi. Šeit ir jūsu opcijas: +Dzīvām lietojumprogrammām jūs vēlēsities nepārtrauktu apstrādi. Šeit ir jūsu opcijas: -- **Daemon režīms**: +- **Dēmona režīms**: ```bash php vendor/bin/runway apm:worker --daemon ``` - Darbojas mūžīgi, apstrādājot metrikas, kad tās nāk. Lieliski izstrādei vai maziem iestatījumiem. + Darbojas mūžīgi, apstrādājot metrikas, kad tās nāk. Lieliski izstrādei vai maziem uzstādījumiem. - **Crontab**: - Pievienojiet to savam crontab (`crontab -e`): + Pievienojiet to jūsu crontab (`crontab -e`): ```bash * * * * * php /path/to/project/vendor/bin/runway apm:worker ``` - Palaid katru minūti — ideāli produkcijai. + Palaid katru minūti — ideāli ražošanai. - **Tmux/Screen**: Sāciet atvienojamu sesiju: ```bash tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon - # Ctrl+B, tad D, lai atvienotu; `tmux attach -t apm-worker` lai savienotu atkārtoti + # Ctrl+B, tad D, lai atvienotos; `tmux attach -t apm-worker` lai savienotos atkārtoti ``` - Uztur to darbojošos pat ja izreģistrējaties. + Uztur to darbojošos pat ja izvadaties. - **Pielāgoti uzstādījumi**: ```bash php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 ``` - - `--batch_size 50`: Apstrādāt 50 metrikas uzreiz. - - `--max_messages 1000`: Apstāties pēc 1000 metriku. + - `--batch_size 50`: Apstrādā 50 metrikas uzreiz. + - `--max_messages 1000`: Apstājas pēc 1000 metrikiem. - `--timeout 300`: Iziet pēc 5 minūtēm. **Kāpēc censties?** -Bez darbinieka jūsu panelis ir tukšs. Tas ir tilts starp neapstrādātiem žurnāliem un izmantojamiem ieskatiem. +Bez darbinieka jūsu panelis ir tukšs. Tas ir tilts starp izejmateriālu žurnāliem un izmantojamiem ieskatiem. ### 4. Palaidiet paneli @@ -153,52 +154,52 @@ php vendor/bin/runway apm:dashboard ``` **Kas tas ir?** -- Palaid PHP serveri pie `http://localhost:8001/apm/dashboard`. +- Palaid PHP serveri uz `http://localhost:8001/apm/dashboard`. - Rāda pieprasījumu žurnālus, lēnus maršrutus, kļūdu līmeņus un vairāk. **Pielāgojiet to**: ```bash php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php ``` -- `--host 0.0.0.0`: Pieejams no jebkura IP (noderīgs attālinātai skatīšanai). +- `--host 0.0.0.0`: Piekļaujams no jebkura IP (noderīgs attālam skatīšanai). - `--port 8080`: Izmanto citu portu, ja 8001 ir aizņemts. - `--php-path`: Norāda uz PHP, ja tas nav jūsu PATH. Atveriet URL savā pārlūkprogrammā un izpētiet! -#### Produkcijas režīms +#### Ražošanas režīms -Produkcijā jums var nākties izmēģināt dažas tehnikas, lai panelis darbotos, jo droši vien ir ugunsmūri un citas drošības pasākumi. Šeit ir dažas opcijas: +Ražošanai jums var nākties izmēģināt vairākas tehnikas, lai palaistu paneli, jo, iespējams, ir ugunsmūri un citas drošības pasākumi. Šeit ir dažas opcijas: -- **Izmantojiet reverso proxy**: Iestatiet Nginx vai Apache, lai pārsūtītu pieprasījumus panelim. +- **Izmantojiet reverso proxy**: Uzstādiet Nginx vai Apache, lai pārsūtītu pieprasījumus uz paneli. - **SSH tunelis**: Ja varat SSH uz serveri, izmantojiet `ssh -L 8080:localhost:8001 youruser@yourserver`, lai tunelētu paneli uz jūsu lokālo mašīnu. - **VPN**: Ja jūsu serveris ir aiz VPN, savienojieties ar to un piekļūstiet panelim tieši. -- **Konfigurējiet ugunsmūri**: Atveriet portu 8001 jūsu IP vai servera tīklam. (vai kādu portu jūs iestatījāt). -- **Konfigurējiet Apache/Nginx**: Ja jums ir tīmekļa serveris jūsu lietojumprogrammas priekšā, jūs varat to konfigurēt domēnam vai apakšdomēnam. Ja to darāt, iestatīsiet dokumentu sakni uz `/path/to/your/project/vendor/flightphp/apm/dashboard` +- **Konfigurējiet ugunsmūri**: Atveriet portu 8001 jūsu IP vai servera tīklam. (vai kādu portu jūs uzstādījāt). +- **Konfigurējiet Apache/Nginx**: Ja jums ir tīmekļa serveris jūsu lietojumprogrammas priekšā, jūs varat to konfigurēt uz domēna vai apakšdomēna. Ja to darāt, iestatiet dokumenta sakni uz `/path/to/your/project/vendor/flightphp/apm/dashboard` #### Vai vēlaties citu paneli? -Jūs varat izveidot savu paneli, ja vēlaties! Apskatiet vendor/flightphp/apm/src/apm/presenter direktoriju idejām, kā prezentēt datus savam panelim! +Jūs varat izveidot savu paneli, ja vēlaties! Apskatiet vendor/flightphp/apm/src/apm/presenter direktoriju idejām, kā prezentēt datus jūsu paša panelim! -## Panaļa funkcijas +## Paneļa funkcijas -Panels ir jūsu APM galvenā mītne — šeit ir, ko redzēsiet: +Panels ir jūsu APM galvenā mītne — šeit ir tas, ko redzēsiet: - **Pieprasījumu žurnāls**: Katrs pieprasījums ar laika zīmi, URL, atbildes kodu un kopējo laiku. Noklikšķiniet “Detalizēti”, lai redzētu starprogrammatūru, vaicājumus un kļūdas. - **Lēnākie pieprasījumi**: Top 5 pieprasījumi, kas aizņem laiku (piem., “/api/heavy” 2.5s). - **Lēnākie maršruti**: Top 5 maršruti pēc vidējā laika — lieliski, lai pamanītu modeļus. -- **Kļūdu līmenis**: Procentos no pieprasījumiem, kas neizdodas (piem., 2.3% 500s). +- **Kļūdu līmenis**: Procentuālā daļa no neveiksmīgiem pieprasījumiem (piem., 2.3% 500). - **Latentuma percentīļi**: 95. (p95) un 99. (p99) atbilžu laiki — ziniet savus sliktākos scenārijus. -- **Atbildes koda diagramma**: Vizualizējiet 200s, 404s, 500s laika gaitā. +- **Atbildes koda diagramma**: Vizualizējiet 200, 404, 500 laika gaitā. - **Gari vaicājumi/Starpprogrammatūra**: Top 5 lēni datubāzes zvani un starprogrammatūras slāņi. -- **Kešs trāpījums/Praids**: Cik bieži jūsu kešs glābj dienu. +- **Kešs trāpījums/Prašu**: Cik bieži jūsu kešs glābj dienu. **Ekstras**: -- Filtrēt pēc “Pēdējā stunda,” “Pēdējā diena,” vai “Pēdējā nedēļa.” -- Pārslēdziet tumšo režīmu tiem vēlošajiem seansiem. +- Filtrējiet pēc “Pēdējā stunda”, “Pēdējā diena” vai “Pēdējā nedēļa”. +- Pārslēdziet tumšo režīmu tiem vēlošiem nakts seansiem. **Piemērs**: -Pieprasījums uz `/users` var rādīt: +Pieprasījums uz `/users` var parādīt: - Kopējais laiks: 150ms - Starpprogrammatūra: `AuthMiddleware->handle` (50ms) - Vaicājums: `SELECT * FROM users` (80ms) @@ -206,7 +207,7 @@ Pieprasījums uz `/users` var rādīt: ## Pievienošana pielāgotu notikumu -Izsekot jebko — piemēram, API zvanu vai maksājumu procesu: +Izsekojiet jebko — piemēram, API zvanu vai maksājuma procesu: ```php use flight\apm\CustomEvent; @@ -219,7 +220,7 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ``` **Kur tas parādās?** -Panelī pieprasījuma detaļās zem “Pielāgoti notikumi” — paplašināms ar skaistu JSON formatējumu. +Paneļa pieprasījuma detaļās zem “Pielāgoti notikumi” — paplašināms ar skaistu JSON formatējumu. **Lietošanas gadījums**: ```php @@ -231,11 +232,11 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -Tagad redzēsiet, vai tas API velk jūsu lietojumprogrammu lejup! +Tagad jūs redzēsiet, vai tas API velk jūsu lietojumprogrammu uz leju! ## Datubāzes uzraudzība -Izsekot PDO vaicājumus šādi: +Izsekojiet PDO vaicājumus šādi: ```php use flight\database\PdoWrapper; @@ -244,29 +245,29 @@ $pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // < $Apm->addPdoConnection($pdo); ``` -**Ko jūs iegūstat**: -- Vaicājuma tekstu (piem., `SELECT * FROM users WHERE id = ?`) -- Izpildes laiku (piem., 0.015s) -- Rindu skaitu (piem., 42) +**Ko jūs iegūsiet**: +- Vaicājuma teksts (piem., `SELECT * FROM users WHERE id = ?`) +- Izpildes laiks (piem., 0.015s) +- Rindu skaits (piem., 42) **Brīdinājums**: -- **Opsionāli**: Izlaidiet to, ja nevajag DB izsekošanu. +- **Neobligāti**: Izlaidiet to, ja nevajag DB izsekošanu. - **Tikai PdoWrapper**: Kodols PDO vēl nav savienots — sekojiet līdzi! -- **Veiktspējas brīdinājums**: Žurnālošana katra vaicājuma uz DB smagas vietnes var palēnināt. Izmantojiet paraugu (`$Apm = new Apm($ApmLogger, 0.1)`), lai samazinātu slodzi. +- **Veiktspējas brīdinājums**: Žurnālošana katram vaicājumam uz DB smagas vietnes var palēnināt. Izmantojiet paraugu (`$Apm = new Apm($ApmLogger, 0.1)`), lai samazinātu slodzi. **Piemēra izvade**: - Vaicājums: `SELECT name FROM products WHERE price > 100` - Laiks: 0.023s -- Rindas: 15 +- Rindu: 15 ## Darbinieka opcijas Pielāgojiet darbinieku savai gaumei: -- `--timeout 300`: Apstājas pēc 5 minūtēm — labi testēšanai. -- `--max_messages 500`: Ierobežo līdz 500 metriku — saglabā to ierobežotu. +- `--timeout 300`: Apstājas pēc 5 minūtēm — labs testēšanai. +- `--max_messages 500`: Ierobežo līdz 500 metrikiem — uztur to ierobežotu. - `--batch_size 200`: Apstrādā 200 uzreiz — līdzsvaro ātrumu un atmiņu. -- `--daemon`: Darbojas bez apstājas — ideāli dzīvai uzraudzībai. +- `--daemon`: Darbojas nepārtraukti — ideāli tiešai uzraudzībai. **Piemērs**: ```bash @@ -276,11 +277,11 @@ Darbojas stundu, apstrādājot 100 metrikas uzreiz. ## Pieprasījuma ID lietojumprogrammā -Katram pieprasījumam ir unikāls pieprasījuma ID izsekošanai. Jūs varat izmantot šo ID savā lietojumprogrammā, lai korelētu žurnālus un metrikas. Piemēram, jūs varat pievienot pieprasījuma ID kļūdu lapai: +Katram pieprasījumam ir unikāls pieprasījuma ID izsekošanai. Jūs varat izmantot šo ID savā lietojumprogrammā, lai korelētu žurnālus un metrikas. Piemēram, jūs varat pievienot pieprasījuma ID kļūdas lapai: ```php Flight::map('error', function($message) { - // Iegūt pieprasījuma ID no atbildes galvenes X-Flight-Request-Id + // Iegūstiet pieprasījuma ID no atbildes galvenes X-Flight-Request-Id $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); // Papildus jūs varētu to iegūt no Flight mainīgā @@ -293,33 +294,43 @@ Flight::map('error', function($message) { ## Atjaunināšana -Ja atjaunināt uz jaunāku APM versiju, ir iespēja, ka ir datubāzes migrācijas, kas jāpalaid. Jūs varat to izdarīt, palaižot šādu komandu: +Ja jūs atjaunināt uz jaunāku APM versiju, ir iespējams, ka ir datubāzes migrācijas, kas jāpalaid. Jūs varat to izdarīt, izpildot šādu komandu: ```bash php vendor/bin/runway apm:migrate ``` -Tas palaidīs visas nepieciešamās migrācijas, lai atjauninātu datubāzes shēmu uz jaunāko versiju. +Tas palaids visas nepieciešamās migrācijas, lai atjauninātu datubāzes shēmu uz jaunāko versiju. + +**Piezīme:** Ja jūsu APM datubāze ir liela izmērā, šīs migrācijas var prasīt laiku. Jūs varat vēlēties palaist šo komandu ārpus maksimālās slodzes stundām. + +### Atjaunināšana no 0.4.3 -> 0.5.0 + +Ja jūs atjaunināt no 0.4.3 uz 0.5.0, jums jāpalaid šāda komanda: + +```bash +php vendor/bin/runway apm:config-migrate +``` -**Piezīme:** Ja jūsu APM datubāze ir liela izmērā, šīs migrācijas var prasīt laiku. Jūs varat vēlēties palaidīt šo komandu ārpus maksimālās slodzes stundām. +Tas migrēs jūsu konfigurāciju no vecā formāta, izmantojot `.runway-config.json` failu, uz jauno formātu, kas glabā atslēgas/vērtības `config.php` failā. ## Veco datu dzēšana -Lai saglabātu jūsu datubāzi kārtīgu, jūs varat dzēst vecus datus. Tas ir īpaši noderīgi, ja darbojaties aizņemtu lietojumprogrammu un vēlaties uzturēt datubāzes izmēru vadāmu. -Jūs varat to izdarīt, palaižot šādu komandu: +Lai uzturētu jūsu datubāzi kārtīgu, jūs varat dzēst vecus datus. Tas ir īpaši noderīgi, ja darbojaties aizņemtu lietojumprogrammu un vēlaties uzturēt datubāzes izmēru pārvaldāmu. +Jūs varat to izdarīt, izpildot šādu komandu: ```bash php vendor/bin/runway apm:purge ``` -Tas noņems visus datus vecākus par 30 dienām no datubāzes. Jūs varat pielāgot dienu skaitu, nododot citu vērtību `--days` opcijai: +Tas noņem visus datus, kas vecāki par 30 dienām no datubāzes. Jūs varat pielāgot dienu skaitu, nododot citu vērtību `--days` opcijai: ```bash php vendor/bin/runway apm:purge --days 7 ``` -Tas noņems visus datus vecākus par 7 dienām no datubāzes. +Tas noņem visus datus, kas vecāki par 7 dienām no datubāzes. -## Problēmu risināšana +## Traucējummeklēšana -Iestrēdzis? Mēģiniet šos: +Iestrēdzis? Izmēģiniet šos: - **Nav paneļa datu?** - Vai darbinieks darbojas? Pārbaudiet `ps aux | grep apm:worker`. @@ -328,7 +339,7 @@ Iestrēdzis? Mēģiniet šos: - **Darbinieka kļūdas?** - Apskatiet jūsu SQLite failus (piem., `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Pārbaudiet PHP žurnālus uz steka pēdzīmēm. + - Pārbaudiet PHP žurnālus uz steka pēdnēm. - **Panels nesākas?** - Ports 8001 aizņemts? Izmantojiet `--port 8080`. @@ -339,9 +350,9 @@ Iestrēdzis? Mēģiniet šos: - Samaziniet parauga līmeni: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - Samaziniet partijas lielumu: `--batch_size 20`. -- **Netiek izsekotas izņēmumi/Kļūdas?** - - Ja jums ir [Tracy](https://tracy.nette.org/) iespējots projektam, tas pārņems Flight kļūdu apstrādi. Jums jāatspējo Tracy un tad jāpārliecinās, ka `Flight::set('flight.handle_errors', true);` ir iestatīts. +- **Netiek izsekotas izņēmumi/kļūdas?** + - Ja jums ir [Tracy](https://tracy.nette.org/) iespējots projektam, tas pārņems Flight kļūdu apstrādi. Jums jāatspējo Tracy un pēc tam jāpārliecinās, ka `Flight::set('flight.handle_errors', true);` ir iestatīts. - **Netiek izsekoti datubāzes vaicājumi?** - - Pārliecinieties, ka izmantojat `PdoWrapper` savām datubāzes savienojumiem. + - Pārliecinieties, ka izmantojat `PdoWrapper` saviem datubāzes savienojumiem. - Pārliecinieties, ka konstruktorā pēdējais arguments ir `true`. \ No newline at end of file diff --git a/content/v3/lv/awesome-plugins/awesome_plugins.md b/content/v3/lv/awesome-plugins/awesome_plugins.md index 3eddbbd7..1d132321 100644 --- a/content/v3/lv/awesome-plugins/awesome_plugins.md +++ b/content/v3/lv/awesome-plugins/awesome_plugins.md @@ -1,26 +1,26 @@ # Lieliski spraudņi -Flight ir neticami paplašināms. Ir vairāki spraudņi, ko var izmantot, lai pievienotu funkcionalitāti jūsu Flight lietojumprogrammai. Daži no tiem oficiāli atbalsta Flight Team, bet citi ir mikro/lite bibliotēkas, lai palīdzētu jums sākt. +Flight ir neticami paplašināms. Ir vairāki spraudņi, ko var izmantot, lai pievienotu funkcionalitāti jūsu Flight lietojumprogrammai. Daži no tiem oficiāli atbalsta Flight komanda, bet citi ir mikro/lite bibliotēkas, lai palīdzētu jums sākt. ## API dokumentācija -API dokumentācija ir izšķiroša jebkuram API. Tā palīdz izstrādātājiem saprast, kā mijiedarboties ar jūsu API un ko sagaidīt pretī. Ir pieejami vairāki rīki, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. +API dokumentācija ir izšķiroša jebkuram API. Tā palīdz izstrādātājiem saprast, kā mijiedarboties ar jūsu API un ko sagaidīt pretī. Ir pieejami vairāki rīki, lai palīdzētu jums ģenerēt API dokumentāciju jūsu Flight projektiem. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Bloga ieraksts, ko uzrakstījis Daniels Šreibers, par to, kā izmantot OpenAPI specifikāciju ar FlightPHP, lai izveidotu jūsu API, izmantojot API pirmo pieeju. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Bloga ieraksts, ko uzrakstījis Daniels Šreibers par to, kā izmantot OpenAPI specifikāciju ar FlightPHP, lai izveidotu jūsu API, izmantojot API pirmo pieeju. - [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ir lielisks rīks, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. To ir ļoti viegli izmantot, un to var pielāgot jūsu vajadzībām. Šī ir PHP bibliotēka, lai palīdzētu ģenerēt Swagger dokumentāciju. ## Lietojumprogrammas veiktspējas uzraudzība (APM) -Lietojumprogrammas veiktspējas uzraudzība (APM) ir izšķiroša jebkurai lietojumprogrammai. Tā palīdz jums saprast, kā darbojas jūsu lietojumprogramma un kur ir pudeles kakli. Ir vairāki APM rīki, ko var izmantot ar Flight. +Lietojumprogrammas veiktspējas uzraudzība (APM) ir izšķiroša jebkurai lietojumprogrammai. Tā palīdz saprast, kā jūsu lietojumprogramma darbojas un kur ir pudeles kakli. Ir vairāki APM rīki, ko var izmantot ar Flight. - oficiāls [flightphp/apm](/awesome-plugins/apm) - Flight APM ir vienkārša APM bibliotēka, ko var izmantot, lai uzraudzītu jūsu Flight lietojumprogrammas. To var izmantot, lai uzraudzītu jūsu lietojumprogrammas veiktspēju un palīdzētu identificēt pudeles kaklus. ## Async -Flight jau ir ātrs ietvars, bet, pievienojot tam turbīnas dzinēju, viss kļūst jautrāks (un izaicinošāks)! +Flight jau ir ātrs ietvars, bet pievienojot tam turbīnas dzinēju, viss kļūst jautrāks (un izaicināmāks)! -- [flightphp/async](/awesome-plugins/async) - Oficiālā Flight Async bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot asinhrono apstrādi jūsu lietojumprogrammai. Tā izmanto Swoole/Openswoole zem kapota, lai nodrošinātu vienkāršu un efektīvu veidu, kā palaist uzdevumus asinhroni. +- [flightphp/async](/awesome-plugins/async) - Oficiālā Flight Async bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot asinhrono apstrādi jūsu lietojumprogrammai. Tā izmanto Swoole/Openswoole zem pārsega, lai nodrošinātu vienkāršu un efektīvu veidu, kā palaist uzdevumus asinhroni. -## Autorizācija/Atslēgas +## Autorizācija/Atļaujas Autorizācija un atļaujas ir izšķirošas jebkurai lietojumprogrammai, kas prasa kontroles, lai noteiktu, kas var piekļūt kam. @@ -30,40 +30,40 @@ Autorizācija un atļaujas ir izšķirošas jebkurai lietojumprogrammai, kas pra Kešošana ir lielisks veids, kā paātrināt jūsu lietojumprogrammu. Ir vairākas kešošanas bibliotēkas, ko var izmantot ar Flight. -- oficiāls [flightphp/cache](/awesome-plugins/php-file-cache) - Gaisīga, vienkārša un neatkarīga PHP failā kešošanas klase +- oficiāls [flightphp/cache](/awesome-plugins/php-file-cache) - Viegls, vienkāršs un neatkarīgs PHP failu kešošanas klase ## CLI CLI lietojumprogrammas ir lielisks veids, kā mijiedarboties ar jūsu lietojumprogrammu. Jūs varat izmantot tās, lai ģenerētu kontrolierus, parādītu visas maršrutus un vairāk. -- oficiāls [flightphp/runway](/awesome-plugins/runway) - Runway ir CLI lietojumprogramma, kas palīdz jums pārvaldīt jūsu Flight lietojumprogrammas. +- oficiāls [flightphp/runway](/awesome-plugins/runway) - Runway ir CLI lietojumprogramma, kas palīdz pārvaldīt jūsu Flight lietojumprogrammas. ## Sīkfaili -Sīkfaili ir lielisks veids, kā uzglabāt mazus datu gabaliņus klienta pusē. Tos var izmantot, lai uzglabātu lietotāja preferences, lietojumprogrammas iestatījumus un vairāk. +Sīkfaili ir lielisks veids, kā uzglabāt mazas datu daļas klienta pusē. Tos var izmantot, lai uzglabātu lietotāja preferences, lietojumprogrammas iestatījumus un vairāk. -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie ir PHP bibliotēka, kas nodrošina vienkāršu un efektīvu veidu, kā pārvaldīt sīkfaiļus. +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie ir PHP bibliotēka, kas nodrošina vienkāršu un efektīvu veidu, kā pārvaldīt sīkfaius. -## Kļūdu meklēšana +## Kļūdu labošana -Kļūdu meklēšana ir izšķiroša, kad jūs izstrādājat savā lokālajā vidē. Ir dažas spraudņi, kas var uzlabot jūsu kļūdu meklēšanas pieredzi. +Kļūdu labošana ir izšķiroša, kad jūs attīstāt savā lokālajā vidē. Ir daži spraudņi, kas var uzlabot jūsu kļūdu labošanas pieredzi. -- [tracy/tracy](/awesome-plugins/tracy) - Šis ir pilnvērtīgs kļūdu apstrādātājs, ko var izmantot ar Flight. Tam ir vairāki paneļi, kas var palīdzēt jums kļūdu meklēšanā jūsu lietojumprogrammā. To ir arī ļoti viegli paplašināt un pievienot savus paneļus. -- oficiāls [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Izmantojot ar [Tracy](/awesome-plugins/tracy) kļūdu apstrādātāju, šis spraudnis pievieno dažus papildu paneļus, lai palīdzētu ar kļūdu meklēšanu tieši Flight projektiem. +- [tracy/tracy](/awesome-plugins/tracy) - Šis ir pilnvērtīgs kļūdu apstrādātājs, ko var izmantot ar Flight. Tam ir vairāki paneļi, kas var palīdzēt labot kļūdas jūsu lietojumprogrammā. To ir arī ļoti viegli paplašināt un pievienot savus paneļus. +- oficiāls [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Izmantojot ar [Tracy](/awesome-plugins/tracy) kļūdu apstrādātāju, šis spraudnis pievieno dažus papildu paneļus, lai palīdzētu ar kļūdu labošanu tieši Flight projektiem. ## Datubāzes -Datubāzes ir kodols lielākajai daļai lietojumprogrammu. Tā ir veids, kā uzglabāt un izgūt datus. Dažas datubāzes bibliotēkas ir vienkārši apvalki vaicājumu rakstīšanai, bet dažas ir pilnvērtīgas ORM. +Datubāzes ir kodols lielākajai daļai lietojumprogrammu. Tādējādi jūs uzglabājat un izgūstat datus. Dažas datubāzu bibliotēkas ir tikai apvalki vaicājumu rakstīšanai, bet dažas ir pilnvērtīgas ORM. - oficiāls [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Oficiālais Flight PDO apvalks, kas ir daļa no kodola. Šis ir vienkāršs apvalks, lai palīdzētu vienkāršot vaicājumu rakstīšanas un izpildes procesu. Tas nav ORM. -- oficiāls [flightphp/active-record](/awesome-plugins/active-record) - Oficiālā Flight ActiveRecord ORM/Mapper. Lieliska maza bibliotēka, lai viegli izgūtu un uzglabātu datus jūsu datubāzē. +- oficiāls [flightphp/active-record](/awesome-plugins/active-record) - Oficiālā Flight ActiveRecord ORM/Mapper. Lieliska maza bibliotēka vieglai datu izgūšanai un uzglabāšanai jūsu datubāzē. - [byjg/php-migration](/awesome-plugins/migrations) - Spraudnis, lai sekotu visām datubāzes izmaiņām jūsu projektā. ## Šifrēšana -Šifrēšana ir izšķiroša jebkurai lietojumprogrammai, kas uzglabā sensitīvus datus. Datu šifrēšana un dešifrēšana nav pārāk grūti, bet pareiza šifrēšanas atslēgas uzglabāšana [var](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [būt](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [grūti](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Visnozīmīgākais ir nekad neuzglabāt jūsu šifrēšanas atslēgu publiskā direktorijā vai apņemt to jūsu koda repozitorijā. +Šifrēšana ir izšķiroša jebkurai lietojumprogrammai, kas uzglabā sensitīvus datus. Datu šifrēšana un atšifrēšana nav pārāk grūta, bet pareiza šifrēšanas atslēgas uzglabāšana [var](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [būt](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [grūta](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Visnozīmīgākais ir nekad neuzglabāt jūsu šifrēšanas atslēgu publiskā direktorijā vai neiekļaut to jūsu koda repozitorijā. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Šī ir bibliotēka, ko var izmantot, lai šifrētu un dešifrētu datus. Sākšana un palaišana ir diezgan vienkārša, lai sāktu šifrēt un dešifrēt datus. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - Šī ir bibliotēka, ko var izmantot, lai šifrētu un atšifrētu datus. Sākšana ir diezgan vienkārša, lai sāktu šifrēt un atšifrēt datus. ## Darbu rinda @@ -73,25 +73,25 @@ Darbu rindas ir patiešām noderīgas, lai asinhroni apstrādātu uzdevumus. Tas ## Sesija -Sesijas nav īsti noderīgas API, bet, veidojot tīmekļa lietojumprogrammu, sesijas var būt izšķirošas, lai uzturētu stāvokli un pieteikšanās informāciju. +Sesijas nav īsti noderīgas API, bet veidojot tīmekļa lietojumprogrammu, sesijas var būt izšķirošas stāvokļa un pieteikšanās informācijas uzturēšanai. - oficiāls [flightphp/session](/awesome-plugins/session) - Oficiālā Flight Session bibliotēka. Šī ir vienkārša sesijas bibliotēka, ko var izmantot, lai uzglabātu un izgūtu sesijas datus. Tā izmanto PHP iebūvēto sesijas apstrādi. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (nebloķējošs, zibspuldze, segments, sesijas šifrēšana). Izmanto PHP open_ssl izvēles šifrēšanai/dešifrēšanai sesijas datiem. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (neblokējošs, zibspuldze, segments, sesijas šifrēšana). Izmanto PHP open_ssl opcionālai sesijas datu šifrēšanai/atšifrēšanai. ## Veidnes -Veidnes ir kodols jebkurai tīmekļa lietojumprogrammai ar lietotāja interfeisu. Ir vairāki veidņu dzinēji, ko var izmantot ar Flight. +Veidnes ir kodols jebkurai tīmekļa lietojumprogrammai ar UI. Ir vairāki veidņu dzinēji, ko var izmantot ar Flight. -- novecojis [flightphp/core View](/learn#views) - Šis ir ļoti pamata veidņu dzinējs, kas ir daļa no kodola. Nav ieteicams izmantot, ja jums ir vairāk nekā pāris lapas jūsu projektā. -- [latte/latte](/awesome-plugins/latte) - Latte ir pilnvērtīgs veidņu dzinējs, ko ir ļoti viegli izmantot un kas jūtas tuvāk PHP sintaksei nekā Twig vai Smarty. To ir arī ļoti viegli paplašināt un pievienot savus filtrus un funkcijas. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate ir spēcīgs PHP veidņu dzinējs ar resursu kompilāciju, veidnes mantošanu un mainīgo apstrādi. Funkcijas ietver automātisku CSS/JS minimizāciju, kešošanu, Base64 kodēšanu un izvēles Flight PHP ietvara integrāciju. +- novecojis [flightphp/core View](/learn#views) - Šis ir ļoti pamata veidņu dzinējs, kas ir daļa no kodola. Nav ieteicams izmantot, ja jūsu projektā ir vairāk nekā pāris lapas. +- [latte/latte](/awesome-plugins/latte) - Latte ir pilnvērtīgs veidņu dzinējs, ko ir ļoti viegli izmantot un tas šķiet tuvāks PHP sintaksei nekā Twig vai Smarty. To ir arī ļoti viegli paplašināt un pievienot savus filtrus un funkcijas. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate ir jaudīgs PHP veidņu dzinējs ar resursu kompilāciju, veidnes mantojumu un mainīgo apstrādi. Funkcijas ietver automātisku CSS/JS minimizāciju, kešošanu, Base64 kodēšanu un opcionālu Flight PHP ietvara integrāciju. ## WordPress integrācija -Vai vēlaties izmantot Flight savā WordPress projektā? Ir ērts spraudnis tam! +Vai vēlaties izmantot Flight savā WordPress projektā? Tam ir ērts spraudnis! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Šis WordPress spraudnis ļauj palaist Flight tieši blakus WordPress. Tas ir ideāli, lai pievienotu pielāgotus API, mikroservisu vai pat pilnas lietojumprogrammas jūsu WordPress vietnē, izmantojot Flight ietvaru. Ļoti noderīgi, ja vēlaties labāko no abām pasaulēm! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Šis WordPress spraudnis ļauj palaist Flight tieši blakus WordPress. Tas ir ideāls, lai pievienotu pielāgotus API, mikroservisu vai pat pilnvērtīgas lietojumprogrammas jūsu WordPress vietnē, izmantojot Flight ietvaru. Ļoti noderīgi, ja vēlaties labāko no abām pasaulēm! ## Iesaiste -Vai jums ir spraudnis, ko vēlaties dalīties? Iesniedziet pieprasījumu, lai pievienotu to sarakstam! \ No newline at end of file +Vai jums ir spraudnis, ko vēlaties dalīties? Iesniedziet pieprasījumu pēc vilkšanas, lai pievienotu to sarakstam! \ No newline at end of file diff --git a/content/v3/lv/awesome-plugins/comment_template.md b/content/v3/lv/awesome-plugins/comment_template.md index d83f927b..480c6ac0 100644 --- a/content/v3/lv/awesome-plugins/comment_template.md +++ b/content/v3/lv/awesome-plugins/comment_template.md @@ -1,6 +1,6 @@ # CommentTemplate -[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) ir jaudīgs PHP veidņu dz motor ar resursu kompilāciju, veidņu mantojumu un mainīgo apstrādi. Tas nodrošina vienkāršu, bet elastīgu veidu, kā pārvaldīt veidnes ar iebūvētu CSS/JS minimizāciju un kešošanu. +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) ir jaudīgs PHP veidņu dzinējs ar resursu kompilāciju, veidņu mantojumu un mainīgo apstrādi. Tas nodrošina vienkāršu, bet elastīgu veidu, kā pārvaldīt veidnes ar iebūvētu CSS/JS minimizāciju un kešošanu. ## Funkcijas @@ -10,7 +10,7 @@ - **Base64 kodēšana**: Iekšējie resursi kā datu URI - **Flight Framework integrācija**: Neobligātā integrācija ar Flight PHP framework -## Instalācija +## Instalēšana Instalējiet ar composer. @@ -20,7 +20,7 @@ composer require knifelemon/comment-template ## Pamata konfigurācija -Ir daži pamata konfigurācijas varianti, lai sāktu darbu. Jūs varat lasīt vairāk par tiem [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate). +Ir dažas pamata konfigurācijas opcijas, lai sāktu. Vairāk par tām var lasīt [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate). ### 1. metode: Izmantojot atgriezeniskās saites funkciju @@ -33,14 +33,14 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Saknes direktorijs (kur atrodas index.php) - jūsu tīmekļa lietojumprogrammas dokumentu sakne + // Saknes direktorija (kur ir index.php) - jūsu tīmekļa lietojumprogrammas dokumentu sakne $engine->setPublicPath(__DIR__); - // Veidņu failu direktorijs - atbalsta relatīvos un absolūtos ceļus - $engine->setSkinPath('views'); // Relatīvs pret publisko ceļu + // Veidņu failu direktorija - atbalsta gan relatīvās, gan absolūtās ceļus + $engine->setSkinPath('views'); // Relatīvi pret publisko ceļu - // Kur tiks glabāti kompilētie resursi - atbalsta relatīvos un absolūtos ceļus - $engine->setAssetPath('assets'); // Relatīvs pret publisko ceļu + // Kur tiks glabāti kompilētie resursi - atbalsta gan relatīvās, gan absolūtās ceļus + $engine->setAssetPath('assets'); // Relatīvi pret publisko ceļu // Veidnes faila paplašinājums $engine->setFileExtension('.php'); @@ -51,7 +51,7 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` -### 2. metode: Izmantojot konstruktoras parametrus +### 2. metode: Izmantojot konstruktoru parametrus ```php register('view', Engine::class, [ - __DIR__, // publicPath - saknes direktorijs (kur atrodas index.php) + __DIR__, // publicPath - saknes direktorija (kur ir index.php) 'views', // skinPath - veidņu ceļš (atbalsta relatīvos/absolūtos) 'assets', // assetPath - kompilēto resursu ceļš (atbalsta relatīvos/absolūtos) '.php' // fileExtension - veidnes faila paplašinājums @@ -74,19 +74,19 @@ $app->map('render', function(string $template, array $data) use ($app): void { }); ``` -## Ceļa konfigurācija +## Ceļu konfigurācija -CommentTemplate nodrošina inteliģentu ceļu apstrādi relatīvajiem un absolūtajiem ceļiem: +CommentTemplate nodrošina inteliģentu ceļu apstrādi gan relatīvajiem, gan absolūtajiem ceļiem: ### Publiskais ceļš -**Publiskais ceļš** ir jūsu tīmekļa lietojumprogrammas saknes direktorijs, parasti tur, kur atrodas `index.php`. Šis ir dokumentu sakne, no kuras tīmekļa serveri apkalpo failus. +**Publiskais ceļš** ir jūsu tīmekļa lietojumprogrammas saknes direktorija, parasti tur, kur atrodas `index.php`. Tas ir dokumentu saknes ceļš, no kura tīmekļa serveri pasniedz failus. ```php -// Piemērs: ja jūsu index.php atrodas /var/www/html/myapp/index.php -$template->setPublicPath('/var/www/html/myapp'); // Saknes direktorijs +// Piemērs: ja jūsu index.php ir /var/www/html/myapp/index.php +$template->setPublicPath('/var/www/html/myapp'); // Saknes direktorija -// Windows piemērs: ja jūsu index.php atrodas C:\xampp\htdocs\myapp\index.php +// Windows piemērs: ja jūsu index.php ir C:\xampp\htdocs\myapp\index.php $template->setPublicPath('C:\\xampp\\htdocs\\myapp'); ``` @@ -96,7 +96,7 @@ Veidņu ceļš atbalsta gan relatīvos, gan absolūtos ceļus: ```php $template = new Engine(); -$template->setPublicPath('/var/www/html/myapp'); // Saknes direktorijs (kur atrodas index.php) +$template->setPublicPath('/var/www/html/myapp'); // Saknes direktorija (kur ir index.php) // Relatīvie ceļi - automātiski apvienoti ar publisko ceļu $template->setSkinPath('views'); // → /var/www/html/myapp/views/ @@ -135,21 +135,21 @@ $template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ ``` -**Viedā ceļa noteikšana:** +**Inteliģenta ceļu noteikšana:** -- **Relatīvie ceļi**: Bez sākuma atdalītājiem (`/`, `\`) vai disku burtiem -- **Unix absolūtie**: Sākas ar `/` (piem. `/var/www/assets`) -- **Windows absolūtie**: Sākas ar disku burtu (piem. `C:\www`, `D:/assets`) -- **UNC ceļi**: Sākas ar `\\` (piem. `\\server\share`) +- **Relatīvie ceļi**: Nav vadītājsimbolu (`/`, `\`) vai disketes burtiem +- **Unix absolūtie**: Sākas ar `/` (piem., `/var/www/assets`) +- **Windows absolūtie**: Sākas ar diska burtu (piem., `C:\www`, `D:/assets`) +- **UNC ceļi**: Sākas ar `\\` (piem., `\\server\share`) **Kā tas darbojas:** -- Visi ceļi tiek automātiski atrisināti, pamatojoties uz tipu (relatīvs vs absolūts) +- Visi ceļi tiek automātiski atrisināti, balstoties uz tipu (relatīvs pret absolūto) - Relatīvie ceļi tiek apvienoti ar publisko ceļu -- `@css` un `@js` izveido minimizētus failus šeit: `{resolvedAssetPath}/css/` vai `{resolvedAssetPath}/js/` +- `@css` un `@js` izveido minimizētus failus: `{resolvedAssetPath}/css/` vai `{resolvedAssetPath}/js/` - `@asset` kopē atsevišķus failus uz: `{resolvedAssetPath}/{relativePath}` -- `@assetDir` kopē direktorijus uz: `{resolvedAssetPath}/{relativePath}` -- Viedā kešošana: faili tiek kopēti tikai tad, ja avots ir jaunāks nekā mērķis +- `@assetDir` kopē direktorijas uz: `{resolvedAssetPath}/{relativePath}` +- Inteliģenta kešošana: faili tiek kopēti tikai tad, kad avots ir jaunāks par mērķi ## Veidnes direktīvas @@ -182,7 +182,7 @@ Izmantojiet izkārtojumus, lai izveidotu kopīgu struktūru: #### CSS faili ```html - + ``` #### JavaScript faili @@ -195,19 +195,20 @@ CommentTemplate atbalsta dažādas JavaScript ielādes stratēģijas: - - - + + + ``` #### Resursu direktīvas CSS/JS failos -CommentTemplate apstrādā arī resursu direktīvas CSS un JavaScript failos kompilācijas laikā: +CommentTemplate arī apstrādā resursu direktīvas CSS un JavaScript failos kompilācijas laikā: **CSS piemērs:** ```css /* Jūsu CSS failos */ -/* @font-face { +/* Fontu definīcijas */ +@font-face { font-family: 'CustomFont'; src: url('') format('woff2'); } @@ -230,11 +231,11 @@ const imageData = ''; #### Base64 kodēšana ```html - + ``` ** Piemērs: ** ```html - + Logo
          Mazs ikona kā fons @@ -243,27 +244,27 @@ const imageData = ''; #### Resursu kopēšana ```html - - + + ``` ** Piemērs: ** ```html - + Hero Banner Lejupielādēt Brošūru - + ``` ### Veidnes iekļaušana ```html - + ``` ** Piemērs: ** ```html - +
          @@ -288,46 +289,46 @@ const imageData = ''; #### Mainīgo filtri ```html -{$title|upper} -{$content|lower} -{$html|striptag} -{$text|escape} -{$multiline|nl2br} -{$html|br2nl} -{$description|trim} -{$subject|title} +{$title|upper} +{$content|lower} +{$html|striptag} +{$text|escape} +{$multiline|nl2br} +{$html|br2nl} +{$description|trim} +{$subject|title} ``` #### Mainīgo komandas ```html -{$title|default=Default Title} -{$name|concat= (Admin)} +{$title|default=Default Title} +{$name|concat= (Admin)} ``` -#### Ķēdīt vairākus filtrus +#### Mainīgo komandas ```html -{$content|striptag|trim|escape} +{$content|striptag|trim|escape} ``` ### Komentāri -Veidnes komentāri tiek pilnībā noņemti no izvades un neparādās gala HTML: +Veidnes komentāri tiek pilnībā noņemti no izvades un neparādīsies galīgajā HTML: ```html -{* Šis ir vienas līnijas veidnes komentārs *} +{* Tas ir vienrindas veidnes komentārs *} {* - Šis ir daudzrindas + Tas ir vairākrindu veidnes komentārs - kas aptver vairākas līnijas + kas aptver vairākas rindas *}

          {$title}

          -{* Atkļūdošanas komentārs: pārbauda vai title mainīgais darbojas *} +{* Debug komentārs: pārbauda, vai title mainīgais darbojas *}

          {$content}

          ``` -**Piezīme**: Veidnes komentāri `{* ... *}` atšķiras no HTML komentāriem ``. Veidnes komentāri tiek noņemti apstrādes laikā un nekad nesasniedz pārlūkprogrammu. +**Piezīme**: Veidnes komentāri `{* ... *}` atšķiras no HTML komentāriem ``. Veidnes komentāri tiek noņemti apstrādes laikā un nekad nenonāk pārlūkprogrammā. ## Piemēra projekta struktūra diff --git a/content/v3/lv/awesome-plugins/runway.md b/content/v3/lv/awesome-plugins/runway.md index 05fc12b3..5fc12ef6 100644 --- a/content/v3/lv/awesome-plugins/runway.md +++ b/content/v3/lv/awesome-plugins/runway.md @@ -1,12 +1,12 @@ -# Lidmašīnas +# Runway -Lidmašīnas ir CLI lietotne, kas palīdz pārvaldīt jūsu Flight lietojumprogrammas. Tā var ģenerēt kontrolierus, parādīt visus maršrutus un vairāk. Tā balstīta uz lielisko [adhocore/php-cli](https://github.com/adhocore/php-cli) bibliotēku. +Runway ir CLI lietojumprogramma, kas palīdz pārvaldīt jūsu Flight lietojumprogrammas. Tā var ģenerēt kontrolierus, parādīt visas maršrutus un vairāk. Tā balstās uz izcilo [adhocore/php-cli](https://github.com/adhocore/php-cli) bibliotēku. -Uzklikšķiniet [šeit](https://github.com/flightphp/runway), lai skatītu kodu. +Noklikšķiniet [šeit](https://github.com/flightphp/runway), lai skatītu kodu. -## Instalēšana +## Uzstādīšana -Instalējiet to ar komponistu. +Uzstādiet ar composer. ```bash composer require flightphp/runway @@ -14,16 +14,16 @@ composer require flightphp/runway ## Pamata konfigurācija -Pirmo reizi palaižot Lidmašīnas, tā vadīs jūs caur iestatīšanas procesu un izveidos `.runway.json` konfigurācijas failu jūsu projekta saknē. Šajā failā būs dažas nepieciešamās konfigurācijas, lai Lidmašīnas pareizi darbotos. +Pirmo reizi palaižot Runway, tā vadīs jūs cauri uzstādīšanas procesam un izveidos `.runway.json` konfigurācijas failu jūsu projekta saknes direktorijā. Šis fails saturēs dažas nepieciešamas konfigurācijas, lai Runway darbotos pareizi. -## Lietojums +## Lietošana -Lidmašīnā ir vairākas komandas, ar kurām varat pārvaldīt savu Flight lietojumprogrammu. Ir divi viegli veidi, kā izmantot Lidmašīnas. +Runway ir vairākas komandas, kuras jūs varat izmantot, lai pārvaldītu jūsu Flight lietojumprogrammu. Ir divi viegli veidi, kā izmantot Runway. -1. Ja izmantojat ietvaru projektu, varat izpildīt `php runway [komanda]` no savu projekta saknes. -1. Ja izmantojat Lidmašīnas kā paketi, kas instalēts ar komponistu, varat izpildīt `vendor/bin/runway [komanda]` no savu projekta saknes. +1. Ja jūs izmantojat skeletu projektu, jūs varat palaidīt `php runway [command]` no jūsu projekta saknes. +1. Ja jūs izmantojat Runway kā paketi, kas uzstādīta caur composer, jūs varat palaidīt `vendor/bin/runway [command]` no jūsu projekta saknes. -Lai iegūtu papildinformāciju par jebkuru komandu, jūs varat padot `--help` karodziņa. +Jebkurai komandai jūs varat pievienot `--help` karodziņu, lai iegūtu vairāk informācijas par to, kā izmantot komandu. ```bash php runway routes --help @@ -33,21 +33,21 @@ php runway routes --help ### Ģenerēt kontrolieri -Balstoties uz konfigurāciju jūsu `.runway.json` failā, noklusējuma atrašanās vieta jums ģenerēs kontrolieri `app/controllers/` direktorijā. +Pamatojoties uz konfigurāciju jūsu `.runway.json` failā, noklusējuma atrašanās vieta ģenerēs kontrolieri jums `app/controllers/` direktorijā. ```bash php runway make:controller MyController ``` -### Ģenerēt aktīvās ierakstu modeles +### Ģenerēt Active Record modeli -Balstoties uz konfigurāciju jūsu `.runway.json` failā, noklusējuma atrašanās vieta jums ģenerēs kontrolieri `app/records/` direktorijā. +Pamatojoties uz konfigurāciju jūsu `.runway.json` failā, noklusējuma atrašanās vieta ģenerēs kontrolieri jums `app/records/` direktorijā. ```bash php runway make:record users ``` -Ja, piemēram, ir `users` tabula ar sekojošu shēmu: `id`, `name`, `email`, `created_at`, `updated_at`, fails līdzīgs sekojošajam tiks izveidots `app/records/UserRecord.php` failā: +Ja, piemēram, jums ir `users` tabula ar šādu shēmu: `id`, `name`, `email`, `created_at`, `updated_at`, fails, līdzīgs šim, tiks izveidots `app/records/UserRecord.php` failā: ```php $config JSON konfigurācija no .runway-config.json @@ -130,7 +130,7 @@ class ExampleCommand extends AbstractBaseCommand public function __construct(array $config) { parent::__construct('make:example', 'Izveidot piemēru dokumentācijai', $config); - $this->argument('', 'Smaida GIF nosaukums'); + $this->argument('', 'Smieklīgā gif nosaukums'); } /** @@ -138,17 +138,56 @@ class ExampleCommand extends AbstractBaseCommand * * @return void */ - public function execute(string $controller) + public function execute() { $io = $this->app()->io(); $io->info('Izveido piemēru...'); - // Kaut ko dariet šeit + // Dariet kaut ko šeit $io->ok('Piemērs izveidots!'); } } ``` -Skatiet [adhocore/php-cli Dokumentāciju](https://github.com/adhocore/php-cli), lai iegūtu vairāk informācijas par to, kā izveidot savas pielāgotas komandas savā Flight lietojumprogrammā! \ No newline at end of file +Skatiet [adhocore/php-cli Dokumentāciju](https://github.com/adhocore/php-cli), lai iegūtu vairāk informācijas par to, kā izveidot savas pielāgotas komandas savai Flight lietojumprogrammai! + +### Konfigurācija + +Ja nepieciešams pielāgot konfigurāciju Runway, jūs varat izveidot `.runway-config.json` failu jūsu projekta saknes direktorijā. Zemāk ir dažas papildu konfigurācijas, kuras jūs varat iestatīt: + +```js +{ + + // Šī ir vieta, kur atrodas jūsu lietojumprogrammas direktorija + "app_root": "app/", + + // Šī ir direktorija, kur atrodas jūsu saknes indeksa fails + "index_root": "public/", + + // Šie ir ceļi uz citu projektu saknēm + "root_paths": [ + "/home/user/different-project", + "/var/www/another-project" + ], + + // Bāzes ceļi visticamāk nav jākonfigurē, bet tas ir šeit, ja vēlaties + "base_paths": { + "/includes/libs/vendor", // ja jums ir patiesi unikāls ceļš uz jūsu vendor direktoriju vai kaut ko + }, + + // Galīgie ceļi ir vietas projektā, kur meklēt komandu failus + "final_paths": { + "src/diff-path/commands", + "app/module/admin/commands", + }, + + // Ja vēlaties pievienot pilnu ceļu, dariet to (absolūts vai relatīvs pret projektu sakni) + "paths": [ + "/home/user/different-project/src/diff-path/commands", + "/var/www/another-project/app/module/admin/commands", + "app/my-unique-commands" + ] +} +``` \ No newline at end of file diff --git a/content/v3/lv/examples.md b/content/v3/lv/examples.md index d1bbd8be..4c146408 100644 --- a/content/v3/lv/examples.md +++ b/content/v3/lv/examples.md @@ -1,38 +1,39 @@ -# Vai tev vajadzīga ātra uzsākšana? +# Vai ātri sākt? -Tev ir divas iespējas sākt darbu ar jaunu Flight projektu: +Jums ir divas opcijas, lai sāktu darbu ar jaunu Flight projektu: -- [Pilna Skeleton Boilerplate](https://github.com/flightphp/skeleton): Pilnīgāks piemērs ar kontrolieriem un skatiem. -- [Vienfaila Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Viena faila, kas ietver visu, kas tev vajadzīgs, lai palaistu savu lietotni vienā vienkāršā failā. +- [Pilns Skelets Boilerplate](https://github.com/flightphp/skeleton): Pilnīgāks piemērs ar kontrolieriem un skatiem. +- [Vienkāršs Fails Skelets Boilerplate](https://github.com/flightphp/skeleton-simple): Viens fails, kas ietver visu, kas nepieciešams, lai palaistu jūsu lietojumprogrammu vienā vienkāršā failā. Kopienas sniegtie piemēri: - [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP ar Laravel direktorijām, ar PHP rīkiem + GH Actions - [fleact](https://github.com/flightphp/fleact) - FlightPHP starter komplekts ar ReactJS integrāciju. - [flastro](https://github.com/flightphp/flastro) - FlightPHP starter komplekts ar Astro integrāciju. -- [velt](https://github.com/flightphp/velt) - Velt ir ātrs un viegls Svelte starter veidne ar FlightPHP backend. +- [velt](https://github.com/flightphp/velt) - Velt ir ātrs un viegls Svelte starter veidne ar FlightPHP aizmuguri. -## Vai tev vajadzīga kāda iedvesma? +## Vai vajag iedvesmu? -Lai gan šie nav oficiāli atbalstīti no Flight komandas puses, tie var dot tev idejas, kā strukturēt savus paša projektus, kas būvēti ar Flight! +Lai gan šie nav oficiāli atbalstīti no Flight komandas puses, tie var dot jums idejas, kā strukturēt savus pašu projektus, kas izveidoti ar Flight! -- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify ir vienas lapas lietotne, kas savieno pasākumu organizatorus ar dalībniekiem. Būvēta ar PHP (FlightPHP), JavaScript un MySQL, tā ietver JWT autentifikāciju, pasākumu pārvaldību un RESTful API dokumentāciju, izmantojot OpenAPI. -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental ir vienas lapas, mobilajām ierīcēm draudzīga automašīnu nomas tīmekļa lietotne, būvēta ar PHP (FlightPHP), JavaScript un MySQL. Tā atbalsta lietotāju reģistrāciju, pārlūkošanu un automašīnu rezervēšanu, kamēr administratori var pārvaldīt automašīnas, lietotājus un rezervācijas. Lietotnē ir REST API, JWT autentifikācija un responsīvs dizains modernai nomas pieredzei. +- [ASC REST API Pareizrakstības pārbaudītājs](https://github.com/AlMosahih-ASC/asc-api-sample) - Viegls REST API arabu valodas pareizrakstības pārbaudei, izveidots ar FlightPHP un ArPHP bibliotēku. Šis API nodrošina arabu teksta pareizrakstības pārbaudes iespējas, tostarp nepareizi uzrakstītu vārdu atklāšanu un labošanas ieteikumus. +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify ir vienas lapas lietojumprogramma, kas savieno pasākumu organizētājus ar dalībniekiem. Izveidots ar PHP (FlightPHP), JavaScript un MySQL, tas ietver JWT autentifikāciju, pasākumu pārvaldību un RESTful API dokumentāciju, izmantojot OpenAPI. +- [Ivox Auto Noma](https://github.com/najtms/introductionToWeb) - Ivox Auto Noma ir vienas lapas, mobilajām ierīcēm draudzīga auto nomas tīmekļa lietojumprogramma, izveidota ar PHP (FlightPHP), JavaScript un MySQL. Tā atbalsta lietotāju reģistrāciju, pārlūkošanu un auto rezervēšanu, savukārt administratori var pārvaldīt auto, lietotājus un rezervācijas. Lietojumprogrammā ir REST API, JWT autentifikācija un atsaucīgs dizains modernai nomas pieredzei. - [Decay](https://github.com/boxybird/decay) - Flight v3 ar HTMX un SleekDB, viss par zombijiem! ([Demo](https://decay.andrewrhyand.com)) -- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 ar Middleware, kontrolieriem, Active Record un Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Vienkāršs CRUD API projekts, izmantojot Flight framework, kas nodrošina pamata struktūru jauniem lietotājiem, lai ātri izveidotu PHP lietotni ar CRUD operācijām un datubāzes savienojumu. Projekts demonstrē, kā izmantot Flight RESTful API izstrādei, padarot to par ideālu mācību rīku iesācējiem un noderīgu starter komplektu pieredzējušākiem izstrādātājiem. -- [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 -- [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 -- [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) -- [Example Wiki](https://github.com/Skayo/FlightWiki) -- [The IT-Innovator PHP Framework Application](https://github.com/itinnovator/myphp-app) -- [LittleEducationalCMS (Spanish)](https://github.com/casgin/LittleEducationalCMS) -- [Italian Yellow Pages API](https://github.com/chiccomagnus/PGAPI) -- [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) -- [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) -- [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Ražošanai gatavs autentifikācijas framework, kas ietaupa nedēļas izstrādes laika. Ietver uzņēmuma līmeņa drošību: 2FA/TOTP, LDAP integrāciju, Azure SSO, inteliģentu ātruma ierobežošanu, sesijas pirkstu nospiedumu, aizsardzību pret brutālu spēku, drošības analītikas paneli, visaptverošu audita žurnālošanu un granulētu lomu balstītu piekļuves kontroli. - -## Vai vēlies dalīties ar savu paša piemēru? - -Ja tev ir projekts, ko vēlies dalīt, lūdzu, iesniedz pull request, lai to pievienotu šim sarakstam! \ No newline at end of file +- [Flight Piemērs Blogs](https://github.com/n0nag0n/flightphp-blog) - Flight v3 ar vidutājprogrammu, kontrolieriem, Active Record un Latte. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Vienkāršs CRUD API projekts, izmantojot Flight ietvaru, kas nodrošina pamata struktūru jauniem lietotājiem, lai ātri iestatītu PHP lietojumprogrammu ar CRUD operācijām un datubāzes savienojumu. Projekts demonstrē, kā izmantot Flight RESTful API izstrādei, padarot to par ideālu mācību rīku iesācējiem un noderīgu starter komplektu pieredzējušākiem izstrādātājiem. +- [Flight Skolas Pārvaldības Sistēma](https://github.com/krmu/FlightPHP_School) - Flight v3 +- [Paste Bin ar Komentāriem](https://github.com/n0nag0n/commie2) - Flight v3 +- [Pamata Skelets Lietojumprogramma](https://github.com/markhughes/flight-skeleton) +- [Piemērs Viki](https://github.com/Skayo/FlightWiki) +- [The IT-Innovator PHP Framework Lietojumprogramma](https://github.com/itinnovator/myphp-app) +- [LittleEducationalCMS (Spāņu)](https://github.com/casgin/LittleEducationalCMS) +- [Itāļu Dzelteno Lappušu API](https://github.com/chiccomagnus/PGAPI) +- [Vispārīga Satura Pārvaldības Sistēma (ar....ļoti maz dokumentācijas)](https://github.com/recepuncu/cms) +- [Mazs php ietvars balstīts uz Flight un medoo.](https://github.com/ycrao/tinyme) +- [Piemērs MVC Lietojumprogramma](https://github.com/paddypei/Flight-MVC) +- [Ražošanai gatavs Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Ražošanai gatavs autentifikācijas ietvars, kas ietaupa nedēļām ilgu izstrādi. Ietver uzņēmuma līmeņa drošību: 2FA/TOTP, LDAP integrācija, Azure SSO, inteliģenta ātruma ierobežošana, sesijas pirkstu nospiedumu, aizsardzība pret brutālu spēku, drošības analītikas panelis, visaptveroša auditēšanas žurnālošana un granulēta loma balstīta piekļuves kontrole. + +## Vai vēlaties Dalīties ar Savu Piemēru? + +Ja jums ir projekts, kuru vēlaties dalīt, lūdzu, iesniedziet pull request, lai to pievienotu šim sarakstam! \ No newline at end of file diff --git a/content/v3/pt/awesome-plugins/active_record.md b/content/v3/pt/awesome-plugins/active_record.md index 014e372c..7bdaf07a 100644 --- a/content/v3/pt/awesome-plugins/active_record.md +++ b/content/v3/pt/awesome-plugins/active_record.md @@ -1,6 +1,6 @@ # Flight Active Record -Um registro ativo é o mapeamento de uma entidade de banco de dados para um objeto PHP. Falando de forma simples, se você tiver uma tabela de usuários em seu banco de dados, você pode "traduzir" uma linha dessa tabela para uma classe `User` e um objeto `$user` em seu código. Veja [exemplo básico](#basic-example). +Um active record é um mapeamento de uma entidade de banco de dados para um objeto PHP. Falando de forma simples, se você tem uma tabela users no seu banco de dados, você pode "traduzir" uma linha dessa tabela para uma classe `User` e um objeto `$user` no seu código. Veja [exemplo básico](#basic-example). Clique [aqui](https://github.com/flightphp/active-record) para o repositório no GitHub. @@ -20,9 +20,9 @@ Agora você pode configurar uma nova classe para representar essa tabela: ```php /** - * Uma classe ActiveRecord é geralmente singular + * Uma classe ActiveRecord geralmente é singular * - * É altamente recomendável adicionar as propriedades da tabela como comentários aqui + * É altamente recomendado adicionar as propriedades da tabela como comentários aqui * * @property int $id * @property string $name @@ -31,7 +31,7 @@ Agora você pode configurar uma nova classe para representar essa tabela: class User extends flight\ActiveRecord { public function __construct($database_connection) { - // você pode configurá-la assim + // você pode definir assim parent::__construct($database_connection, 'users'); // ou assim parent::__construct($database_connection, null, [ 'table' => 'users']); @@ -39,7 +39,7 @@ class User extends flight\ActiveRecord { } ``` -Agora assista a mágica acontecer! +Agora veja a mágica acontecer! ```php // para sqlite @@ -55,24 +55,24 @@ $database_connection = mysqli_connect('localhost', 'username', 'password', 'test $user = new User($database_connection); $user->name = 'Bobby Tables'; -$user->password = password_hash('uma senha legal'); +$user->password = password_hash('some cool password'); $user->insert(); // ou $user->save(); echo $user->id; // 1 $user->name = 'Joseph Mamma'; -$user->password = password_hash('uma nova senha legal!!!'); +$user->password = password_hash('some cool password again!!!'); $user->insert(); -// não pode usar $user->save() aqui ou ele achará que é uma atualização! +// não pode usar $user->save() aqui ou ele pensará que é uma atualização! echo $user->id; // 2 ``` -E foi assim tão fácil adicionar um novo usuário! Agora que há uma linha de usuário no banco de dados, como você a extrai? +E foi tão fácil adicionar um novo usuário! Agora que há uma linha de usuário no banco de dados, como você a recupera? ```php -$user->find(1); // encontra id = 1 no banco de dados e o retorna. +$user->find(1); // encontre id = 1 no banco de dados e retorne-o. echo $user->name; // 'Bobby Tables' ``` @@ -82,17 +82,17 @@ E se você quiser encontrar todos os usuários? $users = $user->findAll(); ``` -E quanto a uma certa condição? +E com uma condição específica? ```php $users = $user->like('name', '%mamma%')->findAll(); ``` -Veja quanto é divertido isso? Vamos instalá-lo e começar! +Veja como isso é divertido? Vamos instalá-lo e começar! ## Instalação -Basta instalar com o Composer +Simplesmente instale com o Composer ```php composer require flightphp/active-record @@ -100,10 +100,10 @@ composer require flightphp/active-record ## Uso -Isso pode ser utilizado como uma biblioteca autônoma ou com o Framework PHP Flight. Totalmente a seu critério. +Isso pode ser usado como uma biblioteca independente ou com o Flight PHP Framework. Completamente com você. -### Autônomo -Basta garantir que você passe uma conexão PDO para o construtor. +### Independente +Apenas certifique-se de passar uma conexão PDO para o construtor. ```php $pdo_connection = new PDO('sqlite:test.db'); // isso é apenas um exemplo, você provavelmente usaria uma conexão de banco de dados real @@ -111,26 +111,26 @@ $pdo_connection = new PDO('sqlite:test.db'); // isso é apenas um exemplo, você $User = new User($pdo_connection); ``` -> Não quer sempre configurar sua conexão de banco de dados no construtor? Veja [Gerenciamento de Conexão de Banco de Dados](#database-connection-management) para outras ideias! +> Não quer sempre definir sua conexão de banco de dados no construtor? Veja [Gerenciamento de Conexão de Banco de Dados](#database-connection-management) para outras ideias! ### Registrar como um método no Flight -Se você estiver usando o Framework PHP Flight, pode registrar a classe ActiveRecord como um serviço, mas honestamente, você não precisa. +Se você estiver usando o Flight PHP Framework, você pode registrar a classe ActiveRecord como um serviço, mas honestamente não precisa. ```php Flight::register('user', 'User', [ $pdo_connection ]); -// então você pode usá-la assim em um controlador, uma função, etc. +// então você pode usá-lo assim em um controlador, uma função, etc. Flight::user()->find(1); ``` ## Métodos `runway` -[runway](/awesome-plugins/runway) é uma ferramenta CLI para o Flight que possui um comando personalizado para esta biblioteca. +[runway](/awesome-plugins/runway) é uma ferramenta CLI para Flight que tem um comando personalizado para esta biblioteca. ```bash # Uso -php runway make:record nome_da_tabela_do_banco_de_dados [nome_da_classe] +php runway make:record database_table_name [class_name] # Exemplo php runway make:record users @@ -158,11 +158,11 @@ namespace app\records; class UserRecord extends \flight\ActiveRecord { /** - * @var array $relations Defina os relacionamentos para o modelo + * @var array $relations Defina as relações para o modelo * https://docs.flightphp.com/awesome-plugins/active-record#relationships */ protected array $relations = [ - // 'nome_da_relação' => [ self::HAS_MANY, 'ClasseRelacionada', 'chave_estrangeira' ], + // 'relation_name' => [ self::HAS_MANY, 'RelatedClass', 'foreign_key' ], ]; /** @@ -180,15 +180,15 @@ class UserRecord extends \flight\ActiveRecord #### `find($id = null) : boolean|ActiveRecord` -Encontra um registro e atribui ao objeto atual. Se você passar um `$id` de algum tipo, ele realizará uma busca na chave primária com esse valor. Se nada for passado, ele apenas encontrará o primeiro registro na tabela. +Encontra um registro e o atribui ao objeto atual. Se você passar um `$id` de algum tipo, ele executará uma busca na chave primária com esse valor. Se nada for passado, ele simplesmente encontrará o primeiro registro na tabela. -Além disso, você pode passar outros métodos auxiliares para consultar sua tabela. +Adicionalmente, você pode passar outros métodos auxiliares para consultar sua tabela. ```php -// encontrar um registro com algumas condições previamente +// encontre um registro com algumas condições antes $user->notNull('password')->orderBy('id DESC')->find(); -// encontrar um registro por um id específico +// encontre um registro por um id específico $id = 123; $user->find($id); ``` @@ -203,7 +203,7 @@ $user->findAll(); #### `isHydrated(): boolean` (v0.4.0) -Retorna `true` se o registro atual tiver sido hidratado (buscado do banco de dados). +Retorna `true` se o registro atual foi hidratado (buscado do banco de dados). ```php $user->find(1); @@ -224,24 +224,24 @@ $user->insert(); ##### Chaves Primárias Baseadas em Texto -Se você tiver uma chave primária baseada em texto (como um UUID), pode definir o valor da chave primária antes de inserir de duas maneiras. +Se você tiver uma chave primária baseada em texto (como um UUID), você pode definir o valor da chave primária antes de inserir de uma de duas maneiras. ```php $user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]); -$user->uuid = 'algum-uuid'; +$user->uuid = 'some-uuid'; $user->name = 'demo'; $user->password = md5('demo'); $user->insert(); // ou $user->save(); ``` -ou você pode fazer com que a chave primária seja gerada automaticamente para você por meio de eventos. +ou você pode ter a chave primária gerada automaticamente para você através de eventos. ```php class User extends flight\ActiveRecord { public function __construct($database_connection) { parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]); - // você também pode definir a chave primária assim em vez do array acima. + // você também pode definir a primaryKey dessa maneira em vez do array acima. $this->primaryKey = 'uuid'; } @@ -251,9 +251,7 @@ class User extends flight\ActiveRecord { } ``` -Se você não definir a chave primária antes de inserir, ela será definida como o `rowid` e o -banco de dados a gerará para você, mas não persistirá porque esse campo pode não existir -em sua tabela. Por isso, é recomendável usar o evento para gerenciar isso automaticamente. +Se você não definir a chave primária antes de inserir, ela será definida como `rowid` e o banco de dados a gerará para você, mas não persistirá porque esse campo pode não existir na sua tabela. É por isso que é recomendado usar o evento para lidar com isso automaticamente. #### `update(): boolean|ActiveRecord` @@ -267,7 +265,7 @@ $user->update(); #### `save(): boolean|ActiveRecord` -Insere ou atualiza o registro atual no banco de dados. Se o registro tiver um id, ele atualizará; caso contrário, ele irá inserir. +Insere ou atualiza o registro atual no banco de dados. Se o registro tiver um id, ele atualizará, caso contrário, inserirá. ```php $user = new User($pdo_connection); @@ -276,7 +274,7 @@ $user->password = md5('demo'); $user->save(); ``` -**Nota:** Se você tiver relacionamentos definidos na classe, ele salvará recursivamente essas relações também, se foram definidas, instanciadas e possuem dados sujos para atualizar. (v0.4.0 e superior) +**Nota:** Se você tiver relações definidas na classe, ele salvará recursivamente essas relações também se elas tiverem sido definidas, instanciadas e tiverem dados sujos para atualizar. (v0.4.0 e acima) #### `delete(): boolean` @@ -287,7 +285,7 @@ $user->gt('id', 0)->orderBy('id desc')->find(); $user->delete(); ``` -Você também pode excluir vários registros executando uma pesquisa previamente. +Você também pode excluir múltiplos registros executando uma busca antes. ```php $user->like('name', 'Bob%')->delete(); @@ -300,32 +298,32 @@ Dados sujos referem-se aos dados que foram alterados em um registro. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); -// nada está "sujo" até esse ponto. +// nada está "sujo" até este ponto. -$user->email = 'test@example.com'; // agora o e-mail é considerado "sujo" pois foi alterado. +$user->email = 'test@example.com'; // agora o email é considerado "sujo" pois foi alterado. $user->update(); -// agora não há dados sujos porque foram atualizados e persistidos no banco de dados. +// agora não há dados sujos porque foi atualizado e persistido no banco de dados -$user->password = password_hash('nova_senha'); // agora isso é sujo -$user->dirty(); // passando nada limpará todas as entradas sujas. -$user->update(); // nada será atualizado porque nada foi capturado como sujo. +$user->password = password_hash()'newpassword'); // agora isso é sujo +$user->dirty(); // passar nada limpará todas as entradas sujas. +$user->update(); // nada será atualizado pois nada foi capturado como sujo. -$user->dirty([ 'name' => 'algo', 'password' => password_hash('uma senha diferente') ]); -$user->update(); // tanto nome quanto senha são atualizados. +$user->dirty([ 'name' => 'something', 'password' => password_hash('a different password') ]); +$user->update(); // tanto name quanto password são atualizados. ``` #### `copyFrom(array $data): ActiveRecord` (v0.4.0) -Este é um alias para o método `dirty()`. É um pouco mais claro o que você está fazendo. +Isso é um alias para o método `dirty()`. É um pouco mais claro o que você está fazendo. ```php -$user->copyFrom([ 'name' => 'algo', 'password' => password_hash('uma senha diferente') ]); -$user->update(); // tanto nome quanto senha são atualizados. +$user->copyFrom([ 'name' => 'something', 'password' => password_hash('a different password') ]); +$user->update(); // tanto name quanto password são atualizados. ``` #### `isDirty(): boolean` (v0.4.0) -Retorna `true` se o registro atual tiver sido alterado. +Retorna `true` se o registro atual foi alterado. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); @@ -335,15 +333,14 @@ $user->isDirty(); // true #### `reset(bool $include_query_data = true): ActiveRecord` -Redefine o registro atual para seu estado inicial. Isso é muito bom para usar em tipos de comportamento de loop. -Se você passar `true`, isso também redefinirá os dados da consulta usados para encontrar o objeto atual (comportamento padrão). +Redefine o registro atual para seu estado inicial. Isso é realmente bom para usar em comportamentos de loop. Se você passar `true`, ele também redefinirá os dados da consulta usados para encontrar o objeto atual (comportamento padrão). ```php $users = $user->greaterThan('id', 0)->orderBy('id desc')->find(); $user_company = new UserCompany($pdo_connection); foreach($users as $user) { - $user_company->reset(); // comece com uma folha limpa + $user_company->reset(); // comece com uma lousa limpa $user_company->user_id = $user->id; $user_company->company_id = $some_company_id; $user_company->insert(); @@ -352,12 +349,12 @@ foreach($users as $user) { #### `getBuiltSql(): string` (v0.4.1) -Depois de executar um método `find()`, `findAll()`, `insert()`, `update()`, ou `save()`, você pode obter o SQL que foi construído e usá-lo para fins de depuração. +Após executar um método `find()`, `findAll()`, `insert()`, `update()`, ou `save()`, você pode obter o SQL que foi construído e usá-lo para fins de depuração. ## Métodos de Consulta SQL #### `select(string $field1 [, string $field2 ... ])` -Você pode selecionar apenas algumas das colunas em uma tabela, se desejar (é mais eficiente em tabelas realmente largas com muitas colunas) +Você pode selecionar apenas algumas das colunas em uma tabela se quiser (é mais performático em tabelas muito largas com muitas colunas) ```php $user->select('id', 'name')->find(); @@ -373,7 +370,7 @@ $user->select('id', 'name')->from('user')->find(); #### `join(string $table_name, string $join_condition)` -Você pode até juntar a outra tabela no banco de dados. +Você pode até juntar com outra tabela no banco de dados. ```php $user->join('contacts', 'contacts.user_id = users.id')->find(); @@ -381,13 +378,13 @@ $user->join('contacts', 'contacts.user_id = users.id')->find(); #### `where(string $where_conditions)` -Você pode definir alguns argumentos where personalizados (não pode definir parâmetros nesta declaração where) +Você pode definir alguns argumentos where personalizados (você não pode definir params nesta declaração where) ```php $user->where('id=1 AND name="demo"')->find(); ``` -**Nota de Segurança** - Você pode ser tentado a fazer algo como `$user->where("id = '{$id}' AND name = '{$name}'")->find();`. Por favor, NÃO FAÇA ISSO!!! Isso é suscetível a ataques que são conhecidos como injeções de SQL. Existem muitos artigos online, por favor, pesquise "sql injection attacks php" e você encontrará muitos artigos sobre esse assunto. A maneira adequada de lidar com isso com esta biblioteca é, em vez desse método `where()`, você faria algo mais parecido com `$user->eq('id', $id)->eq('name', $name)->find();` Se você absolutamente precisa fazer isso, a biblioteca `PDO` possui `$pdo->quote($var)` para escapar para você. Somente após usar `quote()` você pode usá-lo em uma declaração `where()`. +**Nota de Segurança** - Você pode ser tentado a fazer algo como `$user->where("id = '{$id}' AND name = '{$name}'")->find();`. Por favor, NÃO FAÇA ISSO!!! Isso é suscetível a ataques conhecidos como Injeção de SQL. Há muitos artigos online, por favor pesquise "sql injection attacks php" e você encontrará muitos artigos sobre o assunto. A maneira adequada de lidar com isso com esta biblioteca é, em vez de usar este método `where()`, você faria algo como `$user->eq('id', $id)->eq('name', $name)->find();` Se você absolutamente tiver que fazer isso, a biblioteca `PDO` tem `$pdo->quote($var)` para escapá-lo para você. Somente após usar `quote()` você pode usá-lo em uma declaração `where()`. #### `group(string $group_by_statement)/groupBy(string $group_by_statement)` @@ -399,7 +396,7 @@ $user->select('COUNT(*) as count')->groupBy('name')->findAll(); #### `order(string $order_by_statement)/orderBy(string $order_by_statement)` -Classifique a consulta retornada de uma certa maneira. +Ordene a consulta retornada de uma certa maneira. ```php $user->orderBy('name DESC')->find(); @@ -407,7 +404,7 @@ $user->orderBy('name DESC')->find(); #### `limit(string $limit)/limit(int $offset, int $limit)` -Limite a quantidade de registros retornados. Se um segundo int for dado, será offset, limit como em SQL. +Limite a quantidade de registros retornados. Se um segundo int for dado, será offset, limit assim como no SQL. ```php $user->orderby('name DESC')->limit(0, 10)->findAll(); @@ -501,20 +498,20 @@ $user->between('id', [1, 2])->find(); ### Condições OR -É possível envolver suas condições em uma declaração OR. Isso é feito com o método `startWrap()` e `endWrap()` ou preenchendo o 3º parâmetro da condição após o campo e o valor. +É possível envolver suas condições em uma declaração OR. Isso é feito com os métodos `startWrap()` e `endWrap()` ou preenchendo o 3º parâmetro da condição após o campo e valor. ```php // Método 1 $user->eq('id', 1)->startWrap()->eq('name', 'demo')->or()->eq('name', 'test')->endWrap('OR')->find(); -// Isso será avaliado para `id = 1 AND (name = 'demo' OR name = 'test')` +// Isso avaliará como `id = 1 AND (name = 'demo' OR name = 'test')` // Método 2 $user->eq('id', 1)->eq('name', 'demo', 'OR')->find(); -// Isso será avaliado para `id = 1 OR name = 'demo'` +// Isso avaliará como `id = 1 OR name = 'demo'` ``` ## Relacionamentos -Você pode definir vários tipos de relacionamentos usando esta biblioteca. Você pode definir relacionamentos um->muitos e um->um entre tabelas. Isso requer uma configuração extra na classe previamente. +Você pode definir vários tipos de relacionamentos usando esta biblioteca. Você pode definir relacionamentos um-para-muitos e um-para-um entre tabelas. Isso requer um pouco de configuração extra na classe antes. Definir o array `$relations` não é difícil, mas adivinhar a sintaxe correta pode ser confuso. @@ -527,7 +524,7 @@ protected array $relations = [ self::HAS_ONE, // este é o tipo de relacionamento // obrigatório - 'Some_Class', // esta é a classe ActiveRecord "outra" que será referenciada + 'Some_Class', // esta é a classe ActiveRecord "outra" que isso referenciará // obrigatório // dependendo do tipo de relacionamento @@ -535,20 +532,20 @@ protected array $relations = [ // self::HAS_MANY = a chave estrangeira que referencia a junção // self::BELONGS_TO = a chave local que referencia a junção 'local_or_foreign_key', - // apenas FYI, isso também se junta apenas à chave primária do modelo "outro" + // apenas FYI, isso também só junta com a chave primária do modelo "outro" // opcional - [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // condições adicionais que você deseja ao juntar a relação + [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // condições adicionais que você quer ao juntar a relação // $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5)) // opcional - 'back_reference_name' // isso é se você quiser referenciar essa relação de volta para si mesma Ex: $user->contact->user; + 'back_reference_name' // isso é se você quiser referenciar de volta este relacionamento para si mesmo Ex: $user->contact->user; ]; ] ``` ```php -class User extends ActiveRecord { +class User extends ActiveRecord{ protected array $relations = [ 'contacts' => [ self::HAS_MANY, Contact::class, 'user_id' ], 'contact' => [ self::HAS_ONE, Contact::class, 'user_id' ], @@ -560,7 +557,7 @@ class User extends ActiveRecord { } } -class Contact extends ActiveRecord { +class Contact extends ActiveRecord{ protected array $relations = [ 'user' => [ self::BELONGS_TO, User::class, 'user_id' ], 'user_with_backref' => [ self::BELONGS_TO, User::class, 'user_id', [], 'contact' ], @@ -572,33 +569,134 @@ class Contact extends ActiveRecord { } ``` -Agora temos as referências configuradas para que possamos usá-las muito facilmente! +Agora temos as referências configuradas para que possamos usá-las facilmente! ```php $user = new User($pdo_connection); -// encontrar o usuário mais recente. +// encontre o usuário mais recente. $user->notNull('id')->orderBy('id desc')->find(); -// obter contatos usando a relação: +// obtenha contatos usando a relação: foreach($user->contacts as $contact) { echo $contact->id; } -// ou podemos fazer o caminho inverso. +// ou podemos ir do outro jeito. $contact = new Contact(); -// encontrar um contato +// encontre um contato $contact->find(); -// obter usuário usando a relação: +// obtenha o usuário usando a relação: echo $contact->user->name; // este é o nome do usuário ``` -Bem legal, não é? +Bem legal, hein? + +### Carregamento Ansioso + +#### Visão Geral +O carregamento ansioso resolve o problema de consulta N+1 carregando relacionamentos antecipadamente. Em vez de executar uma consulta separada para os relacionamentos de cada registro, o carregamento ansioso busca todos os dados relacionados em apenas uma consulta adicional por relacionamento. + +> **Nota:** O carregamento ansioso está disponível apenas para v0.7.0 e acima. + +#### Uso Básico +Use o método `with()` para especificar quais relacionamentos carregar ansiosamente: +```php +// Carregue usuários com seus contatos em 2 consultas em vez de N+1 +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + foreach ($u->contacts as $contact) { + echo $contact->email; // Sem consulta adicional! + } +} +``` + +#### Múltiplas Relações +Carregue múltiplos relacionamentos de uma vez: +```php +$users = $user->with(['contacts', 'profile', 'settings'])->findAll(); +``` + +#### Tipos de Relacionamento + +##### HAS_MANY +```php +// Carregue ansiosamente todos os contatos para cada usuário +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + // $u->contacts já está carregado como um array + foreach ($u->contacts as $contact) { + echo $contact->email; + } +} +``` +##### HAS_ONE +```php +// Carregue ansiosamente um contato para cada usuário +$users = $user->with('contact')->findAll(); +foreach ($users as $u) { + // $u->contact já está carregado como um objeto + echo $u->contact->email; +} +``` + +##### BELONGS_TO +```php +// Carregue ansiosamente usuários pais para todos os contatos +$contacts = $contact->with('user')->findAll(); +foreach ($contacts as $c) { + // $c->user já está carregado + echo $c->user->name; +} +``` +##### Com find() +O carregamento ansioso funciona com +findAll() + e +find() +: + +```php +$user = $user->with('contacts')->find(1); +// Usuário e todos os seus contatos carregados em 2 consultas +``` +#### Benefícios de Desempenho +Sem carregamento ansioso (problema N+1): +```php +$users = $user->findAll(); // 1 consulta +foreach ($users as $u) { + $contacts = $u->contacts; // N consultas (uma por usuário!) +} +// Total: 1 + N consultas +``` + +Com carregamento ansioso: + +```php +$users = $user->with('contacts')->findAll(); // 2 consultas no total +foreach ($users as $u) { + $contacts = $u->contacts; // 0 consultas adicionais! +} +// Total: 2 consultas (1 para usuários + 1 para todos os contatos) +``` +Para 10 usuários, isso reduz as consultas de 11 para 2 - uma redução de 82%! + +#### Notas Importantes +- O carregamento ansioso é completamente opcional - o carregamento preguiçoso ainda funciona como antes +- Relacionamentos já carregados são automaticamente ignorados +- Referências de volta funcionam com carregamento ansioso +- Callbacks de relação são respeitados durante o carregamento ansioso + +#### Limitações +- Carregamento ansioso aninhado (ex., +with(['contacts.addresses']) +) não é suportado atualmente +- Restrições de carregamento ansioso via closures não são suportadas nesta versão ## Definindo Dados Personalizados -Às vezes você pode precisar anexar algo único ao seu ActiveRecord, como um cálculo personalizado que pode ser mais fácil apenas anexar ao objeto que então seria passado para, digamos, um modelo. +Às vezes, você pode precisar anexar algo único ao seu ActiveRecord, como um cálculo personalizado que pode ser mais fácil de simplesmente anexar ao objeto que seria passado para, digamos, um template. #### `setCustomData(string $field, mixed $value)` Você anexa os dados personalizados com o método `setCustomData()`. @@ -606,7 +704,7 @@ Você anexa os dados personalizados com o método `setCustomData()`. $user->setCustomData('page_view_count', $page_view_count); ``` -E então, você simplesmente faz referência a ele como uma propriedade normal do objeto. +E então você simplesmente o referencia como uma propriedade de objeto normal. ```php echo $user->page_view_count; @@ -614,7 +712,7 @@ echo $user->page_view_count; ## Eventos -Mais uma super incrível característica sobre esta biblioteca é sobre eventos. Eventos são acionados em determinados momentos com base em certos métodos que você chama. Eles são muito úteis para configurar dados automaticamente para você. +Uma funcionalidade super legal sobre esta biblioteca é sobre eventos. Eventos são acionados em certos momentos com base em certos métodos que você chama. Eles são muito úteis para configurar dados para você automaticamente. #### `onConstruct(ActiveRecord $ActiveRecord, array &config)` @@ -631,7 +729,7 @@ Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php class User extends flight\ActiveRecord { - protected function onConstruct(self $self, array &$config) { // não se esqueça da referência & + protected function onConstruct(self $self, array &$config) { // não esqueça a referência & // você poderia fazer isso para definir automaticamente a conexão $config['connection'] = Flight::db(); // ou isso @@ -645,7 +743,7 @@ class User extends flight\ActiveRecord { #### `beforeFind(ActiveRecord $ActiveRecord)` -Isso provavelmente só é útil se você precisar de uma manipulação de consulta toda vez. +Isso provavelmente é útil apenas se você precisar de uma manipulação de consulta a cada vez. ```php class User extends flight\ActiveRecord { @@ -656,7 +754,7 @@ class User extends flight\ActiveRecord { } protected function beforeFind(self $self) { - // sempre execute id >= 0 se isso for do seu agrado + // sempre execute id >= 0 se isso for o seu estilo $self->gte('id', 0); } } @@ -664,7 +762,7 @@ class User extends flight\ActiveRecord { #### `afterFind(ActiveRecord $ActiveRecord)` -Esse é provavelmente mais útil se você sempre precisar executar alguma lógica toda vez que este registro for buscado. Você precisa descriptografar algo? Você precisa executar uma consulta de contagem personalizada a cada vez (não performático, mas tudo bem)? +Este é provavelmente mais útil se você sempre precisar executar alguma lógica toda vez que este registro é buscado. Você precisa descriptografar algo? Você precisa executar uma consulta de contagem personalizada a cada vez (não performático, mas tanto faz)? ```php class User extends flight\ActiveRecord { @@ -686,7 +784,7 @@ class User extends flight\ActiveRecord { #### `beforeFindAll(ActiveRecord $ActiveRecord)` -Isso é provavelmente só útil se você precisar de uma manipulação de consulta toda vez. +Isso provavelmente é útil apenas se você precisar de uma manipulação de consulta a cada vez. ```php class User extends flight\ActiveRecord { @@ -697,7 +795,7 @@ class User extends flight\ActiveRecord { } protected function beforeFindAll(self $self) { - // sempre execute id >= 0 se isso for do seu agrado + // sempre execute id >= 0 se isso for o seu estilo $self->gte('id', 0); } } @@ -705,7 +803,7 @@ class User extends flight\ActiveRecord { #### `afterFindAll(array $results)` -Semelhante ao `afterFind()`, mas você pode fazê-lo com todos os registros! +Similar ao `afterFind()` mas você pode fazer isso para todos os registros! ```php class User extends flight\ActiveRecord { @@ -718,7 +816,7 @@ class User extends flight\ActiveRecord { protected function afterFindAll(array $results) { foreach($results as $self) { - // faça algo legal como no afterFind() + // faça algo legal como afterFind() } } } @@ -726,7 +824,7 @@ class User extends flight\ActiveRecord { #### `beforeInsert(ActiveRecord $ActiveRecord)` -Realmente útil se você precisar definir alguns valores padrão toda vez. +Realmente útil se você precisar de alguns valores padrão definidos a cada vez. ```php class User extends flight\ActiveRecord { @@ -737,7 +835,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // defina alguns padrões sensatos + // defina alguns padrões sólidos if(!$self->created_date) { $self->created_date = gmdate('Y-m-d'); } @@ -751,7 +849,7 @@ class User extends flight\ActiveRecord { #### `afterInsert(ActiveRecord $ActiveRecord)` -Talvez você tenha um caso de uso para mudar dados após serem inseridos? +Talvez você tenha um caso de uso para alterar dados após a inserção? ```php class User extends flight\ActiveRecord { @@ -764,14 +862,14 @@ class User extends flight\ActiveRecord { protected function afterInsert(self $self) { // você faz o que quiser Flight::cache()->set('most_recent_insert_id', $self->id); - // ou qualquer outra coisa.... + // ou o que for.... } } ``` #### `beforeUpdate(ActiveRecord $ActiveRecord)` -Realmente útil se você precisar definir alguns valores padrão cada vez que uma atualização ocorrer. +Realmente útil se você precisar de alguns valores padrão definidos a cada vez em uma atualização. ```php class User extends flight\ActiveRecord { @@ -782,7 +880,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // defina alguns padrões sensatos + // defina alguns padrões sólidos if(!$self->updated_date) { $self->updated_date = gmdate('Y-m-d'); } @@ -792,7 +890,7 @@ class User extends flight\ActiveRecord { #### `afterUpdate(ActiveRecord $ActiveRecord)` -Talvez você tenha um caso de uso para mudar dados após serem atualizados? +Talvez você tenha um caso de uso para alterar dados após a atualização? ```php class User extends flight\ActiveRecord { @@ -805,14 +903,14 @@ class User extends flight\ActiveRecord { protected function afterInsert(self $self) { // você faz o que quiser Flight::cache()->set('most_recently_updated_user_id', $self->id); - // ou qualquer outra coisa.... + // ou o que for.... } } ``` #### `beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)` -Isso é útil se você quiser que eventos aconteçam tanto quando inserções quanto atualizações ocorrerem. Vou poupar você da longa explicação, mas tenho certeza de que você pode imaginar o que é. +Isso é útil se você quiser que eventos aconteçam tanto em inserções quanto em atualizações. Vou poupá-lo da longa explicação, mas tenho certeza de que você pode adivinhar o que é. ```php class User extends flight\ActiveRecord { @@ -841,14 +939,14 @@ class User extends flight\ActiveRecord { } protected function beforeDelete(self $self) { - echo 'Ele foi um soldado valente... :cry-face:'; + echo 'He was a brave soldier... :cry-face:'; } } ``` ## Gerenciamento de Conexão de Banco de Dados -Quando você estiver usando esta biblioteca, pode definir a conexão com o banco de dados de algumas maneiras diferentes. Você pode definir a conexão no construtor, pode defini-la via uma variável de configuração `$config['connection']` ou pode defini-la via `setDatabaseConnection()` (v0.4.1). +Quando você está usando esta biblioteca, você pode definir a conexão de banco de dados de algumas maneiras diferentes. Você pode definir a conexão no construtor, você pode defini-la via uma variável de configuração `$config['connection']` ou você pode defini-la via `setDatabaseConnection()` (v0.4.1). ```php $pdo_connection = new PDO('sqlite:test.db'); // por exemplo @@ -860,7 +958,7 @@ $user = new User(); $user->setDatabaseConnection($pdo_connection); ``` -Se você deseja evitar configurar sempre uma `$database_connection` toda vez que chamar um registro ativo, existem maneiras de contornar isso! +Se você quiser evitar sempre definir um `$database_connection` toda vez que chamar um active record, há maneiras de contornar isso! ```php // index.php ou bootstrap.php @@ -877,24 +975,23 @@ class User extends flight\ActiveRecord { } } -// E agora, nenhum argumento é necessário! +// E agora, sem argumentos necessários! $user = new User(); ``` -> **Nota:** Se você planeja fazer testes unitários, fazer assim pode adicionar alguns desafios aos testes unitários, mas, no geral, porque você pode injetar sua -conexão com `setDatabaseConnection()` ou `$config['connection']`, não é tão complicado. +> **Nota:** Se você estiver planejando testes unitários, fazer isso dessa maneira pode adicionar alguns desafios aos testes unitários, mas no geral, porque você pode injetar sua conexão com `setDatabaseConnection()` ou `$config['connection']`, não é tão ruim. -Se você precisar atualizar a conexão do banco de dados, por exemplo, se estiver executando um script CLI de longa duração e precisar atualizar a conexão de tempos em tempos, pode redefinir a conexão com `$your_record->setDatabaseConnection($pdo_connection)`. +Se você precisar atualizar a conexão de banco de dados, por exemplo, se estiver executando um script CLI de longa duração e precisar atualizar a conexão de tempos em tempos, você pode redefinir a conexão com `$your_record->setDatabaseConnection($pdo_connection)`. -## Contribuindo +## Contribuição -Por favor, contribua. :D +Por favor, faça. :D ### Configuração -Quando você contribuir, certifique-se de executar `composer test-coverage` para manter 100% de cobertura de testes (isso não é verdadeiro teste unitário, mais como teste de integração). +Quando você contribuir, certifique-se de executar `composer test-coverage` para manter 100% de cobertura de testes (isso não é cobertura de teste unitário real, mais como testes de integração). -Além disso, certifique-se de executar `composer beautify` e `composer phpcs` para corrigir quaisquer erros de linting. +Também certifique-se de executar `composer beautify` e `composer phpcs` para corrigir qualquer erro de linting. ## Licença diff --git a/content/v3/pt/awesome-plugins/apm.md b/content/v3/pt/awesome-plugins/apm.md index 85b109bc..be4d7ded 100644 --- a/content/v3/pt/awesome-plugins/apm.md +++ b/content/v3/pt/awesome-plugins/apm.md @@ -1,14 +1,14 @@ # Documentação do APM do FlightPHP -Bem-vindo ao FlightPHP APM—o treinador pessoal de desempenho do seu app! Este guia é o seu mapa para configurar, usar e dominar o Application Performance Monitoring (APM) com FlightPHP. Seja caçando requisições lentas ou apenas querendo se aprofundar em gráficos de latência, nós cobrimos tudo. Vamos tornar seu app mais rápido, seus usuários mais felizes e suas sessões de depuração uma brisa! +Bem-vindo ao FlightPHP APM—o treinador de desempenho pessoal do seu app! Este guia é o seu mapa para configurar, usar e dominar o Application Performance Monitoring (APM) com o FlightPHP. Seja caçando requisições lentas ou apenas querendo se empolgar com gráficos de latência, nós cobrimos tudo. Vamos tornar o seu app mais rápido, seus usuários mais felizes e suas sessões de depuração uma brisa! Veja uma [demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard) do dashboard para o site Flight Docs. ![FlightPHP APM](/images/apm.png) -## Por Que o APM Importa +## Por que o APM Importa -Imagine isso: seu app é um restaurante movimentado. Sem uma forma de rastrear quanto tempo as ordens demoram ou onde a cozinha está travando, você está adivinhando por que os clientes estão saindo irritados. O APM é o seu sous-chef—ele observa cada passo, desde requisições de entrada até consultas de banco de dados, e sinaliza qualquer coisa que esteja te atrasando. Páginas lentas perdem usuários (estudos dizem que 53% abandonam se um site demora mais de 3 segundos para carregar!), e o APM te ajuda a capturar esses problemas *antes* que eles doam. É uma paz de espírito proativa—menos momentos de “por que isso está quebrado?”, mais vitórias de “olha como isso roda suave!”. +Imagine isso: o seu app é um restaurante movimentado. Sem uma forma de rastrear quanto tempo os pedidos demoram ou onde a cozinha está travando, você está adivinhando por que os clientes estão saindo de mau humor. O APM é o seu sous-chef—ele observa cada passo, desde requisições de entrada até consultas de banco de dados, e sinaliza qualquer coisa que esteja te atrasando. Páginas lentas perdem usuários (estudos dizem que 53% abandonam se um site demora mais de 3 segundos para carregar!), e o APM te ajuda a capturar esses problemas *antes* que eles doam. É uma paz de espírito proativa—menos momentos de “por que isso está quebrado?”, mais vitórias de “olha como isso roda suave!”. ## Instalação @@ -29,9 +29,9 @@ O FlightPHP APM atualmente suporta os seguintes bancos de dados para armazenar m - **SQLite3**: Simples, baseado em arquivo, e ótimo para desenvolvimento local ou apps pequenos. Opção padrão na maioria das configurações. - **MySQL/MariaDB**: Ideal para projetos maiores ou ambientes de produção onde você precisa de armazenamento robusto e escalável. -Você pode escolher o tipo de banco de dados durante o passo de configuração (veja abaixo). Certifique-se de que seu ambiente PHP tenha as extensões necessárias instaladas (ex.: `pdo_sqlite` ou `pdo_mysql`). +Você pode escolher o tipo de banco de dados durante o passo de configuração (veja abaixo). Certifique-se de que o seu ambiente PHP tenha as extensões necessárias instaladas (ex.: `pdo_sqlite` ou `pdo_mysql`). -## Começando +## Primeiros Passos Aqui está o seu passo a passo para o APM incrível: @@ -41,6 +41,7 @@ Adicione isso no seu `index.php` ou arquivo `services.php` para começar o rastr ```php use flight\apm\logger\LoggerFactory; +use flight\database\PdoWrapper; use flight\Apm; $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); @@ -49,12 +50,12 @@ $Apm->bindEventsToFlightInstance($app); // Se você estiver adicionando uma conexão de banco de dados // Deve ser PdoWrapper ou PdoQueryCapture das Extensões Tracy -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True necessário para habilitar rastreamento no APM. +$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True obrigatório para habilitar o rastreamento no APM. $Apm->addPdoConnection($pdo); ``` **O que está acontecendo aqui?** -- `LoggerFactory::create()` pega sua configuração (mais sobre isso em breve) e configura um logger—SQLite por padrão. +- `LoggerFactory::create()` pega a sua configuração (mais sobre isso em breve) e configura um logger—SQLite por padrão. - `Apm` é a estrela—ele escuta os eventos do Flight (requisições, rotas, erros, etc.) e coleta métricas. - `bindEventsToFlightInstance($app)` conecta tudo ao seu app Flight. @@ -69,7 +70,7 @@ Isso mantém o desempenho ágil enquanto ainda te dá dados sólidos. ### 2. Configure-o -Execute isso para criar seu `.runway-config.json`: +Execute isso para criar o seu `.runway-config.json`: ```bash php vendor/bin/runway apm:init @@ -78,7 +79,7 @@ php vendor/bin/runway apm:init **O que isso faz?** - Inicia um assistente perguntando de onde vêm as métricas brutas (fonte) e para onde vão os dados processados (destino). - Padrão é SQLite—ex.: `sqlite:/tmp/apm_metrics.sqlite` para fonte, outro para destino. -- Você acabará com uma configuração como: +- Você terminará com uma configuração como: ```json { "apm": { @@ -93,7 +94,7 @@ php vendor/bin/runway apm:init > Esse processo também perguntará se você quer executar as migrações para essa configuração. Se você estiver configurando pela primeira vez, a resposta é sim. **Por que dois locais?** -Métricas brutas se acumulam rápido (pense em logs não filtrados). O worker as processa em um destino estruturado para o dashboard. Mantém tudo organizado! +Métricas brutas se acumulam rápido (pense em logs não filtrados). O worker as processa em um destino estruturado para o dashboard. Mantém as coisas organizadas! ### 3. Processar Métricas com o Worker @@ -105,17 +106,17 @@ php vendor/bin/runway apm:worker **O que ele está fazendo?** - Lê da sua fonte (ex.: `apm_metrics.sqlite`). -- Processa até 100 métricas (tamanho de lote padrão) para o seu destino. +- Processa até 100 métricas (tamanho de lote padrão) no seu destino. - Para quando termina ou se não há métricas restantes. **Mantenha-o Rodando** -Para apps ao vivo, você quer processamento contínuo. Aqui estão suas opções: +Para apps ao vivo, você vai querer processamento contínuo. Aqui estão suas opções: - **Modo Daemon**: ```bash php vendor/bin/runway apm:worker --daemon ``` - Roda para sempre, processando métricas conforme chegam. Ótimo para dev ou configurações pequenas. + Roda para sempre, processando métricas à medida que chegam. Ótimo para dev ou configurações pequenas. - **Crontab**: Adicione isso ao seu crontab (`crontab -e`): @@ -142,9 +143,9 @@ Para apps ao vivo, você quer processamento contínuo. Aqui estão suas opções - `--timeout 300`: Sai após 5 minutos. **Por que se preocupar?** -Sem o worker, seu dashboard está vazio. É a ponte entre logs brutos e insights acionáveis. +Sem o worker, o seu dashboard fica vazio. É a ponte entre logs brutos e insights acionáveis. -### 4. Inicie o Dashboard +### 4. Iniciar o Dashboard Veja os vitais do seu app: @@ -162,7 +163,7 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l ``` - `--host 0.0.0.0`: Acessível de qualquer IP (útil para visualização remota). - `--port 8080`: Use uma porta diferente se 8001 estiver ocupada. -- `--php-path`: Aponta para PHP se não estiver no seu PATH. +- `--php-path`: Aponta para o PHP se não estiver no seu PATH. Acesse a URL no seu navegador e explore! @@ -170,15 +171,15 @@ Acesse a URL no seu navegador e explore! Para produção, você pode precisar tentar algumas técnicas para fazer o dashboard rodar, já que provavelmente há firewalls e outras medidas de segurança no lugar. Aqui estão algumas opções: -- **Use um Reverse Proxy**: Configure Nginx ou Apache para encaminhar requisições para o dashboard. -- **Túnel SSH**: Se você puder fazer SSH no servidor, use `ssh -L 8080:localhost:8001 youruser@yourserver` para tunelar o dashboard para sua máquina local. +- **Use um Proxy Reverso**: Configure o Nginx ou Apache para encaminhar requisições ao dashboard. +- **Túnel SSH**: Se você puder SSH no servidor, use `ssh -L 8080:localhost:8001 youruser@yourserver` para tunelar o dashboard para a sua máquina local. - **VPN**: Se o seu servidor estiver atrás de uma VPN, conecte-se a ela e acesse o dashboard diretamente. -- **Configure Firewall**: Abra a porta 8001 para o seu IP ou a rede do servidor. (ou qualquer porta que você definiu). -- **Configure Apache/Nginx**: Se você tiver um servidor web na frente do seu app, você pode configurá-lo para um domínio ou subdomínio. Se fizer isso, você definirá a raiz do documento para `/path/to/your/project/vendor/flightphp/apm/dashboard` +- **Configure o Firewall**: Abra a porta 8001 para o seu IP ou a rede do servidor. (ou qualquer porta que você definiu). +- **Configure Apache/Nginx**: Se você tiver um servidor web na frente do seu aplicativo, você pode configurá-lo para um domínio ou subdomínio. Se fizer isso, você definirá o document root para `/path/to/your/project/vendor/flightphp/apm/dashboard` #### Quer um dashboard diferente? -Você pode construir o seu próprio dashboard se quiser! Olhe no diretório vendor/flightphp/apm/src/apm/presenter para ideias de como apresentar os dados para o seu próprio dashboard! +Você pode construir o seu próprio dashboard se quiser! Olhe o diretório vendor/flightphp/apm/src/apm/presenter para ideias de como apresentar os dados para o seu próprio dashboard! ## Recursos do Dashboard @@ -186,15 +187,15 @@ O dashboard é o seu QG do APM—aqui está o que você verá: - **Log de Requisições**: Toda requisição com timestamp, URL, código de resposta e tempo total. Clique em “Detalhes” para middleware, consultas e erros. - **Requisições Mais Lentas**: Top 5 requisições consumindo tempo (ex.: “/api/heavy” em 2.5s). -- **Rotas Mais Lentas**: Top 5 rotas por tempo médio—ótimo para identificar padrões. -- **Taxa de Erro**: Percentual de requisições falhando (ex.: 2.3% de 500s). +- **Rotas Mais Lentas**: Top 5 rotas por tempo médio—ótimo para detectar padrões. +- **Taxa de Erro**: Percentual de requisições falhando (ex.: 2.3% 500s). - **Percentis de Latência**: 95º (p95) e 99º (p99) tempos de resposta—conheça seus cenários de pior caso. - **Gráfico de Código de Resposta**: Visualize 200s, 404s, 500s ao longo do tempo. - **Consultas/Middleware Longas**: Top 5 chamadas de banco de dados lentas e camadas de middleware. -- **Acerto/Erro de Cache**: Com que frequência seu cache salva o dia. +- **Acerto/Falha de Cache**: Com que frequência o seu cache salva o dia. **Extras**: -- Filtre por “Última Hora”, “Último Dia” ou “Última Semana.” +- Filtre por “Última Hora”, “Último Dia” ou “Última Semana”. - Ative o modo escuro para aquelas sessões noturnas. **Exemplo**: @@ -219,7 +220,7 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ``` **Onde aparece?** -Nos detalhes da requisição do dashboard sob “Eventos Personalizados”—expandível com formatação JSON bonita. +Nos detalhes de requisição do dashboard sob “Eventos Personalizados”—expandível com formatação JSON bonita. **Caso de Uso**: ```php @@ -231,7 +232,7 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -Agora você verá se essa API está arrastando seu app para baixo! +Agora você verá se aquela API está arrastando o seu app para baixo! ## Monitoramento de Banco de Dados @@ -240,7 +241,7 @@ Rastreie consultas PDO assim: ```php use flight\database\PdoWrapper; -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True necessário para habilitar rastreamento no APM. +$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True obrigatório para habilitar o rastreamento no APM. $Apm->addPdoConnection($pdo); ``` @@ -251,7 +252,7 @@ $Apm->addPdoConnection($pdo); **Atenção**: - **Opcional**: Pule isso se não precisar de rastreamento de BD. -- **Apenas PdoWrapper**: PDO principal ainda não está conectado—fique ligado! +- **Apenas PdoWrapper**: PDO core ainda não está conectado—fique ligado! - **Aviso de Desempenho**: Registrar toda consulta em um site pesado de BD pode desacelerar as coisas. Use amostragem (`$Apm = new Apm($ApmLogger, 0.1)`) para aliviar a carga. **Saída de Exemplo**: @@ -280,11 +281,11 @@ Cada requisição tem um ID de requisição único para rastreamento. Você pode ```php Flight::map('error', function($message) { - // Obtenha o ID de requisição do cabeçalho de resposta X-Flight-Request-Id + // Obtém o ID de requisição do cabeçalho de resposta X-Flight-Request-Id $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); - // Além disso, você poderia obtê-lo da variável Flight - // Esse método não funcionará bem em swoole ou outras plataformas assíncronas. + // Adicionalmente, você poderia buscá-lo da variável Flight + // Esse método não funcionará bem em swoole ou outras plataformas async. // $requestId = Flight::get('apm.request_id'); echo "Erro: $message (ID de Requisição: $requestId)"; @@ -293,19 +294,29 @@ Flight::map('error', function($message) { ## Atualizando -Se você estiver atualizando para uma versão mais nova do APM, há uma chance de que haja migrações de banco de dados que precisam ser executadas. Você pode fazer isso executando o comando a seguir: +Se você estiver atualizando para uma versão mais nova do APM, há uma chance de que haja migrações de banco de dados que precisam ser executadas. Você pode fazer isso executando o seguinte comando: ```bash php vendor/bin/runway apm:migrate ``` Isso executará quaisquer migrações necessárias para atualizar o esquema do banco de dados para a versão mais recente. -**Nota:** Se o seu banco de dados APM for grande em tamanho, essas migrações podem demorar um pouco para rodar. Você pode querer executar esse comando durante horários de baixa atividade. +**Nota:** Se o seu banco de dados APM for grande em tamanho, essas migrações podem demorar um pouco para rodar. Você pode querer executar esse comando durante horários de baixa demanda. + +### Atualizando de 0.4.3 -> 0.5.0 + +Se você estiver atualizando de 0.4.3 para 0.5.0, você precisará executar o seguinte comando: + +```bash +php vendor/bin/runway apm:config-migrate +``` + +Isso migrará a sua configuração do formato antigo usando o arquivo `.runway-config.json` para o novo formato que armazena as chaves/valores no arquivo `config.php`. ## Limpando Dados Antigos -Para manter seu banco de dados organizado, você pode limpar dados antigos. Isso é especialmente útil se você estiver rodando um app movimentado e quiser manter o tamanho do banco de dados gerenciável. -Você pode fazer isso executando o comando a seguir: +Para manter o seu banco de dados organizado, você pode limpar dados antigos. Isso é especialmente útil se você estiver rodando um app movimentado e quiser manter o tamanho do banco de dados gerenciável. +Você pode fazer isso executando o seguinte comando: ```bash php vendor/bin/runway apm:purge @@ -317,18 +328,18 @@ php vendor/bin/runway apm:purge --days 7 ``` Isso removerá todos os dados mais antigos que 7 dias do banco de dados. -## Solução de Problemas +## Resolução de Problemas -Travado? Tente estes: +Travou? Tente estes: - **Sem Dados no Dashboard?** - O worker está rodando? Verifique `ps aux | grep apm:worker`. - - Caminhos de configuração correspondem? Verifique se os DSNs em `.runway-config.json` apontam para arquivos reais. + - Caminhos de configuração batem? Verifique se os DSNs em `.runway-config.json` apontam para arquivos reais. - Execute `php vendor/bin/runway apm:worker` manualmente para processar métricas pendentes. - **Erros no Worker?** - Dê uma olhada nos seus arquivos SQLite (ex.: `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - - Verifique os logs PHP para traces de pilha. + - Verifique os logs do PHP para stack traces. - **Dashboard Não Inicia?** - Porta 8001 em uso? Use `--port 8080`. @@ -340,8 +351,8 @@ Travado? Tente estes: - Reduza o tamanho do lote: `--batch_size 20`. - **Não Rastreando Exceções/Erros?** - - Se você tiver [Tracy](https://tracy.nette.org/) habilitado para o seu projeto, ele substituirá o tratamento de erros do Flight. Você precisará desabilitar o Tracy e depois garantir que `Flight::set('flight.handle_errors', true);` esteja definido. + - Se você tiver [Tracy](https://tracy.nette.org/) habilitado para o seu projeto, ele sobrescreverá o tratamento de erros do Flight. Você precisará desabilitar o Tracy e então garantir que `Flight::set('flight.handle_errors', true);` esteja definido. - **Não Rastreando Consultas de Banco de Dados?** - - Certifique-se de estar usando `PdoWrapper` para as suas conexões de banco de dados. - - Certifique-se de que o último argumento no construtor seja `true`. \ No newline at end of file + - Garanta que você esteja usando `PdoWrapper` para as suas conexões de banco de dados. + - Certifique-se de que você esteja definindo o último argumento no construtor como `true`. \ No newline at end of file diff --git a/content/v3/pt/awesome-plugins/awesome_plugins.md b/content/v3/pt/awesome-plugins/awesome_plugins.md index 5df510e3..62b62c07 100644 --- a/content/v3/pt/awesome-plugins/awesome_plugins.md +++ b/content/v3/pt/awesome-plugins/awesome_plugins.md @@ -14,21 +14,21 @@ A documentação de API é crucial para qualquer API. Ela ajuda os desenvolvedor O Monitoramento de Desempenho de Aplicação (APM) é crucial para qualquer aplicação. Ele ajuda você a entender como sua aplicação está se saindo e onde estão os gargalos. Existem vários ferramentas APM que podem ser usadas com Flight. - oficial [flightphp/apm](/awesome-plugins/apm) - Flight APM é uma biblioteca APM simples que pode ser usada para monitorar suas aplicações Flight. Pode ser usada para monitorar o desempenho da sua aplicação e ajudá-lo a identificar gargalos. -## Assíncrono +## Async Flight já é um framework rápido, mas adicionar um motor turbo a ele torna tudo mais divertido (e desafiador)! -- [flightphp/async](/awesome-plugins/async) - Biblioteca Async oficial do Flight. Esta biblioteca é uma forma simples de adicionar processamento assíncrono à sua aplicação. Ela usa Swoole/Openswoole sob o capô para fornecer uma maneira simples e eficaz de executar tarefas de forma assíncrona. +- [flightphp/async](/awesome-plugins/async) - Biblioteca Async oficial do Flight. Esta biblioteca é uma maneira simples de adicionar processamento assíncrono à sua aplicação. Ela usa Swoole/Openswoole sob o capô para fornecer uma maneira simples e eficaz de executar tarefas de forma assíncrona. ## Autorização/Permissões Autorização e Permissões são cruciais para qualquer aplicação que exija controles para quem pode acessar o quê. -- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca de Permissões oficial do Flight. Esta biblioteca é uma forma simples de adicionar permissões em nível de usuário e aplicação à sua aplicação. +- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca de Permissões oficial do Flight. Esta biblioteca é uma maneira simples de adicionar permissões em nível de usuário e aplicação à sua aplicação. ## Cache -Cache é uma ótima maneira de acelerar sua aplicação. Existem várias bibliotecas de cache que podem ser usadas com Flight. +O cache é uma ótima maneira de acelerar sua aplicação. Existem várias bibliotecas de cache que podem ser usadas com Flight. - oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Classe de cache em arquivo PHP leve, simples e independente @@ -46,10 +46,10 @@ Cookies são uma ótima maneira de armazenar pequenos pedaços de dados no lado ## Depuração -Depuração é crucial quando você está desenvolvendo em seu ambiente local. Existem alguns plugins que podem elevar sua experiência de depuração. +A depuração é crucial quando você está desenvolvendo em seu ambiente local. Existem alguns plugins que podem elevar sua experiência de depuração. -- [tracy/tracy](/awesome-plugins/tracy) - Este é um manipulador de erros completo que pode ser usado com Flight. Ele tem vários painéis que podem ajudá-lo a depurar sua aplicação. Também é muito fácil de estender e adicionar seus próprios painéis. -- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado com o manipulador de erros [Tracy](/awesome-plugins/tracy), este plugin adiciona alguns painéis extras para ajudar na depuração especificamente para projetos Flight. +- [tracy/tracy](/awesome-plugins/tracy) - Esta é uma manipuladora de erros completa que pode ser usada com Flight. Ela tem vários painéis que podem ajudá-lo a depurar sua aplicação. Também é muito fácil de estender e adicionar seus próprios painéis. +- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado com o manipulador de erros [Tracy](/awesome-plugins/tracy), este plugin adiciona alguns painéis extras para ajudar com a depuração especificamente para projetos Flight. ## Bancos de Dados @@ -61,13 +61,13 @@ Bancos de dados são o núcleo da maioria das aplicações. É assim que você a ## Criptografia -Criptografia é crucial para qualquer aplicação que armazena dados sensíveis. Criptografar e descriptografar os dados não é terrivelmente difícil, mas armazenar adequadamente a chave de criptografia [pode](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [ser](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difícil](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). O mais importante é nunca armazenar sua chave de criptografia em um diretório público ou commitá-la em seu repositório de código. +A criptografia é crucial para qualquer aplicação que armazena dados sensíveis. Criptografar e descriptografar os dados não é terrivelmente difícil, mas armazenar adequadamente a chave de criptografia [pode](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [ser](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difícil](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). O mais importante é nunca armazenar sua chave de criptografia em um diretório público ou commitá-la em seu repositório de código. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Esta é uma biblioteca que pode ser usada para criptografar e descriptografar dados. Começar a usar é bastante simples para começar a criptografar e descriptografar dados. ## Fila de Tarefas -Filas de tarefas são realmente úteis para processar tarefas de forma assíncrona. Isso pode ser enviar e-mails, processar imagens ou qualquer coisa que não precise ser feita em tempo real. +Filas de tarefas são realmente úteis para processar tarefas de forma assíncrona. Isso pode ser o envio de e-mails, processamento de imagens ou qualquer coisa que não precise ser feita em tempo real. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue é uma biblioteca que pode ser usada para processar tarefas de forma assíncrona. Pode ser usada com beanstalkd, MySQL/MariaDB, SQLite e PostgreSQL. @@ -78,13 +78,13 @@ Sessões não são realmente úteis para APIs, mas para construir uma aplicaçã - oficial [flightphp/session](/awesome-plugins/session) - Biblioteca de Sessão oficial do Flight. Esta é uma biblioteca de sessão simples que pode ser usada para armazenar e recuperar dados de sessão. Ela usa o manuseio de sessão integrado do PHP. - [Ghostff/Session](/awesome-plugins/ghost-session) - Gerenciador de Sessão PHP (não bloqueante, flash, segmento, criptografia de sessão). Usa PHP open_ssl para criptografia/descriptografia opcional de dados de sessão. -## Modelagem +## Templating -Modelagem é o núcleo de qualquer aplicação web com uma UI. Existem vários motores de modelagem que podem ser usados com Flight. +O templating é o núcleo de qualquer aplicação web com uma UI. Existem vários motores de templating que podem ser usados com Flight. -- deprecado [flightphp/core View](/learn#views) - Este é um motor de modelagem muito básico que faz parte do núcleo. Não é recomendado usá-lo se você tiver mais do que algumas páginas em seu projeto. -- [latte/latte](/awesome-plugins/latte) - Latte é um motor de modelagem completo que é muito fácil de usar e se sente mais próximo da sintaxe PHP do que Twig ou Smarty. Também é muito fácil de estender e adicionar seus próprios filtros e funções. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate é um poderoso motor de template PHP com compilação de assets, herança de templates e processamento de variáveis. Recursos incluem minificação automática de CSS/JS, cache, codificação Base64 e integração opcional com o framework PHP Flight. +- deprecado [flightphp/core View](/learn#views) - Este é um motor de templating muito básico que faz parte do núcleo. Não é recomendado usá-lo se você tiver mais do que algumas páginas em seu projeto. +- [latte/latte](/awesome-plugins/latte) - Latte é um motor de templating completo que é muito fácil de usar e se sente mais próximo da sintaxe PHP do que Twig ou Smarty. Também é muito fácil de estender e adicionar seus próprios filtros e funções. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate é um poderoso motor de template PHP com compilação de assets, herança de templates e processamento de variáveis. Recursos incluem minificação automática de CSS/JS, cache, codificação Base64 e integração opcional com o framework Flight PHP. ## Integração com WordPress diff --git a/content/v3/pt/awesome-plugins/comment_template.md b/content/v3/pt/awesome-plugins/comment_template.md index 8c1899f6..34167337 100644 --- a/content/v3/pt/awesome-plugins/comment_template.md +++ b/content/v3/pt/awesome-plugins/comment_template.md @@ -5,7 +5,7 @@ ## Recursos - **Herança de Templates**: Use layouts e inclua outros templates -- **Compilação de Assets**: Minificação e cache automáticos de CSS/JS +- **Compilação de Assets**: Minificação automática de CSS/JS e cache - **Processamento de Variáveis**: Variáveis de template com filtros e comandos - **Codificação Base64**: Assets inline como URIs de dados - **Integração com o Framework Flight**: Integração opcional com o framework PHP Flight @@ -33,16 +33,16 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Diretório raiz (onde está o index.php) - a raiz do documento da sua aplicação web + // Diretório raiz (onde index.php está) - a raiz de documentos da sua aplicação web $engine->setPublicPath(__DIR__); - // Diretório dos arquivos de template - suporta caminhos relativos e absolutos + // Diretório de arquivos de template - suporta caminhos relativos e absolutos $engine->setSkinPath('views'); // Relativo ao caminho público // Onde os assets compilados serão armazenados - suporta caminhos relativos e absolutos $engine->setAssetPath('assets'); // Relativo ao caminho público - // Extensão do arquivo de template + // Extensão de arquivo de template $engine->setFileExtension('.php'); }); @@ -63,10 +63,10 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__, // publicPath - diretório raiz (onde está o index.php) - 'views', // skinPath - caminho dos templates (suporta relativo/absoluto) - 'assets', // assetPath - caminho dos assets compilados (suporta relativo/absoluto) - '.php' // fileExtension - extensão do arquivo de template + __DIR__, // publicPath - diretório raiz (onde index.php está) + 'views', // skinPath - caminho de templates (suporta relativo/absoluto) + 'assets', // assetPath - caminho de assets compilados (suporta relativo/absoluto) + '.php' // fileExtension - extensão de arquivo de template ]); $app->map('render', function(string $template, array $data) use ($app): void { @@ -76,29 +76,29 @@ $app->map('render', function(string $template, array $data) use ($app): void { ## Configuração de Caminhos -CommentTemplate fornece tratamento inteligente de caminhos para caminhos relativos e absolutos: +O CommentTemplate fornece tratamento inteligente de caminhos para caminhos relativos e absolutos: ### Caminho Público -O **Caminho Público** é o diretório raiz da sua aplicação web, tipicamente onde o `index.php` reside. Esta é a raiz do documento de onde os servidores web servem arquivos. +O **Caminho Público** é o diretório raiz da sua aplicação web, tipicamente onde `index.php` reside. Este é o raiz de documentos de onde os servidores web servem arquivos. ```php -// Exemplo: se seu index.php está em /var/www/html/myapp/index.php +// Exemplo: se o seu index.php estiver em /var/www/html/myapp/index.php $template->setPublicPath('/var/www/html/myapp'); // Diretório raiz -// Exemplo Windows: se seu index.php está em C:\xampp\htdocs\myapp\index.php +// Exemplo Windows: se o seu index.php estiver em C:\xampp\htdocs\myapp\index.php $template->setPublicPath('C:\\xampp\\htdocs\\myapp'); ``` -### Configuração do Caminho de Templates +### Configuração de Caminho de Templates O caminho de templates suporta caminhos relativos e absolutos: ```php $template = new Engine(); -$template->setPublicPath('/var/www/html/myapp'); // Diretório raiz (onde está o index.php) +$template->setPublicPath('/var/www/html/myapp'); // Diretório raiz (onde index.php está) -// Caminhos relativos - automaticamente combinados com o caminho público +// Caminhos relativos - combinados automaticamente com o caminho público $template->setSkinPath('views'); // → /var/www/html/myapp/views/ $template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ @@ -114,12 +114,12 @@ $template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ $template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ ``` -### Configuração do Caminho de Assets +### Configuração de Caminho de Assets O caminho de assets também suporta caminhos relativos e absolutos: ```php -// Caminhos relativos - automaticamente combinados com o caminho público +// Caminhos relativos - combinados automaticamente com o caminho público $template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ $template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ @@ -138,13 +138,13 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse **Detecção Inteligente de Caminhos:** - **Caminhos Relativos**: Sem separadores iniciais (`/`, `\`) ou letras de unidade -- **Unix Absoluto**: Começa com `/` (ex. `/var/www/assets`) -- **Windows Absoluto**: Começa com letra de unidade (ex. `C:\www`, `D:/assets`) -- **Caminhos UNC**: Começa com `\\` (ex. `\\server\share`) +- **Absolutos Unix**: Começa com `/` (ex.: `/var/www/assets`) +- **Absolutos Windows**: Começa com letra de unidade (ex.: `C:\www`, `D:/assets`) +- **Caminhos UNC**: Começa com `\\` (ex.: `\\server\share`) **Como funciona:** -- Todos os caminhos são automaticamente resolvidos baseados no tipo (relativo vs absoluto) +- Todos os caminhos são resolvidos automaticamente com base no tipo (relativo vs absoluto) - Caminhos relativos são combinados com o caminho público - `@css` e `@js` criam arquivos minificados em: `{resolvedAssetPath}/css/` ou `{resolvedAssetPath}/js/` - `@asset` copia arquivos únicos para: `{resolvedAssetPath}/{relativePath}` @@ -192,9 +192,9 @@ O CommentTemplate suporta diferentes estratégias de carregamento de JavaScript: - - - + + + @@ -234,7 +234,7 @@ const imageData = ''; ``` ** Exemplo: ** ```html - + Logo
          Ícone pequeno como fundo @@ -249,7 +249,7 @@ const imageData = ''; ** Exemplo: ** ```html -Banner Heroico +Hero Banner Baixar Brochura @@ -292,10 +292,10 @@ const imageData = ''; {$content|lower} {$html|striptag} {$text|escape} -{$multiline|nl2br} -{$html|br2nl} +{$multiline|nl2br} +{$html|br2nl} {$description|trim} -{$subject|title} +{$subject|title} ``` #### Comandos de Variáveis @@ -304,30 +304,30 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### Encadear Múltiplos Filtros +#### Comandos de Variáveis ```html {$content|striptag|trim|escape} ``` ### Comentários -Comentários de template são completamente removidos da saída e não aparecem no HTML final: +Os comentários de template são completamente removidos da saída e não aparecerão no HTML final: ```html -{* Este é um comentário de template de uma linha *} +{* Este é um comentário de template de linha única *} {* - Este é um comentário de template - de múltiplas linhas - que abrange várias linhas + Este é um comentário de + template multi-linha + que se estende por várias linhas *}

          {$title}

          -{* Comentário de debug: verificar se a variável title funciona *} +{* Comentário de debug: verificando se a variável title funciona *}

          {$content}

          ``` -**Nota**: Comentários de template `{* ... *}` são diferentes de comentários HTML ``. Comentários de template são removidos durante o processamento e nunca chegam ao navegador. +**Nota**: Os comentários de template `{* ... *}` são diferentes dos comentários HTML ``. Os comentários de template são removidos durante o processamento e nunca chegam ao navegador. ## Estrutura de Projeto Exemplo diff --git a/content/v3/pt/awesome-plugins/runway.md b/content/v3/pt/awesome-plugins/runway.md index 3e7a3b4b..73cf108e 100644 --- a/content/v3/pt/awesome-plugins/runway.md +++ b/content/v3/pt/awesome-plugins/runway.md @@ -1,6 +1,6 @@ -# Pista +# Runway -A Pista é uma aplicação CLI que ajuda a gerenciar suas aplicações Flight. Ela pode gerar controladores, exibir todas as rotas e mais. É baseada na excelente biblioteca [adhocore/php-cli](https://github.com/adhocore/php-cli). +Runway é uma aplicação CLI que ajuda você a gerenciar suas aplicações Flight. Ela pode gerar controladores, exibir todas as rotas e mais. É baseada na excelente biblioteca [adhocore/php-cli](https://github.com/adhocore/php-cli). Clique [aqui](https://github.com/flightphp/runway) para visualizar o código. @@ -14,16 +14,16 @@ composer require flightphp/runway ## Configuração Básica -Na primeira execução da Pista, ela guiará você por um processo de configuração e criará um arquivo de configuração `.runway.json` na raiz do seu projeto. Este arquivo conterá algumas configurações necessárias para que a Pista funcione corretamente. +Na primeira vez que você executar o Runway, ele o guiará por um processo de configuração e criará um arquivo de configuração `.runway.json` na raiz do seu projeto. Este arquivo conterá algumas configurações necessárias para o Runway funcionar corretamente. -## Utilização +## Uso -A Pista possui vários comandos que você pode usar para gerenciar sua aplicação Flight. Existem duas maneiras fáceis de usar a Pista. +O Runway possui vários comandos que você pode usar para gerenciar sua aplicação Flight. Existem duas maneiras fáceis de usar o Runway. -1. Se estiver usando o projeto esqueleto, você pode executar `php runway [comando]` a partir da raiz do seu projeto. -1. Se estiver usando a Pista como um pacote instalado via composer, você pode executar `vendor/bin/runway [comando]` a partir da raiz do seu projeto. +1. Se você estiver usando o projeto skeleton, você pode executar `php runway [command]` a partir da raiz do seu projeto. +1. Se você estiver usando o Runway como um pacote instalado via composer, você pode executar `vendor/bin/runway [command]` a partir da raiz do seu projeto. -Para qualquer comando, você pode inserir a flag `--help` para obter mais informações sobre como utilizar o comando. +Para qualquer comando, você pode passar a flag `--help` para obter mais informações sobre como usar o comando. ```bash php runway routes --help @@ -33,21 +33,21 @@ Aqui estão alguns exemplos: ### Gerar um Controlador -Com base na configuração em seu arquivo `.runway.json`, a localização padrão gerará um controlador para você no diretório `app/controllers/`. +Com base na configuração no seu arquivo `.runway.json`, o local padrão gerará um controlador para você no diretório `app/controllers/`. ```bash -php runway make:controller MeuControlador +php runway make:controller MyController ``` ### Gerar um Modelo Active Record -Com base na configuração em seu arquivo `.runway.json`, a localização padrão gerará um controlador para você no diretório `app/records/`. +Com base na configuração no seu arquivo `.runway.json`, o local padrão gerará um controlador para você no diretório `app/records/`. ```bash -php runway make:record usuários +php runway make:record users ``` -Se por acaso você tiver a tabela `usuários` com o seguinte esquema: `id`, `nome`, `email`, `criado_em`, `atualizado_em`, um arquivo semelhante ao seguinte será criado no arquivo `app/records/RegistroUsuario.php`: +Se, por exemplo, você tiver a tabela `users` com o seguinte esquema: `id`, `name`, `email`, `created_at`, `updated_at`, um arquivo semelhante ao seguinte será criado no arquivo `app/records/UserRecord.php`: ```php argument('', 'O nome do gif engraçado'); + $this->argument('', 'O nome do gif engraçado'); } /** @@ -138,7 +138,7 @@ class ComandoExemplo extends AbstractBaseCommand * * @return void */ - public function execute(string $controlador) + public function execute() { $io = $this->app()->io(); @@ -151,4 +151,43 @@ class ComandoExemplo extends AbstractBaseCommand } ``` -Consulte a [Documentação do adhocore/php-cli](https://github.com/adhocore/php-cli) para mais informações sobre como criar seus próprios comandos personalizados em sua aplicação Flight! \ No newline at end of file +Consulte a [Documentação do adhocore/php-cli](https://github.com/adhocore/php-cli) para mais informações sobre como construir seus próprios comandos personalizados para sua aplicação Flight! + +### Configuração + +Se você precisar personalizar a configuração para o Runway, pode criar um arquivo `.runway-config.json` na raiz do seu projeto. Abaixo estão algumas configurações adicionais que você pode definir: + +```js +{ + + // Este é o local onde o diretório da sua aplicação está localizado + "app_root": "app/", + + // Este é o diretório onde o arquivo index raiz está localizado + "index_root": "public/", + + // Estes são os caminhos para as raízes de outros projetos + "root_paths": [ + "/home/user/different-project", + "/var/www/another-project" + ], + + // Caminhos base provavelmente não precisam ser configurados, mas está aqui se você quiser + "base_paths": { + "/includes/libs/vendor", // se você tiver um caminho realmente único para o diretório vendor ou algo assim + }, + + // Caminhos finais são locais dentro de um projeto para procurar os arquivos de comando + "final_paths": { + "src/diff-path/commands", + "app/module/admin/commands", + }, + + // Se você quiser apenas adicionar o caminho completo, vá em frente (absoluto ou relativo à raiz do projeto) + "paths": [ + "/home/user/different-project/src/diff-path/commands", + "/var/www/another-project/app/module/admin/commands", + "app/my-unique-commands" + ] +} +``` \ No newline at end of file diff --git a/content/v3/pt/examples.md b/content/v3/pt/examples.md index 30358c64..96fc4451 100644 --- a/content/v3/pt/examples.md +++ b/content/v3/pt/examples.md @@ -16,8 +16,9 @@ Exemplos contribuídos pela comunidade: Embora estes não sejam oficialmente patrocinados pela Equipe Flight, eles podem dar ideias sobre como estruturar seus próprios projetos construídos com Flight! -- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify é um app de página única que conecta organizadores de eventos com participantes. Construído com PHP (FlightPHP), JavaScript e MySQL, possui autenticação JWT, gerenciamento de eventos e documentação de API RESTful usando OpenAPI. -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental é uma aplicação web de aluguel de carros de página única e amigável para mobile, construída com PHP (FlightPHP), JavaScript e MySQL. Suporta registro de usuários, navegação e reserva de carros, enquanto administradores podem gerenciar carros, usuários e reservas. O app possui uma API REST, autenticação JWT e design responsivo para uma experiência de aluguel moderna. +- [ASC REST API Spell Checker](https://github.com/AlMosahih-ASC/asc-api-sample) - Uma API REST leve para verificação ortográfica em árabe construída com FlightPHP e biblioteca ArPHP. Esta API fornece capacidades de verificação ortográfica de texto em árabe, incluindo detecção de palavras mal escritas e sugestões de correção. +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify é um app de página única que conecta organizadores de eventos com participantes. Construído com PHP (FlightPHP), JavaScript e MySQL, ele apresenta autenticação JWT, gerenciamento de eventos e documentação de API RESTful usando OpenAPI. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental é uma aplicação web de aluguel de carros de página única e amigável para mobile construída com PHP (FlightPHP), JavaScript e MySQL. Ela suporta registro de usuários, navegação e reserva de carros, enquanto administradores podem gerenciar carros, usuários e reservas. O app apresenta uma API REST, autenticação JWT e um design responsivo para uma experiência de aluguel moderna. - [Decay](https://github.com/boxybird/decay) - Flight v3 com HTMX e SleekDB tudo sobre zumbis! ([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 com Middleware, Controllers, Active Record e Latte. - [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Projeto simples de API CRUD usando o framework Flight, que fornece uma estrutura básica para novos usuários configurarem rapidamente uma aplicação PHP com operações CRUD e conectividade de banco de dados. O projeto demonstra como usar Flight para desenvolvimento de API RESTful, tornando-o uma ferramenta de aprendizado ideal para iniciantes e um kit inicial útil para desenvolvedores mais experientes. diff --git a/content/v3/ru/awesome-plugins/active_record.md b/content/v3/ru/awesome-plugins/active_record.md index 8b85b96a..98b89b2b 100644 --- a/content/v3/ru/awesome-plugins/active_record.md +++ b/content/v3/ru/awesome-plugins/active_record.md @@ -1,10 +1,10 @@ # Flight Active Record -Активная запись – это отображение сущности базы данных на объект PHP. Проще говоря, если у вас есть таблица пользователей в вашей базе данных, вы можете "перевести" строку в этой таблице на класс `User` и объект `$user` в вашем коде. См. [основной пример](#basic-example). +Active Record — это сопоставление сущности базы данных с объектом PHP. Проще говоря, если у вас есть таблица users в базе данных, вы можете "перевести" строку в этой таблице в класс `User` и объект `$user` в вашем коде. См. [базовый пример](#basic-example). Нажмите [здесь](https://github.com/flightphp/active-record) для просмотра репозитория на GitHub. -## Основной пример +## Базовый пример Предположим, у вас есть следующая таблица: @@ -20,7 +20,7 @@ CREATE TABLE users ( ```php /** - * Класс ActiveRecord обычно единственное число + * Класс ActiveRecord обычно используется в единственном числе * * Настоятельно рекомендуется добавлять свойства таблицы в виде комментариев здесь * @@ -39,56 +39,56 @@ class User extends flight\ActiveRecord { } ``` -Теперь смотрите, как происходит магия! +Теперь наблюдайте за магией! ```php // для sqlite -$database_connection = new PDO('sqlite:test.db'); // это просто для примера, вы, вероятно, используете реальное подключение к базе данных +$database_connection = new PDO('sqlite:test.db'); // это просто для примера, вы, вероятно, используете реальное соединение с базой данных // для mysql $database_connection = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'username', 'password'); // или mysqli $database_connection = new mysqli('localhost', 'username', 'password', 'test_db'); -// или mysqli с созданием без объекта +// или mysqli с созданием на основе не-объекта $database_connection = mysqli_connect('localhost', 'username', 'password', 'test_db'); $user = new User($database_connection); $user->name = 'Bobby Tables'; -$user->password = password_hash('некоторый классный пароль'); +$user->password = password_hash('some cool password'); $user->insert(); // или $user->save(); echo $user->id; // 1 $user->name = 'Joseph Mamma'; -$user->password = password_hash('некоторый классный пароль снова!!!'); +$user->password = password_hash('some cool password again!!!'); $user->insert(); -// нельзя использовать $user->save() здесь, иначе он подумает, что это обновление! +// здесь нельзя использовать $user->save(), иначе оно подумает, что это обновление! echo $user->id; // 2 ``` -И добавление нового пользователя было так же просто! Теперь, когда в базе данных есть строка пользователя, как вы можете ее извлечь? +И было так просто добавить нового пользователя! Теперь, когда в базе данных есть строка пользователя, как вы её извлечёте? ```php $user->find(1); // найти id = 1 в базе данных и вернуть его. echo $user->name; // 'Bobby Tables' ``` -А что если вы хотите найти всех пользователей? +А что, если вы хотите найти всех пользователей? ```php $users = $user->findAll(); ``` -Что насчет определенного условия? +А с определённым условием? ```php $users = $user->like('name', '%mamma%')->findAll(); ``` -Видите, как это весело? Давайте установим это и начнем! +Видите, насколько это весело? Давайте установим его и начнём! ## Установка @@ -100,33 +100,33 @@ composer require flightphp/active-record ## Использование -Это можно использовать как отдельную библиотеку или с PHP-фреймворком Flight. Полностью вам решать. +Это можно использовать как самостоятельную библиотеку или с фреймворком Flight PHP. Полностью на ваше усмотрение. -### Отдельно -Просто убедитесь, что вы передаете подключение PDO в конструктор. +### Автономно +Просто убедитесь, что вы передаёте соединение PDO в конструктор. ```php -$pdo_connection = new PDO('sqlite:test.db'); // это просто для примера, вы, вероятно, используете реальное подключение к базе данных +$pdo_connection = new PDO('sqlite:test.db'); // это просто для примера, вы, вероятно, используете реальное соединение с базой данных $User = new User($pdo_connection); ``` -> Не хотите всегда устанавливать ваше подключение к базе данных в конструкторе? См. [Управление подключением к базе данных](#database-connection-management) для других идей! +> Не хотите всегда устанавливать соединение с базой данных в конструкторе? См. [Управление соединением с базой данных](#database-connection-management) для других идей! -### Зарегистрировать как метод в Flight -Если вы используете PHP-фреймворк Flight, вы можете зарегистрировать класс ActiveRecord как сервис, но вам честно не обязательно это делать. +### Регистрация как метода в Flight +Если вы используете фреймворк Flight PHP, вы можете зарегистрировать класс ActiveRecord как сервис, но честно говоря, это не обязательно. ```php Flight::register('user', 'User', [ $pdo_connection ]); -// тогда вы можете использовать это так в контроллере, функции и т.д. +// затем вы можете использовать его так в контроллере, функции и т.д. Flight::user()->find(1); ``` ## Методы `runway` -[runway](/awesome-plugins/runway) – это CLI инструмент для Flight, который имеет специальную команду для этой библиотеки. +[runway](/awesome-plugins/runway) — это CLI-инструмент для Flight, который имеет пользовательскую команду для этой библиотеки. ```bash # Использование @@ -146,7 +146,7 @@ declare(strict_types=1); namespace app\records; /** - * Класс ActiveRecord для таблицы пользователей. + * Класс ActiveRecord для таблицы users. * @link https://docs.flightphp.com/awesome-plugins/active-record * * @property int $id @@ -158,7 +158,7 @@ namespace app\records; class UserRecord extends \flight\ActiveRecord { /** - * @var array $relations Установите отношения для модели + * @var array $relations Установка отношений для модели * https://docs.flightphp.com/awesome-plugins/active-record#relationships */ protected array $relations = [ @@ -167,7 +167,7 @@ class UserRecord extends \flight\ActiveRecord /** * Конструктор - * @param mixed $databaseConnection Подключение к базе данных + * @param mixed $databaseConnection Соединение с базой данных */ public function __construct($databaseConnection) { @@ -180,9 +180,9 @@ class UserRecord extends \flight\ActiveRecord #### `find($id = null) : boolean|ActiveRecord` -Находит одну запись и присваивает ее текущему объекту. Если вы передаете `$id` какого-либо рода, это будет выполнять поиск по первичному ключу с этим значением. Если ничего не передается, это просто найдет первую запись в таблице. +Найти одну запись и присвоить её текущему объекту. Если вы передадите `$id` какого-либо рода, он выполнит поиск по первичному ключу с этим значением. Если ничего не передано, он просто найдёт первую запись в таблице. -Кроме того, вы можете передать ему другие вспомогательные методы для запроса к вашей таблице. +Кроме того, вы можете передать другие вспомогательные методы для запроса таблицы. ```php // найти запись с некоторыми условиями заранее @@ -195,7 +195,7 @@ $user->find($id); #### `findAll(): array` -Находит все записи в таблице, которую вы указываете. +Находит все записи в указанной таблице. ```php $user->findAll(); @@ -203,7 +203,7 @@ $user->findAll(); #### `isHydrated(): boolean` (v0.4.0) -Возвращает `true`, если текущая запись была гидратирована (извлечена из базы данных). +Возвращает `true`, если текущая запись была гидратирована (загружена из базы данных). ```php $user->find(1); @@ -222,9 +222,9 @@ $user->password = md5('demo'); $user->insert(); ``` -##### Первичные ключи на текстовой основе +##### Первичные ключи на основе текста -Если у вас есть первичный ключ на текстовой основе (например, UUID), вы можете установить значение первичного ключа перед вставкой одним из двух способов. +Если у вас есть первичный ключ на основе текста (например, UUID), вы можете установить значение первичного ключа перед вставкой одним из двух способов. ```php $user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]); @@ -234,24 +234,24 @@ $user->password = md5('demo'); $user->insert(); // или $user->save(); ``` -или вы можете позволить первичному ключу автоматически генерироваться для вас через события. +или вы можете позволить первичному ключу генерироваться автоматически для вас через события. ```php class User extends flight\ActiveRecord { public function __construct($database_connection) { parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]); - // вы также можете установить первичный ключ таким образом вместо массива выше. + // вы также можете установить primaryKey таким образом вместо массива выше. $this->primaryKey = 'uuid'; } protected function beforeInsert(self $self) { - $self->uuid = uniqid(); // или как вам нужно сгенерировать ваши уникальные идентификаторы + $self->uuid = uniqid(); // или как вам нужно генерировать уникальные id } } ``` -Если вы не установите первичный ключ перед вставкой, он будет установлен на `rowid`, и база данных сгенерирует его для вас, но он не будет храниться, потому что это поле может не существовать в вашей таблице. Вот почему рекомендуется использовать событие для автоматического управления этим. +Если вы не установите первичный ключ перед вставкой, он будет установлен как `rowid`, и база данных сгенерирует его для вас, но он не сохранится, потому что это поле может не существовать в вашей таблице. Поэтому рекомендуется использовать событие для автоматической обработки этого. #### `update(): boolean|ActiveRecord` @@ -265,7 +265,7 @@ $user->update(); #### `save(): boolean|ActiveRecord` -Вставляет или обновляет текущую запись в базе данных. Если у записи есть id, она будет обновлена, в противном случае будет вставлена. +Вставляет или обновляет текущую запись в базу данных. Если запись имеет id, она обновится, иначе вставится. ```php $user = new User($pdo_connection); @@ -274,7 +274,7 @@ $user->password = md5('demo'); $user->save(); ``` -**Примечание:** Если у вас есть определенные отношения в классе, они также будут рекурсивно сохранены, если они были определены, созданы и имеют измененные данные для обновления. (v0.4.0 и выше) +**Примечание:** Если у вас определены отношения в классе, он рекурсивно сохранит эти отношения, если они определены, инстанцированы и имеют изменённые данные для обновления. (v0.4.0 и выше) #### `delete(): boolean` @@ -285,7 +285,7 @@ $user->gt('id', 0)->orderBy('id desc')->find(); $user->delete(); ``` -Вы также можете удалить несколько записей, исполняя поиск заранее. +Вы также можете удалить несколько записей, выполнив поиск заранее. ```php $user->like('name', 'Bob%')->delete(); @@ -300,25 +300,25 @@ $user->greaterThan('id', 0)->orderBy('id desc')->find(); // на данный момент ничего не "грязное". -$user->email = 'test@example.com'; // теперь email считается "грязным", поскольку он был изменен. +$user->email = 'test@example.com'; // теперь email считается "грязным", поскольку оно изменилось. $user->update(); -// теперь нет грязных данных, так как они были обновлены и сохранены в базе данных +// теперь нет данных, которые являются грязными, потому что они обновлены и сохранены в базе данных -$user->password = password_hash('newpassword'); // теперь это грязное -$user->dirty(); // ничего не передав, вы очистите все грязные записи. +$user->password = password_hash()'newpassword'); // теперь это грязное +$user->dirty(); // передача ничего очистит все грязные записи. $user->update(); // ничего не обновится, потому что ничего не было захвачено как грязное. -$user->dirty([ 'name' => 'что-то', 'password' => password_hash('другой пароль') ]); -$user->update(); // обновлены как имя, так и пароль. +$user->dirty([ 'name' => 'something', 'password' => password_hash('a different password') ]); +$user->update(); // и name, и password обновлены. ``` #### `copyFrom(array $data): ActiveRecord` (v0.4.0) -Это псевдоним для метода `dirty()`. Немного более понятно, что вы делаете. +Это псевдоним для метода `dirty()`. Это немного яснее, что вы делаете. ```php -$user->copyFrom([ 'name' => 'что-то', 'password' => password_hash('другой пароль') ]); -$user->update(); // обновлены как имя, так и пароль. +$user->copyFrom([ 'name' => 'something', 'password' => password_hash('a different password') ]); +$user->update(); // и name, и password обновлены. ``` #### `isDirty(): boolean` (v0.4.0) @@ -333,15 +333,14 @@ $user->isDirty(); // true #### `reset(bool $include_query_data = true): ActiveRecord` -Сбрасывает текущую запись в ее начальное состояние. Это действительно полезно использовать в поведениях типа цикла. -Если вы передадите `true`, он также сбросит данные запроса, которые использовались для поиска текущего объекта (поведение по умолчанию). +Сбрасывает текущую запись в её начальное состояние. Это очень полезно для циклов. Если вы передадите `true`, он также сбросит данные запроса, которые использовались для поиска текущего объекта (поведение по умолчанию). ```php $users = $user->greaterThan('id', 0)->orderBy('id desc')->find(); $user_company = new UserCompany($pdo_connection); foreach($users as $user) { - $user_company->reset(); // начинаем с чистого листа + $user_company->reset(); // начать с чистого листа $user_company->user_id = $user->id; $user_company->company_id = $some_company_id; $user_company->insert(); @@ -350,12 +349,12 @@ foreach($users as $user) { #### `getBuiltSql(): string` (v0.4.1) -После выполнения метода `find()`, `findAll()`, `insert()`, `update()` или `save()` вы можете получить SQL, который был построен, и использовать его для отладки. +После выполнения метода `find()`, `findAll()`, `insert()`, `update()` или `save()` вы можете получить построенный SQL и использовать его для отладки. -## Методы SQL Запросов +## Методы SQL-запросов #### `select(string $field1 [, string $field2 ... ])` -Вы можете выбрать только несколько столбцов в таблице, если хотите (это более производительно на действительно широких таблицах с большим количеством столбцов) +Вы можете выбрать только несколько столбцов в таблице, если хотите (это более производительно для очень широких таблиц с многими столбцами) ```php $user->select('id', 'name')->find(); @@ -363,7 +362,7 @@ $user->select('id', 'name')->find(); #### `from(string $table)` -Вы вполне можете выбрать другую таблицу! Почему бы и нет?! +Вы технически можете выбрать другую таблицу тоже! Почему бы и нет?! ```php $user->select('id', 'name')->from('user')->find(); @@ -371,7 +370,7 @@ $user->select('id', 'name')->from('user')->find(); #### `join(string $table_name, string $join_condition)` -Вы даже можете присоединиться к другой таблице в базе данных. +Вы даже можете присоединить другую таблицу в базе данных. ```php $user->join('contacts', 'contacts.user_id = users.id')->find(); @@ -379,17 +378,17 @@ $user->join('contacts', 'contacts.user_id = users.id')->find(); #### `where(string $where_conditions)` -Вы можете установить некоторые пользовательские аргументы where (вы не можете устанавливать параметры в этом условии where) +Вы можете установить некоторые пользовательские аргументы where (вы не можете установить параметры в этом операторе where) ```php $user->where('id=1 AND name="demo"')->find(); ``` -**Примечание по безопасности** - Вам может возникнуть желание сделать что-то вроде `$user->where("id = '{$id}' AND name = '{$name}'")->find();`. Пожалуйста, НЕ ДЕЛАЙТЕ ЭТОГО!!! Это подвержено тому, что называется атаками SQL-инъекций. В Интернете есть много статей, пожалуйста, поищите "sql injection attacks php", и вы найдёте много статей на эту тему. Правильный способ обработки этого с помощью этой библиотеки вместо этого метода `where()`, вы бы сделали что-то более вроде `$user->eq('id', $id)->eq('name', $name)->find();` Если вам абсолютно необходимо это делать, библиотека `PDO` имеет `$pdo->quote($var)`, чтобы экранировать это для вас. Только после того, как вы используете `quote()`, вы можете использовать это в операторе `where()`. +**Примечание по безопасности** — Вас может соблазнить сделать что-то вроде `$user->where("id = '{$id}' AND name = '{$name}'")->find();`. Пожалуйста, НЕ ДЕЛАЙТЕ ЭТОГО!!! Это подвержено тому, что известно как атаки SQL-инъекций. В интернете много статей, пожалуйста, погуглите "sql injection attacks php" и вы найдёте много статей по этой теме. Правильный способ обработки этого с этой библиотекой — вместо этого метода `where()` вы бы сделали что-то вроде `$user->eq('id', $id)->eq('name', $name)->find();` Если вам абсолютно необходимо это сделать, библиотека `PDO` имеет `$pdo->quote($var)` для экранирования. Только после использования `quote()` вы можете использовать его в операторе `where()`. #### `group(string $group_by_statement)/groupBy(string $group_by_statement)` -Группируйте ваши результаты по определенному условию. +Группируйте ваши результаты по определённому условию. ```php $user->select('COUNT(*) as count')->groupBy('name')->findAll(); @@ -405,7 +404,7 @@ $user->orderBy('name DESC')->find(); #### `limit(string $limit)/limit(int $offset, int $limit)` -Ограничьте количество возвращаемых записей. Если задано второе целое число, оно будет сдвинуто, ограничение также как в SQL. +Ограничьте количество возвращаемых записей. Если дано второе целое число, оно будет offset, limit точно как в SQL. ```php $user->orderby('name DESC')->limit(0, 10)->findAll(); @@ -497,35 +496,35 @@ $user->in('id', [1, 2])->find(); $user->between('id', [1, 2])->find(); ``` -### Условия ИЛИ +### Условия OR -Возможно, вы захотите обернуть ваши условия в оператор ИЛИ. Это делается либо с помощью методов `startWrap()` и `endWrap()`, либо путем заполнения 3-го параметра условия после поля и значения. +Возможно обернуть ваши условия в оператор OR. Это делается либо с помощью метода `startWrap()` и `endWrap()`, либо заполняя 3-й параметр условия после поля и значения. ```php // Метод 1 $user->eq('id', 1)->startWrap()->eq('name', 'demo')->or()->eq('name', 'test')->endWrap('OR')->find(); -// Это будет эквивалентно `id = 1 AND (name = 'demo' OR name = 'test')` +// Это вычислится как `id = 1 AND (name = 'demo' OR name = 'test')` // Метод 2 $user->eq('id', 1)->eq('name', 'demo', 'OR')->find(); -// Это будет эквивалентно `id = 1 OR name = 'demo'` +// Это вычислится как `id = 1 OR name = 'demo'` ``` ## Отношения -Вы можете установить несколько видов отношений, используя эту библиотеку. Вы можете установить отношения один->много и один->один между таблицами. Это требует небольшой дополнительной настройки в классе заранее. +Вы можете установить несколько видов отношений с помощью этой библиотеки. Вы можете установить отношения один-ко-многим и один-к-одному между таблицами. Это требует немного дополнительной настройки в классе заранее. -Установка массива `$relations` не сложна, но угадать правильный синтаксис может быть сложно. +Установка массива `$relations` не сложна, но угадывание правильного синтаксиса может быть запутанным. ```php protected array $relations = [ - // вы можете назвать ключ как угодно. Имя ActiveRecord, вероятно, хорошее. Например: user, contact, client + // вы можете назвать ключ как угодно. Название ActiveRecord, вероятно, хорошо. Пример: user, contact, client 'user' => [ // обязательно // self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO self::HAS_ONE, // это тип отношения // обязательно - 'Some_Class', // это "другой" ActiveRecord, на который это будет ссылаться + 'Some_Class', // это "другой" класс ActiveRecord, на который будет ссылка // обязательно // в зависимости от типа отношения @@ -533,14 +532,14 @@ protected array $relations = [ // self::HAS_MANY = внешний ключ, который ссылается на соединение // self::BELONGS_TO = локальный ключ, который ссылается на соединение 'local_or_foreign_key', - // просто FYI, это также соединяется только с первичным ключом "другой" модели + // просто FYI, это также присоединяется только к первичному ключу "другой" модели // опционально - [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // дополнительные условия, которые вы хотите при соединении с отношением + [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // дополнительные условия, которые вы хотите при присоединении отношения // $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5)) // опционально - 'back_reference_name' // это если вы хотите ссылаться на это отношение обратно на себя, например: $user->contact->user; + 'back_reference_name' // это если вы хотите обратную ссылку на это отношение обратно на себя Пример: $user->contact->user; ]; ] ``` @@ -570,33 +569,134 @@ class Contact extends ActiveRecord{ } ``` -Теперь у нас есть установленные ссылки, так что мы можем использовать их очень легко! +Теперь у нас настроены ссылки, чтобы мы могли использовать их очень легко! ```php $user = new User($pdo_connection); -// найдите самого последнего пользователя. +// найти самого последнего пользователя. $user->notNull('id')->orderBy('id desc')->find(); -// получите контакты, используя отношение: +// получить контакты, используя отношение: foreach($user->contacts as $contact) { echo $contact->id; } -// или мы можем пойти другим путем. +// или мы можем пойти в обратную сторону. $contact = new Contact(); -// найдите один контакт +// найти один контакт $contact->find(); -// получите пользователя, используя отношение: +// получить пользователя, используя отношение: echo $contact->user->name; // это имя пользователя ``` -Классно, да? +Довольно круто, eh? + +### Жадная загрузка + +#### Обзор +Жадная загрузка решает проблему N+1 запросов, загружая отношения заранее. Вместо выполнения отдельного запроса для отношений каждой записи, жадная загрузка извлекает все связанные данные всего в одном дополнительном запросе на отношение. + +> **Примечание:** Жадная загрузка доступна только для v0.7.0 и выше. + +#### Базовое использование +Используйте метод `with()` для указания, какие отношения жадно загружать: +```php +// Загрузить пользователей с их контактами в 2 запроса вместо N+1 +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + foreach ($u->contacts as $contact) { + echo $contact->email; // Нет дополнительного запроса! + } +} +``` + +#### Несколько отношений +Загружайте несколько отношений одновременно: +```php +$users = $user->with(['contacts', 'profile', 'settings'])->findAll(); +``` + +#### Типы отношений + +##### HAS_MANY +```php +// Жадно загрузить все контакты для каждого пользователя +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + // $u->contacts уже загружен как массив + foreach ($u->contacts as $contact) { + echo $contact->email; + } +} +``` +##### HAS_ONE +```php +// Жадно загрузить один контакт для каждого пользователя +$users = $user->with('contact')->findAll(); +foreach ($users as $u) { + // $u->contact уже загружен как объект + echo $u->contact->email; +} +``` + +##### BELONGS_TO +```php +// Жадно загрузить родительских пользователей для всех контактов +$contacts = $contact->with('user')->findAll(); +foreach ($contacts as $c) { + // $c->user уже загружен + echo $c->user->name; +} +``` +##### С find() +Жадная загрузка работает как с +findAll() +, так и с +find() +: + +```php +$user = $user->with('contacts')->find(1); +// Пользователь и все их контакты загружены в 2 запроса +``` +#### Преимущества производительности +Без жадной загрузки (проблема N+1): +```php +$users = $user->findAll(); // 1 запрос +foreach ($users as $u) { + $contacts = $u->contacts; // N запросов (по одному на пользователя!) +} +// Итого: 1 + N запросов +``` + +С жадной загрузкой: + +```php +$users = $user->with('contacts')->findAll(); // всего 2 запроса +foreach ($users as $u) { + $contacts = $u->contacts; // 0 дополнительных запросов! +} +// Итого: 2 запроса (1 для пользователей + 1 для всех контактов) +``` +Для 10 пользователей это уменьшает запросы с 11 до 2 — снижение на 82%! + +#### Важные примечания +- Жадная загрузка полностью опциональна — ленивая загрузка работает как раньше +- Уже загруженные отношения автоматически пропускаются +- Обратные ссылки работают с жадной загрузкой +- Колбэки отношений уважаются во время жадной загрузки + +#### Ограничения +- Вложенная жадная загрузка (например, +with(['contacts.addresses']) +) в настоящее время не поддерживается +- Ограничения жадной загрузки через замыкания не поддерживаются в этой версии ## Установка пользовательских данных -Иногда вам может потребоваться прикрепить что-то уникальное к вашей ActiveRecord, например, пользовательский расчет, который, возможно, будет легче просто прикрепить к объекту, который затем будет передан, скажем, шаблону. +Иногда вам может понадобиться прикрепить что-то уникальное к вашему ActiveRecord, например, пользовательский расчёт, который может быть проще прикрепить к объекту, который затем передаётся, скажем, в шаблон. #### `setCustomData(string $field, mixed $value)` Вы прикрепляете пользовательские данные с помощью метода `setCustomData()`. @@ -604,7 +704,7 @@ echo $contact->user->name; // это имя пользователя $user->setCustomData('page_view_count', $page_view_count); ``` -А затем вы просто ссылаетесь на это, как на обычное свойство объекта. +А затем вы просто ссылаетесь на него как на обычное свойство объекта. ```php echo $user->page_view_count; @@ -612,11 +712,11 @@ echo $user->page_view_count; ## События -Одним из супер классных преимуществ этой библиотеки являются события. События срабатывают в определенные моменты на основе определенных методов, которые вы вызываете. Они очень полезны для автоматической настройки данных для вас. +Ещё одна супер крутая функция этой библиотеки — это события. События срабатывают в определённые моменты на основе определённых методов, которые вы вызываете. Они очень полезны для автоматической настройки данных для вас. #### `onConstruct(ActiveRecord $ActiveRecord, array &config)` -Это действительно полезно, если вам нужно установить подключение по умолчанию или что-то подобное. +Это очень полезно, если вам нужно установить соединение по умолчанию или что-то вроде того. ```php // index.php или bootstrap.php @@ -629,8 +729,8 @@ Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php class User extends flight\ActiveRecord { - protected function onConstruct(self $self, array &$config) { // не забывайте о референции & - // вы можете сделать это, чтобы автоматически установить подключение + protected function onConstruct(self $self, array &$config) { // не забудьте ссылку & + // вы могли бы сделать это для автоматической установки соединения $config['connection'] = Flight::db(); // или это $self->transformAndPersistConnection(Flight::db()); @@ -643,7 +743,7 @@ class User extends flight\ActiveRecord { #### `beforeFind(ActiveRecord $ActiveRecord)` -Это, вероятно, будет полезно, только если вам нужно манипулировать запросом каждый раз. +Это, вероятно, полезно только если вам нужно манипулировать запросом каждый раз. ```php class User extends flight\ActiveRecord { @@ -654,7 +754,7 @@ class User extends flight\ActiveRecord { } protected function beforeFind(self $self) { - // всегда выполняйте id >= 0, если это ваше желание + // всегда выполняйте id >= 0, если это ваш стиль $self->gte('id', 0); } } @@ -662,7 +762,7 @@ class User extends flight\ActiveRecord { #### `afterFind(ActiveRecord $ActiveRecord)` -Эта один, вероятно, более полезна, если вам всегда нужно выполнять какую-либо логику каждый раз, когда эта запись извлекается. Нужно ли вам расшифровать что-то? Вам нужно запустить пользовательский запрос на подсчет каждый раз (невыгодно, но что ж)? +Этот, вероятно, более полезен, если вам всегда нужно выполнять некоторую логику каждый раз, когда эта запись извлекается. Нужно ли вам расшифровать что-то? Нужно ли выполнять пользовательский запрос подсчёта каждый раз (не производительно, но ладно)? ```php class User extends flight\ActiveRecord { @@ -676,15 +776,15 @@ class User extends flight\ActiveRecord { // расшифровка чего-то $self->secret = yourDecryptFunction($self->secret, $some_key); - // возможно, сохранение чего-то пользовательского, как запрос??? - $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']); + // возможно, хранение чего-то пользовательского, как запрос??? + $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']; } } ``` #### `beforeFindAll(ActiveRecord $ActiveRecord)` -Это, вероятно, будет полезно, только если вам нужно манипулировать запросом каждый раз. +Это, вероятно, полезно только если вам нужно манипулировать запросом каждый раз. ```php class User extends flight\ActiveRecord { @@ -695,7 +795,7 @@ class User extends flight\ActiveRecord { } protected function beforeFindAll(self $self) { - // всегда выполняйте id >= 0, если это ваше желание + // всегда выполняйте id >= 0, если это ваш стиль $self->gte('id', 0); } } @@ -703,7 +803,7 @@ class User extends flight\ActiveRecord { #### `afterFindAll(array $results)` -Похоже на `afterFind()`, но вы можете делать это со всеми записями сразу! +Похоже на `afterFind()`, но вы можете сделать это для всех записей! ```php class User extends flight\ActiveRecord { @@ -716,7 +816,7 @@ class User extends flight\ActiveRecord { protected function afterFindAll(array $results) { foreach($results as $self) { - // сделайте что-то классное, как и в afterFind() + // сделайте что-то крутое, как afterFind() } } } @@ -724,7 +824,7 @@ class User extends flight\ActiveRecord { #### `beforeInsert(ActiveRecord $ActiveRecord)` -Действительно полезно, если вам нужно установить некоторые значения по умолчанию каждый раз. +Очень полезно, если вам нужно установить некоторые значения по умолчанию каждый раз. ```php class User extends flight\ActiveRecord { @@ -735,7 +835,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // задайте некоторые надежные значения по умолчанию + // установите некоторые разумные значения по умолчанию if(!$self->created_date) { $self->created_date = gmdate('Y-m-d'); } @@ -749,7 +849,7 @@ class User extends flight\ActiveRecord { #### `afterInsert(ActiveRecord $ActiveRecord)` -Возможно, у вас есть случай использования для изменения данных послеINSERT? +Возможно, у вас есть случай использования для изменения данных после вставки? ```php class User extends flight\ActiveRecord { @@ -760,16 +860,16 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // делайте что хотите + // делайте, что хотите Flight::cache()->set('most_recent_insert_id', $self->id); - // или что-то еще... + // или что угодно.... } } ``` #### `beforeUpdate(ActiveRecord $ActiveRecord)` -Действительно полезно, если вам нужно установить некоторые значения по умолчанию каждый раз при обновлении. +Очень полезно, если вам нужно установить некоторые значения по умолчанию каждый раз при обновлении. ```php class User extends flight\ActiveRecord { @@ -779,8 +879,8 @@ class User extends flight\ActiveRecord { parent::__construct($database_connection, 'users'); } - protected function beforeUpdate(self $self) { - // задайте некоторые надежные значения по умолчанию + protected function beforeInsert(self $self) { + // установите некоторые разумные значения по умолчанию if(!$self->updated_date) { $self->updated_date = gmdate('Y-m-d'); } @@ -790,7 +890,7 @@ class User extends flight\ActiveRecord { #### `afterUpdate(ActiveRecord $ActiveRecord)` -Возможно, у вас есть случай использования для изменения данных после его обновления? +Возможно, у вас есть случай использования для изменения данных после обновления? ```php class User extends flight\ActiveRecord { @@ -800,17 +900,17 @@ class User extends flight\ActiveRecord { parent::__construct($database_connection, 'users'); } - protected function afterUpdate(self $self) { - // делайте что хотите + protected function afterInsert(self $self) { + // делайте, что хотите Flight::cache()->set('most_recently_updated_user_id', $self->id); - // или что-то еще... + // или что угодно.... } } ``` #### `beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)` -Это полезно, если вы хотите, чтобы события происходили как при вставках, так и при обновлениях. Я сэкономлю вам длинное объяснение, но я уверен, что вы можете догадаться, что это такое. +Это полезно, если вы хотите, чтобы события происходили как при вставках, так и при обновлениях. Я пощажу вас от длинного объяснения, но уверен, вы можете угадать, что это такое. ```php class User extends flight\ActiveRecord { @@ -828,7 +928,7 @@ class User extends flight\ActiveRecord { #### `beforeDelete(ActiveRecord $ActiveRecord)/afterDelete(ActiveRecord $ActiveRecord)` -Не уверен, что вы хотите сделать здесь, но никаких предвзятостей! Дерзайте! +Не уверен, что вы захотите здесь сделать, но никаких суждений! Действуйте! ```php class User extends flight\ActiveRecord { @@ -839,17 +939,17 @@ class User extends flight\ActiveRecord { } protected function beforeDelete(self $self) { - echo 'Он был смелым солдатом... :cry-face:'; + echo 'He was a brave soldier... :cry-face:'; } } ``` -## Управление подключением к базе данных +## Управление соединением с базой данных -Когда вы используете эту библиотеку, вы можете установить подключение к базе данных несколькими способами. Вы можете установить подключение в конструкторе, вы можете установить его через переменную конфигурации `$config['connection']` или вы можете установить его через `setDatabaseConnection()` (v0.4.1). +При использовании этой библиотеки вы можете установить соединение с базой данных несколькими способами. Вы можете установить соединение в конструкторе, вы можете установить его через переменную конфигурации `$config['connection']` или вы можете установить его через `setDatabaseConnection()` (v0.4.1). ```php -$pdo_connection = new PDO('sqlite:test.db'); // например +$pdo_connection = new PDO('sqlite:test.db'); // для примера $user = new User($pdo_connection); // или $user = new User(null, [ 'connection' => $pdo_connection ]); @@ -858,7 +958,7 @@ $user = new User(); $user->setDatabaseConnection($pdo_connection); ``` -Если вы хотите избежать постоянного указания `$database_connection` каждый раз, когда вы вызываете активную запись, есть способы обойти это! +Если вы хотите избежать установки `$database_connection` каждый раз при вызове active record, есть способы обойти это! ```php // index.php или bootstrap.php @@ -875,24 +975,24 @@ class User extends flight\ActiveRecord { } } -// И теперь, без аргументов не требуется! +// И теперь аргументы не требуются! $user = new User(); ``` -> **Примечание:** Если вы планируете unit-тестирование, делать это может создать некоторые проблемы с unit-тестами, но в целом, потому что вы можете инъектировать ваше -подключение с помощью `setDatabaseConnection()` или `$config['connection']`, это не слишком плохо. +> **Примечание:** Если вы планируете unit-тестирование, делать это таким образом может добавить некоторые вызовы для unit-тестирования, но в целом, поскольку вы можете инжектировать ваше +соединение с `setDatabaseConnection()` или `$config['connection']`, это не так плохо. -Если вам нужно обновить подключение к базе данных, например, если вы запускаете долгое CLI-скрипт и вам нужно периодически обновлять подключение, вы можете переустановить соединение с помощью `$your_record->setDatabaseConnection($pdo_connection)`. +Если вам нужно обновить соединение с базой данных, например, если вы запускаете длительный CLI-скрипт и нужно обновлять соединение каждые несколько минут, вы можете переустановить соединение с `$your_record->setDatabaseConnection($pdo_connection)`. -## Участие +## Вклад -Пожалуйста, сделайте это. :D +Пожалуйста, сделайте. :D ### Настройка -Когда вы участвуете, убедитесь, что вы выполняете команду `composer test-coverage`, чтобы поддерживать 100% покрытие тестами (это не истинное покрытие юнит-тестами, больше похоже на интеграционное тестирование). +При вкладе убедитесь, что вы запускаете `composer test-coverage` для поддержания 100% покрытия тестами (это не настоящее покрытие unit-тестами, больше как интеграционное тестирование). -Также убедитесь, что вы выполняете `composer beautify` и `composer phpcs`, чтобы исправить любые ошибки линтинга. +Также убедитесь, что вы запускаете `composer beautify` и `composer phpcs` для исправления любых ошибок линтинга. ## Лицензия diff --git a/content/v3/ru/awesome-plugins/apm.md b/content/v3/ru/awesome-plugins/apm.md index 149f4d1f..3f193d2c 100644 --- a/content/v3/ru/awesome-plugins/apm.md +++ b/content/v3/ru/awesome-plugins/apm.md @@ -1,6 +1,6 @@ # Документация FlightPHP APM -Добро пожаловать в FlightPHP APM — ваш личный тренер по производительности приложения! Это руководство — ваша дорожная карта по настройке, использованию и освоению мониторинга производительности приложений (APM) с FlightPHP. Будь вы охотником за медленными запросами или просто хотите погрузиться в графики задержек, мы вас прикроем. Давайте сделаем ваше приложение быстрее, ваших пользователей счастливее, а сессии отладки — легкими как ветер! +Добро пожаловать в FlightPHP APM — ваш личный тренер по производительности для приложения! Это руководство — ваша дорожная карта по настройке, использованию и освоению мониторинга производительности приложений (APM) с FlightPHP. Будь то поиск медленных запросов или просто желание погрузиться в графики задержек, мы вас прикроем. Давайте сделаем ваше приложение быстрее, ваших пользователей happier, а сессии отладки — легким бризом! Посмотрите [демо](https://flightphp-docs-apm.sky-9.com/apm/dashboard) панели управления для сайта Flight Docs. @@ -8,7 +8,7 @@ ## Почему APM важен -Представьте: ваше приложение — это оживленный ресторан. Без способа отслеживать, сколько времени занимают заказы или где кухня тормозит, вы угадываете, почему клиенты уходят недовольными. APM — ваш су-шеф: он следит за каждым шагом, от входящих запросов до запросов к базе данных, и отмечает всё, что вас замедляет. Медленные страницы отпугивают пользователей (исследования говорят, что 53% уходят, если сайт загружается дольше 3 секунд!), а APM помогает поймать эти проблемы *до* того, как они укусят. Это проактивное спокойствие — меньше моментов «почему это сломано?», больше побед «смотрите, как круто это работает!». +Представьте: ваше приложение — оживленный ресторан. Без способа отслеживать, сколько времени занимают заказы или где кухня тормозит, вы угадываете, почему клиенты уходят недовольными. APM — ваш су-шеф: он следит за каждым шагом, от входящих запросов до запросов к базе данных, и отмечает все, что вас замедляет. Медленные страницы отпугивают пользователей (исследования показывают, что 53% уходят, если сайт загружается дольше 3 секунд!), а APM помогает поймать эти проблемы *до* того, как они укусят. Это проактивное спокойствие — меньше моментов «почему это сломано?», больше побед «смотрите, как круто это работает!». ## Установка @@ -26,10 +26,10 @@ composer require flightphp/apm FlightPHP APM в настоящее время поддерживает следующие базы данных для хранения метрик: -- **SQLite3**: Простая, на основе файлов, идеальна для локальной разработки или небольших приложений. Вариант по умолчанию в большинстве настроек. -- **MySQL/MariaDB**: Идеально для крупных проектов или производственных сред, где нужна надежная, масштабируемая хранилище. +- **SQLite3**: Простая, на основе файлов, идеальна для локальной разработки или небольших приложений. Опция по умолчанию в большинстве настроек. +- **MySQL/MariaDB**: Идеальна для крупных проектов или производственных сред, где нужна надежная, масштабируемая хранилище. -Вы можете выбрать тип базы данных на шаге конфигурации (см. ниже). Убедитесь, что в вашей среде PHP установлены необходимые расширения (например, `pdo_sqlite` или `pdo_mysql`). +Вы можете выбрать тип базы данных на шаге конфигурации (см. ниже). Убедитесь, что в вашей PHP-среде установлены необходимые расширения (например, `pdo_sqlite` или `pdo_mysql`). ## Начало работы @@ -41,22 +41,23 @@ FlightPHP APM в настоящее время поддерживает след ```php use flight\apm\logger\LoggerFactory; +use flight\database\PdoWrapper; use flight\Apm; $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); $Apm = new Apm($ApmLogger); $Apm->bindEventsToFlightInstance($app); -// Если вы добавляете подключение к базе данных -// Должно быть PdoWrapper или PdoQueryCapture из расширений Tracy +// Если вы добавляете соединение с базой данных +// Должно быть PdoWrapper или PdoQueryCapture из Tracy Extensions $pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True обязательно для включения отслеживания в APM. $Apm->addPdoConnection($pdo); ``` **Что здесь происходит?** -- `LoggerFactory::create()` берет вашу конфигурацию (подробнее об этом скоро) и настраивает логгер — по умолчанию SQLite. +- `LoggerFactory::create()` берет вашу конфигурацию (подробнее об этом скоро) и настраивает логгер — SQLite по умолчанию. - `Apm` — звезда: он слушает события Flight (запросы, маршруты, ошибки и т.д.) и собирает метрики. -- `bindEventsToFlightInstance($app)` связывает всё с вашим приложением Flight. +- `bindEventsToFlightInstance($app)` связывает все с вашим приложением Flight. **Про-совет: Сэмплинг** Если ваше приложение загружено, логирование *каждого* запроса может перегрузить систему. Используйте коэффициент сэмплинга (от 0.0 до 1.0): @@ -65,7 +66,7 @@ $Apm->addPdoConnection($pdo); $Apm = new Apm($ApmLogger, 0.1); // Логирует 10% запросов ``` -Это сохраняет производительность высокой, при этом давая надежные данные. +Это сохраняет производительность быстрой, при этом давая вам солидные данные. ### 2. Настройка @@ -93,7 +94,7 @@ php vendor/bin/runway apm:init > Этот процесс также спросит, хотите ли вы запустить миграции для этой настройки. Если вы настраиваете это впервые, ответ — да. **Почему два места?** -Сырые метрики накапливаются быстро (представьте нефильтрованные логи). Воркер обрабатывает их в структурированное назначение для панели. Держит всё в порядке! +Сырые метрики накапливаются быстро (представьте нефильтрованные логи). Воркер обрабатывает их в структурированное назначение для панели. Держит все в порядке! ### 3. Обработка метрик с помощью воркера @@ -109,7 +110,7 @@ php vendor/bin/runway apm:worker - Останавливается, когда закончит или если метрик больше нет. **Держите его запущенным** -Для живых приложений вам понадобится непрерывная обработка. Вот ваши варианты: +Для живых приложений вам понадобится непрерывная обработка. Вот варианты: - **Режим демона**: ```bash @@ -141,12 +142,12 @@ php vendor/bin/runway apm:worker - `--max_messages 1000`: Останавливается после 1000 метрик. - `--timeout 300`: Выходит через 5 минут. -**Зачем это нужно?** -Без воркера ваша панель пуста. Это мост между сырыми логами и полезными инсайтами. +**Зачем беспокоиться?** +Без воркера ваша панель пуста. Это мост между сырыми логами и actionable insights. ### 4. Запуск панели -Посмотрите жизненные показатели вашего приложения: +Посмотрите жизненно важные показатели вашего приложения: ```bash php vendor/bin/runway apm:dashboard @@ -160,7 +161,7 @@ php vendor/bin/runway apm:dashboard ```bash php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php ``` -- `--host 0.0.0.0`: Доступно с любого IP (удобно для удаленного просмотра). +- `--host 0.0.0.0`: Доступно с любого IP (удобно для просмотра удаленно). - `--port 8080`: Используйте другой порт, если 8001 занят. - `--php-path`: Укажите путь к PHP, если он не в PATH. @@ -168,13 +169,13 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l #### Режим производства -Для производства вам может потребоваться несколько техник, чтобы запустить панель, поскольку, вероятно, есть файрволы и другие меры безопасности. Вот несколько вариантов: +Для производства вам может потребоваться попробовать несколько техник, чтобы запустить панель, поскольку, вероятно, есть файрволы и другие меры безопасности. Вот несколько вариантов: -- **Используйте обратный прокси**: Настройте Nginx или Apache для перенаправления запросов на панель. +- **Используйте обратный прокси**: Настройте Nginx или Apache для переадресации запросов на панель. - **SSH-туннель**: Если вы можете SSH на сервер, используйте `ssh -L 8080:localhost:8001 youruser@yourserver`, чтобы туннелировать панель на вашу локальную машину. - **VPN**: Если ваш сервер за VPN, подключитесь к нему и получите доступ к панели напрямую. - **Настройте файрвол**: Откройте порт 8001 для вашего IP или сети сервера (или любого порта, который вы установили). -- **Настройте Apache/Nginx**: Если у вас есть веб-сервер перед приложением, вы можете настроить его на домен или поддомен. Если вы это сделаете, установите корень документов в `/path/to/your/project/vendor/flightphp/apm/dashboard`. +- **Настройте Apache/Nginx**: Если у вас есть веб-сервер перед приложением, вы можете настроить его на домен или поддомен. Если вы это сделаете, вы установите корень документов в `/path/to/your/project/vendor/flightphp/apm/dashboard`. #### Хотите другую панель? @@ -184,14 +185,14 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l Панель — ваш штаб APM: вот что вы увидите: -- **Журнал запросов**: Каждый запрос с временной меткой, URL, кодом ответа и общим временем. Нажмите «Детали» для middleware, запросов и ошибок. +- **Лог запросов**: Каждый запрос с временной меткой, URL, кодом ответа и общим временем. Нажмите «Детали» для middleware, запросов и ошибок. - **Самые медленные запросы**: Топ-5 запросов, поглощающих время (например, «/api/heavy» за 2.5с). - **Самые медленные маршруты**: Топ-5 маршрутов по среднему времени — отлично для выявления паттернов. - **Уровень ошибок**: Процент неудачных запросов (например, 2.3% 500-х). -- **Перцентили задержек**: 95-й (p95) и 99-й (p99) времена ответа — знайте худшие сценарии. +- **Перцентили задержек**: 95-й (p95) и 99-й (p99) времена ответа — знайте ваши худшие сценарии. - **График кодов ответа**: Визуализируйте 200-е, 404-е, 500-е со временем. - **Длинные запросы/Middleware**: Топ-5 медленных вызовов базы данных и слоев middleware. -- **Попадания/промахи кэша**: Как часто кэш спасает день. +- **Попадания/промахи кэша**: Как часто ваш кэш спасает ситуацию. **Дополнительно**: - Фильтруйте по «Последний час», «Последний день» или «Последняя неделя». @@ -202,7 +203,7 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l - Общее время: 150мс - Middleware: `AuthMiddleware->handle` (50мс) - Запрос: `SELECT * FROM users` (80мс) -- Кэш: Попадание в `user_list` (5мс) +- Кэш: Попадание на `user_list` (5мс) ## Добавление пользовательских событий @@ -218,8 +219,8 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ])); ``` -**Где это появится?** -В деталях запроса панели под «Пользовательские события» — расширяемо с красивым форматированием JSON. +**Где это отображается?** +В деталях запроса панели под «Custom Events» — расширяемо с красивым форматированием JSON. **Пример использования**: ```php @@ -251,8 +252,8 @@ $Apm->addPdoConnection($pdo); **Внимание**: - **Опционально**: Пропустите это, если не нужно отслеживание БД. -- **Только PdoWrapper**: Основной PDO еще не подключен — следите за обновлениями! -- **Предупреждение о производительности**: Логирование каждого запроса на сайте с тяжелой БД может замедлить вещи. Используйте сэмплинг (`$Apm = new Apm($ApmLogger, 0.1)`), чтобы облегчить нагрузку. +- **Только PdoWrapper**: Core PDO еще не подключен — следите за обновлениями! +- **Предупреждение о производительности**: Логирование каждого запроса на сайте с тяжелой БД может замедлить. Используйте сэмплинг (`$Apm = new Apm($ApmLogger, 0.1)`), чтобы снизить нагрузку. **Пример вывода**: - Запрос: `SELECT name FROM products WHERE price > 100` @@ -274,7 +275,7 @@ php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ``` Работает час, обрабатывая 100 метрик за раз. -## ID запроса в приложении +## Request ID в приложении Каждый запрос имеет уникальный ID запроса для отслеживания. Вы можете использовать этот ID в вашем приложении для корреляции логов и метрик. Например, вы можете добавить ID запроса на страницу ошибок: @@ -284,7 +285,7 @@ Flight::map('error', function($message) { $requestId = Flight::response()->getHeader('X-Flight-Request-Id'); // Кроме того, вы могли бы получить его из переменной Flight - // Этот метод не будет работать хорошо в swoole или других асинхронных платформах. + // Этот метод не будет хорошо работать в swoole или других асинхронных платформах. // $requestId = Flight::get('apm.request_id'); echo "Error: $message (Request ID: $requestId)"; @@ -300,7 +301,17 @@ php vendor/bin/runway apm:migrate ``` Это запустит любые необходимые миграции для обновления схемы базы данных до последней версии. -**Примечание:** Если ваша база данных APM большая по размеру, эти миграции могут занять некоторое время. Вы можете захотеть запустить эту команду в непиковые часы. +**Примечание:** Если ваша база данных APM большая по размеру, эти миграции могут занять некоторое время. Вы можете запустить эту команду в непиковые часы. + +### Обновление с 0.4.3 -> 0.5.0 + +Если вы обновляетесь с 0.4.3 до 0.5.0, вам нужно запустить следующую команду: + +```bash +php vendor/bin/runway apm:config-migrate +``` + +Это мигрирует вашу конфигурацию из старого формата с использованием файла `.runway-config.json` в новый формат, который хранит ключ/значения в файле `config.php`. ## Очистка старых данных @@ -324,10 +335,10 @@ php vendor/bin/runway apm:purge --days 7 - **Нет данных в панели?** - Запущен ли воркер? Проверьте `ps aux | grep apm:worker`. - Пути конфигурации совпадают? Проверьте, что DSN в `.runway-config.json` указывают на реальные файлы. - - Запустите `php vendor/bin/runway apm:worker` вручную для обработки ожидающих метрик. + - Запустите `php vendor/bin/runway apm:worker` вручную, чтобы обработать ожидающие метрики. - **Ошибки воркера?** - - Загляните в ваши файлы SQLite (например, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). + - Загляните в ваши SQLite-файлы (например, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - Проверьте логи PHP на наличие стек-трейсов. - **Панель не запускается?** @@ -336,12 +347,12 @@ php vendor/bin/runway apm:purge --days 7 - Файрвол блокирует? Откройте порт или используйте `--host localhost`. - **Слишком медленно?** - - Уменьшите коэффициент сэмплинга: `$Apm = new Apm($ApmLogger, 0.05)` (5%). + - Снизьте коэффициент сэмплинга: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - Уменьшите размер пакета: `--batch_size 20`. - **Не отслеживает исключения/ошибки?** - - Если у вас включен [Tracy](https://tracy.nette.org/) для проекта, он переопределит обработку ошибок Flight. Вам нужно отключить Tracy и убедиться, что `Flight::set('flight.handle_errors', true);` установлено. + - Если у вас включен [Tracy](https://tracy.nette.org/) для вашего проекта, он переопределит обработку ошибок Flight. Вам нужно отключить Tracy и убедиться, что `Flight::set('flight.handle_errors', true);` установлено. - **Не отслеживает запросы к базе данных?** - - Убедитесь, что вы используете `PdoWrapper` для подключений к базе данных. - - Убедитесь, что последний аргумент в конструкторе `true`. \ No newline at end of file + - Убедитесь, что вы используете `PdoWrapper` для соединений с базой данных. + - Убедитесь, что последний аргумент в конструкторе — `true`. \ No newline at end of file diff --git a/content/v3/ru/awesome-plugins/awesome_plugins.md b/content/v3/ru/awesome-plugins/awesome_plugins.md index 144f4c55..707230f6 100644 --- a/content/v3/ru/awesome-plugins/awesome_plugins.md +++ b/content/v3/ru/awesome-plugins/awesome_plugins.md @@ -1,98 +1,97 @@ -# Крутые плагины +# Крутой Плагины -Flight невероятно расширяем. Существует множество плагинов, которые можно использовать для добавления функциональности в ваше приложение Flight. Некоторые из них официально поддерживаются командой Flight, а другие — это микро/лайт-библиотеки, чтобы помочь вам начать. +Flight невероятно расширяем. Существует множество плагинов, которые можно использовать для добавления функциональности в ваше приложение Flight. Некоторые официально поддерживаются командой Flight, а другие — это микробиблиотеки или лайт-библиотеки, чтобы помочь вам начать. ## Документация API -Документация API крайне важна для любого API. Она помогает разработчикам понять, как взаимодействовать с вашим API и чего ожидать в ответ. Есть несколько инструментов, доступных для генерации документации API для ваших проектов Flight. +Документация API крайне важна для любого API. Она помогает разработчикам понять, как взаимодействовать с вашим API и чего ожидать в ответ. Существует несколько инструментов, которые помогут вам генерировать документацию API для ваших проектов Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) — Пост в блоге, написанный Daniel Schreiber, о том, как использовать спецификацию OpenAPI с FlightPHP для построения вашего API с использованием подхода API first. -- [SwaggerUI](https://github.com/zircote/swagger-php) — Swagger UI — отличный инструмент для генерации документации API для ваших проектов Flight. Его очень легко использовать, и его можно настроить под ваши нужды. Это PHP-библиотека для генерации документации Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Блог-пост, написанный Daniel Schreiber, о том, как использовать спецификацию OpenAPI с FlightPHP для построения вашего API с использованием подхода API first. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI — отличный инструмент для генерации документации API для ваших проектов Flight. Его очень легко использовать, и его можно настроить под ваши нужды. Это PHP-библиотека, которая поможет вам генерировать документацию Swagger. -## Мониторинг производительности приложений (APM) +## Мониторинг Производительности Приложений (APM) Мониторинг производительности приложений (APM) крайне важен для любого приложения. Он помогает понять, как работает ваше приложение и где находятся узкие места. Существует множество инструментов APM, которые можно использовать с Flight. +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM — простая библиотека APM, которую можно использовать для мониторинга приложений Flight. Она может использоваться для мониторинга производительности вашего приложения и помощи в выявлении узких мест. -- official [flightphp/apm](/awesome-plugins/apm) — Flight APM — это простая библиотека APM, которую можно использовать для мониторинга приложений Flight. Она может использоваться для мониторинга производительности вашего приложения и помощи в выявлении узких мест. +## Async -## Асинхронность +Flight уже является быстрым фреймворком, но добавление к нему турбо-двигателя делает всё ещё более веселым (и challenging)! -Flight уже является быстрым фреймворком, но добавление турбо-двигателя делает всё ещё веселее (и сложнее)! - -- [flightphp/async](/awesome-plugins/async) — Официальная библиотека Flight Async. Эта библиотека — простой способ добавить асинхронную обработку в ваше приложение. Она использует Swoole/Openswoole под капотом, чтобы предоставить простой и эффективный способ запуска задач асинхронно. +- [flightphp/async](/awesome-plugins/async) - Официальная библиотека Flight Async. Эта библиотека — простой способ добавить асинхронную обработку в ваше приложение. Она использует Swoole/Openswoole под капотом, чтобы предоставить простой и эффективный способ запуска задач асинхронно. ## Авторизация/Разрешения -Авторизация и разрешения крайне важны для любого приложения, которое требует контроля над тем, кто может получить доступ к чему. +Авторизация и разрешения крайне важны для любого приложения, которое требует контроля за тем, кто может получить доступ к чему. -- official [flightphp/permissions](/awesome-plugins/permissions) — Официальная библиотека Flight Permissions. Эта библиотека — простой способ добавить разрешения на уровне пользователя и приложения в ваше приложение. +- official [flightphp/permissions](/awesome-plugins/permissions) - Официальная библиотека Flight Permissions. Эта библиотека — простой способ добавить разрешения на уровне пользователя и приложения в ваше приложение. ## Кэширование Кэширование — отличный способ ускорить ваше приложение. Существует множество библиотек кэширования, которые можно использовать с Flight. -- official [flightphp/cache](/awesome-plugins/php-file-cache) — Легкая, простая и автономная PHP-библиотека кэширования в файле. +- official [flightphp/cache](/awesome-plugins/php-file-cache) - Легкий, простой и автономный класс PHP для кэширования в файле ## CLI -CLI-приложения — отличный способ взаимодействовать с вашим приложением. Их можно использовать для генерации контроллеров, отображения всех маршрутов и многого другого. +CLI-приложения — отличный способ взаимодействовать с вашим приложением. Вы можете использовать их для генерации контроллеров, отображения всех маршрутов и многого другого. -- official [flightphp/runway](/awesome-plugins/runway) — Runway — это CLI-приложение, которое помогает управлять вашими приложениями Flight. +- official [flightphp/runway](/awesome-plugins/runway) - Runway — CLI-приложение, которое помогает управлять вашими приложениями Flight. -## Куки +## Cookies -Куки — отличный способ хранить небольшие объёмы данных на стороне клиента. Их можно использовать для хранения предпочтений пользователя, настроек приложения и многого другого. +Cookies — отличный способ хранить небольшие объемы данных на стороне клиента. Их можно использовать для хранения предпочтений пользователя, настроек приложения и многого другого. -- [overclokk/cookie](/awesome-plugins/php-cookie) — PHP Cookie — это PHP-библиотека, которая предоставляет простой и эффективный способ управления куки. +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie — PHP-библиотека, которая предоставляет простой и эффективный способ управления cookies. ## Отладка -Отладка крайне важна при разработке в локальной среде. Есть несколько плагинов, которые могут улучшить ваш опыт отладки. +Отладка крайне важна при разработке в локальной среде. Существует несколько плагинов, которые могут улучшить ваш опыт отладки. -- [tracy/tracy](/awesome-plugins/tracy) — Это полнофункциональный обработчик ошибок, который можно использовать с Flight. У него есть несколько панелей, которые могут помочь вам отлаживать ваше приложение. Его также очень легко расширять и добавлять свои собственные панели. -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) — Используется с обработчиком ошибок [Tracy](/awesome-plugins/tracy), этот плагин добавляет несколько дополнительных панелей для помощи в отладке специально для проектов Flight. +- [tracy/tracy](/awesome-plugins/tracy) - Это полнофункциональный обработчик ошибок, который можно использовать с Flight. У него есть несколько панелей, которые могут помочь вам отлаживать ваше приложение. Его также очень легко расширять и добавлять свои собственные панели. +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Используется с обработчиком ошибок [Tracy](/awesome-plugins/tracy), этот плагин добавляет несколько дополнительных панелей для помощи в отладке специально для проектов Flight. -## Базы данных +## Базы Данных -Базы данных — основа большинства приложений. Это способ хранения и извлечения данных. Некоторые библиотеки баз данных — просто обёртки для написания запросов, а некоторые — полноценные ORM. +Базы данных — основа большинства приложений. Это способ хранения и извлечения данных. Некоторые библиотеки баз данных — просто обертки для написания запросов, а некоторые — полноценные ORM. -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) — Официальная обёртка Flight PDO, которая является частью ядра. Это простая обёртка, чтобы упростить процесс написания и выполнения запросов. Это не ORM. -- official [flightphp/active-record](/awesome-plugins/active-record) — Официальный ORM/Mapper Flight ActiveRecord. Отличная маленькая библиотека для лёгкого извлечения и хранения данных в вашей базе данных. -- [byjg/php-migration](/awesome-plugins/migrations) — Плагин для отслеживания всех изменений базы данных в вашем проекте. +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Официальная обертка Flight PDO, которая является частью ядра. Это простая обертка, которая помогает упростить процесс написания запросов и их выполнения. Это не ORM. +- official [flightphp/active-record](/awesome-plugins/active-record) - Официальный ORM/Mapper Flight ActiveRecord. Отличная маленькая библиотека для легкого извлечения и хранения данных в вашей базе данных. +- [byjg/php-migration](/awesome-plugins/migrations) - Плагин для отслеживания всех изменений в базе данных для вашего проекта. ## Шифрование Шифрование крайне важно для любого приложения, которое хранит конфиденциальные данные. Шифрование и дешифрование данных не так уж сложно, но правильное хранение ключа шифрования [может](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [быть](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [сложным](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Самое важное — никогда не хранить ключ шифрования в публичной директории или коммитить его в репозиторий кода. -- [defuse/php-encryption](/awesome-plugins/php-encryption) — Это библиотека, которую можно использовать для шифрования и дешифрования данных. Запуск и работа с ней довольно просты для начала шифрования и дешифрования данных. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - Это библиотека, которую можно использовать для шифрования и дешифрования данных. Запуск и использование довольно просты для начала шифрования и дешифрования данных. -## Очередь заданий +## Очередь Задач -Очереди заданий очень полезны для асинхронной обработки задач. Это может быть отправка email, обработка изображений или что-то, что не требует выполнения в реальном времени. +Очереди задач очень полезны для асинхронной обработки задач. Это может быть отправка email, обработка изображений или что-то, что не требует выполнения в реальном времени. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) — Simple Job Queue — это библиотека, которую можно использовать для асинхронной обработки заданий. Её можно использовать с beanstalkd, MySQL/MariaDB, SQLite и PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue — библиотека, которую можно использовать для асинхронной обработки задач. Её можно использовать с beanstalkd, MySQL/MariaDB, SQLite и PostgreSQL. ## Сессии Сессии не очень полезны для API, но для построения веб-приложения сессии могут быть крайне важны для поддержания состояния и информации о входе. -- official [flightphp/session](/awesome-plugins/session) — Официальная библиотека Flight Session. Это простая библиотека сессий, которую можно использовать для хранения и извлечения данных сессии. Она использует встроенную обработку сессий PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) — PHP Session Manager (неблокирующий, flash, сегмент, шифрование сессий). Использует PHP open_ssl для опционального шифрования/дешифрования данных сессии. +- official [flightphp/session](/awesome-plugins/session) - Официальная библиотека Flight Session. Это простая библиотека сессий, которую можно использовать для хранения и извлечения данных сессии. Она использует встроенную обработку сессий PHP. +- [Ghostff/Session](/awesome-plugins/ghost-session) - Менеджер сессий PHP (неблокирующий, flash, сегмент, шифрование сессии). Использует PHP open_ssl для опционального шифрования/дешифрования данных сессии. ## Шаблонизация Шаблонизация — основа любого веб-приложения с UI. Существует множество шаблонизаторов, которые можно использовать с Flight. -- deprecated [flightphp/core View](/learn#views) — Это очень базовый шаблонизатор, который является частью ядра. Не рекомендуется использовать, если в вашем проекте больше нескольких страниц. -- [latte/latte](/awesome-plugins/latte) — Latte — полнофункциональный шаблонизатор, который очень легко использовать и ближе к синтаксису PHP, чем Twig или Smarty. Его также очень легко расширять и добавлять свои фильтры и функции. -- [knifelemon/comment-template](/awesome-plugins/comment-template) — CommentTemplate — мощный PHP-шаблонизатор с компиляцией ассетов, наследованием шаблонов и обработкой переменных. Поддерживает автоматическую минификацию CSS/JS, кэширование, кодирование Base64 и опциональную интеграцию с фреймворком Flight PHP. +- deprecated [flightphp/core View](/learn#views) - Это очень базовый шаблонизатор, который является частью ядра. Не рекомендуется использовать, если у вас больше нескольких страниц в проекте. +- [latte/latte](/awesome-plugins/latte) - Latte — полнофункциональный шаблонизатор, который очень легко использовать и ближе к синтаксису PHP, чем Twig или Smarty. Его также очень легко расширять и добавлять свои собственные фильтры и функции. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate — мощный шаблонизатор PHP с компиляцией ассетов, наследованием шаблонов и обработкой переменных. Функции включают автоматическую минификацию CSS/JS, кэширование, кодирование Base64 и опциональную интеграцию с фреймворком Flight PHP. ## Интеграция с WordPress Хотите использовать Flight в вашем проекте WordPress? Для этого есть удобный плагин! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) — Этот плагин WordPress позволяет запускать Flight параллельно с WordPress. Он идеален для добавления пользовательских API, микросервисов или даже полноценных приложений на ваш сайт WordPress с использованием фреймворка Flight. Суперполезно, если вы хотите лучшее из двух миров! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Этот плагин WordPress позволяет запускать Flight прямо рядом с WordPress. Он идеален для добавления кастомных API, микросервисов или даже полноценных приложений на ваш сайт WordPress с использованием фреймворка Flight. Супер полезно, если вы хотите лучшее из двух миров! -## Вклад в проект +## Вклад Есть плагин, которым вы хотите поделиться? Отправьте pull request, чтобы добавить его в список! \ No newline at end of file diff --git a/content/v3/ru/awesome-plugins/comment_template.md b/content/v3/ru/awesome-plugins/comment_template.md index 3ce888c6..f287da4d 100644 --- a/content/v3/ru/awesome-plugins/comment_template.md +++ b/content/v3/ru/awesome-plugins/comment_template.md @@ -1,18 +1,18 @@ # CommentTemplate -[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) — это мощный шаблонизатор PHP с компиляцией активов, наследованием шаблонов и обработкой переменных. Он предоставляет простой и гибкий способ управления шаблонами с встроенной минификацией CSS/JS и кэшированием. +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) — это мощный шаблонный движок для PHP с компиляцией ресурсов, наследованием шаблонов и обработкой переменных. Он предоставляет простой и гибкий способ управления шаблонами с встроенной минификацией CSS/JS и кэшированием. ## Особенности -- **Наследование шаблонов**: Использование макетов и включение других шаблонов -- **Компиляция активов**: Автоматическая минификация и кэширование CSS/JS +- **Наследование шаблонов**: Используйте макеты и включайте другие шаблоны +- **Компиляция ресурсов**: Автоматическая минификация и кэширование CSS/JS - **Обработка переменных**: Переменные шаблонов с фильтрами и командами -- **Кодирование Base64**: Встраивание активов как data URI -- **Интеграция с фреймворком Flight**: Необязательная интеграция с фреймворком PHP Flight +- **Кодирование Base64**: Встраивание ресурсов как data URI +- **Интеграция с Flight Framework**: Опциональная интеграция с PHP-фреймворком Flight ## Установка -Установите с помощью composer. +Установите с помощью Composer. ```bash composer require knifelemon/comment-template @@ -33,16 +33,16 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Корневая директория (где находится index.php) - корень документа вашего веб-приложения + // Корневая директория (где находится index.php) — корень документов вашего веб-приложения $engine->setPublicPath(__DIR__); - // Директория файлов шаблонов - поддерживает относительные и абсолютные пути - $engine->setSkinPath('views'); // Относительно публичного пути + // Директория файлов шаблонов — поддерживает как относительные, так и абсолютные пути + $engine->setSkinPath('views'); // Относительно пути public - // Где будут храниться скомпилированные активы - поддерживает относительные и абсолютные пути - $engine->setAssetPath('assets'); // Относительно публичного пути + // Куда будут сохраняться скомпилированные ресурсы — поддерживает как относительные, так и абсолютные пути + $engine->setAssetPath('assets'); // Относительно пути public - // Расширение файла шаблона + // Расширение файлов шаблонов $engine->setFileExtension('.php'); }); @@ -63,10 +63,10 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__, // publicPath - корневая директория (где находится index.php) - 'views', // skinPath - путь шаблонов (поддерживает относительные/абсолютные) - 'assets', // assetPath - путь скомпилированных активов (поддерживает относительные/абсолютные) - '.php' // fileExtension - расширение файла шаблона + __DIR__, // publicPath — корневая директория (где находится index.php) + 'views', // skinPath — путь к шаблонам (поддерживает относительные/абсолютные) + 'assets', // assetPath — путь к скомпилированным ресурсам (поддерживает относительные/абсолютные) + '.php' // fileExtension — расширение файлов шаблонов ]); $app->map('render', function(string $template, array $data) use ($app): void { @@ -76,80 +76,80 @@ $app->map('render', function(string $template, array $data) use ($app): void { ## Конфигурация путей -CommentTemplate обеспечивает интеллектуальную обработку путей для относительных и абсолютных путей: +CommentTemplate предоставляет интеллектуальную обработку путей как для относительных, так и для абсолютных путей: ### Публичный путь -**Публичный путь** — это корневая директория вашего веб-приложения, обычно где находится `index.php`. Это корень документа, откуда веб-серверы предоставляют файлы. +**Публичный путь** — это корневая директория вашего веб-приложения, обычно там, где находится `index.php`. Это корень документов, из которого веб-серверы обслуживают файлы. ```php // Пример: если ваш index.php находится в /var/www/html/myapp/index.php $template->setPublicPath('/var/www/html/myapp'); // Корневая директория -// Пример Windows: если ваш index.php находится в C:\xampp\htdocs\myapp\index.php +// Пример для Windows: если ваш index.php находится в C:\xampp\htdocs\myapp\index.php $template->setPublicPath('C:\\xampp\\htdocs\\myapp'); ``` -### Конфигурация пути шаблонов +### Конфигурация пути к шаблонам -Путь шаблонов поддерживает как относительные, так и абсолютные пути: +Путь к шаблонам поддерживает как относительные, так и абсолютные пути: ```php $template = new Engine(); $template->setPublicPath('/var/www/html/myapp'); // Корневая директория (где находится index.php) -// Относительные пути - автоматически объединяются с публичным путем +// Относительные пути — автоматически объединяются с публичным путем $template->setSkinPath('views'); // → /var/www/html/myapp/views/ $template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ -// Абсолютные пути - используются как есть (Unix/Linux) +// Абсолютные пути — используются как есть (Unix/Linux) $template->setSkinPath('/var/www/templates'); // → /var/www/templates/ $template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ -// Абсолютные пути Windows +// Абсолютные пути для Windows $template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ $template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ -// UNC пути (сетевые ресурсы Windows) +// UNC-пути (сетевые ресурсы Windows) $template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ ``` -### Конфигурация пути активов +### Конфигурация пути к ресурсам -Путь активов также поддерживает как относительные, так и абсолютные пути: +Путь к ресурсам также поддерживает как относительные, так и абсолютные пути: ```php -// Относительные пути - автоматически объединяются с публичным путем +// Относительные пути — автоматически объединяются с публичным путем $template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ $template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ -// Абсолютные пути - используются как есть (Unix/Linux) +// Абсолютные пути — используются как есть (Unix/Linux) $template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ $template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ -// Абсолютные пути Windows +// Абсолютные пути для Windows $template->setAssetPath('C:\\www\\static'); // → C:\www\static\ $template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ -// UNC пути (сетевые ресурсы Windows) +// UNC-пути (сетевые ресурсы Windows) $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ ``` **Умное определение путей:** -- **Относительные пути**: Без начальных разделителей (`/`, `\`) или букв дисков -- **Unix абсолютные**: Начинаются с `/` (напр. `/var/www/assets`) -- **Windows абсолютные**: Начинаются с буквы диска (напр. `C:\www`, `D:/assets`) -- **UNC пути**: Начинаются с `\\` (напр. `\\server\share`) +- **Относительные пути**: Без ведущих разделителей (`/`, `\`) или букв дисков +- **Абсолютные Unix**: Начинаются с `/` (например, `/var/www/assets`) +- **Абсолютные Windows**: Начинаются с буквы диска (например, `C:\www`, `D:/assets`) +- **UNC-пути**: Начинаются с `\\` (например, `\\server\share`) **Как это работает:** -- Все пути автоматически разрешаются на основе типа (относительный vs абсолютный) +- Все пути автоматически разрешаются в зависимости от типа (относительный vs абсолютный) - Относительные пути объединяются с публичным путем -- `@css` и `@js` создают минимизированные файлы в: `{resolvedAssetPath}/css/` или `{resolvedAssetPath}/js/` +- `@css` и `@js` создают минифицированные файлы в: `{resolvedAssetPath}/css/` или `{resolvedAssetPath}/js/` - `@asset` копирует отдельные файлы в: `{resolvedAssetPath}/{relativePath}` - `@assetDir` копирует директории в: `{resolvedAssetPath}/{relativePath}` -- Умное кеширование: файлы копируются только когда источник новее цели +- Умное кэширование: файлы копируются только если исходный файл новее целевого ## Директивы шаблонов @@ -177,15 +177,15 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse

          {$content}

          ``` -### Управление активами +### Управление ресурсами -#### Файлы CSS +#### CSS-файлы ```html - + ``` -#### Файлы JavaScript +#### JavaScript-файлы CommentTemplate поддерживает различные стратегии загрузки JavaScript: ```html @@ -195,18 +195,18 @@ CommentTemplate поддерживает различные стратегии - - - + + + ``` -#### Директивы активов в файлах CSS/JS +#### Директивы ресурсов в CSS/JS-файлах -CommentTemplate также обрабатывает директивы активов в файлах CSS и JavaScript во время компиляции: +CommentTemplate также обрабатывает директивы ресурсов внутри CSS- и JavaScript-файлов во время компиляции: **Пример CSS:** ```css -/* В ваших файлах CSS */ +/* В ваших CSS-файлах */ @font-face { font-family: 'CustomFont'; src: url('') format('woff2'); @@ -223,7 +223,7 @@ CommentTemplate также обрабатывает директивы акти **Пример JavaScript:** ```javascript -/* В ваших файлах JS */ +/* В ваших JS-файлах */ const fontUrl = ''; const imageData = ''; ``` @@ -241,14 +241,14 @@ const imageData = '';
          ``` -#### Копирование активов +#### Копирование ресурсов ```html - + ``` ** Пример: ** ```html - + Hero Banner Скачать брошюру @@ -263,7 +263,7 @@ const imageData = ''; ``` ** Пример: ** ```html - +
          @@ -271,7 +271,7 @@ const imageData = '';
          -

          Основной контент здесь...

          +

          Основное содержимое здесь...

          @@ -288,46 +288,46 @@ const imageData = ''; #### Фильтры переменных ```html -{$title|upper} -{$content|lower} -{$html|striptag} -{$text|escape} -{$multiline|nl2br} -{$html|br2nl} -{$description|trim} -{$subject|title} +{$title|upper} +{$content|lower} +{$html|striptag} +{$text|escape} +{$multiline|nl2br} +{$html|br2nl} +{$description|trim} +{$subject|title} ``` #### Команды переменных ```html -{$title|default=Default Title} +{$title|default=Default Title} {$name|concat= (Admin)} ``` -#### Цепочка нескольких фильтров +#### Команды переменных ```html {$content|striptag|trim|escape} ``` ### Комментарии -Комментарии шаблонов полностью удаляются из вывода и не появляются в финальном HTML: +Комментарии шаблонов полностью удаляются из вывода и не появляются в итоговом HTML: ```html {* Это однострочный комментарий шаблона *} {* - Это многострочный + Это многострочный комментарий шаблона - на несколько строк + который занимает несколько строк *}

          {$title}

          -{* Отладочный комментарий: проверяем работает ли переменная title *} +{* Отладочный комментарий: проверка работы переменной title *}

          {$content}

          ``` -**Примечание**: Комментарии шаблонов `{* ... *}` отличаются от HTML комментариев ``. Комментарии шаблонов удаляются во время обработки и никогда не достигают браузера. +**Примечание**: Комментарии шаблонов `{* ... *}` отличаются от HTML-комментариев ``. Комментарии шаблонов удаляются во время обработки и никогда не доходят до браузера. ## Структура примера проекта @@ -347,7 +347,7 @@ project/ │ │ └── bootstrap.min.js │ └── homepage.php ├── public/ -│ └── assets/ # Сгенерированные активы +│ └── assets/ # Сгенерированные ресурсы │ ├── css/ │ └── js/ └── vendor/ diff --git a/content/v3/ru/awesome-plugins/runway.md b/content/v3/ru/awesome-plugins/runway.md index fd3f6a4a..dafbb0d3 100644 --- a/content/v3/ru/awesome-plugins/runway.md +++ b/content/v3/ru/awesome-plugins/runway.md @@ -1,27 +1,27 @@ -# Взлетная полоса +# Runway -Взлетная полоса — это приложение CLI, которое помогает управлять приложениями Flight. Он может генерировать контроллеры, отображать все маршруты и многое другое. Он основан на отличной библиотеке [adhocore/php-cli](https://github.com/adhocore/php-cli). +Runway — это CLI-приложение, которое помогает управлять вашими приложениями Flight. Оно может генерировать контроллеры, отображать все маршруты и многое другое. Оно основано на отличной библиотеке [adhocore/php-cli](https://github.com/adhocore/php-cli). -[Нажмите здесь](https://github.com/flightphp/runway), чтобы просмотреть код. +Нажмите [здесь](https://github.com/flightphp/runway), чтобы просмотреть код. ## Установка -Установите через composer. +Установите с помощью composer. ```bash composer require flightphp/runway ``` -## Основная настройка +## Базовая конфигурация -Первый раз, когда вы запускаете Взлетную полосу, она проведет вас через процесс настройки и создаст файл конфигурации `.runway.json` в корне вашего проекта. Этот файл будет содержать несколько необходимых конфигураций для работы Взлетной полосы должным образом. +В первый раз, когда вы запустите Runway, он проведёт вас через процесс настройки и создаст файл конфигурации `.runway.json` в корне вашего проекта. Этот файл будет содержать некоторые необходимые конфигурации для правильной работы Runway. ## Использование -У Взлетной полосы есть несколько команд, которые вы можете использовать для управления вашим приложением Flight. Есть два простых способа использования Взлетной полосы. +Runway имеет ряд команд, которые вы можете использовать для управления вашим приложением Flight. Есть два простых способа использовать Runway. -1. Если вы используете каркас проекта, вы можете запустить `php runway [команда]` из корня вашего проекта. -1. Если вы используете Взлетную полосу как пакет, установленный через composer, вы можете запустить `vendor/bin/runway [команда]` из корня вашего проекта. +1. Если вы используете скелетный проект, вы можете запустить `php runway [command]` из корня вашего проекта. +1. Если вы используете Runway как пакет, установленный через composer, вы можете запустить `vendor/bin/runway [command]` из корня вашего проекта. Для любой команды вы можете передать флаг `--help`, чтобы получить больше информации о том, как использовать команду. @@ -31,23 +31,23 @@ php runway routes --help Вот несколько примеров: -### Создание контроллера +### Генерация контроллера -На основе конфигурации в вашем файле `.runway.json` по умолчанию контроллер будет создан для вас в каталоге `app/controllers/`. +На основе конфигурации в вашем файле `.runway.json` по умолчанию будет сгенерирован контроллер в директории `app/controllers/`. ```bash php runway make:controller MyController ``` -### Создание модели Active Record +### Генерация модели Active Record -На основе конфигурации в вашем файле `.runway.json` по умолчанию модель будет создана для вас в каталоге `app/records/`. +На основе конфигурации в вашем файле `.runway.json` по умолчанию будет сгенерирована модель в директории `app/records/`. ```bash php runway make:record users ``` -Если у вас, например, есть таблица `users` с такой схемой: `id`, `name`, `email`, `created_at`, `updated_at`, будет создан файл, подобный следующему, в файле `app/records/UserRecord.php`: +Например, если у вас есть таблица `users` со следующей схемой: `id`, `name`, `email`, `created_at`, `updated_at`, то в файле `app/records/UserRecord.php` будет создан файл, похожий на следующий: ```php $config JSON конфигурация из .runway-config.json + * @param array $config JSON-конфигурация из .runway-config.json */ public function __construct(array $config) { parent::__construct('make:example', 'Создать пример для документации', $config); - $this->argument('', 'Имя смешной гифки'); + $this->argument('', 'Имя забавного GIF'); } /** @@ -138,17 +138,56 @@ class ExampleCommand extends AbstractBaseCommand * * @return void */ - public function execute(string $controller) + public function execute() { $io = $this->app()->io(); $io->info('Создание примера...'); - // Сделайте здесь что-то + // Сделайте что-то здесь $io->ok('Пример создан!'); } } ``` -Смотрите [Документация adhocore/php-cli](https://github.com/adhocore/php-cli) для получения дополнительной информации о том, как создавать свои собственные команды в вашем приложении Flight! \ No newline at end of file +См. [Документацию adhocore/php-cli](https://github.com/adhocore/php-cli) для получения дополнительной информации о том, как создавать свои собственные пользовательские команды для вашего приложения Flight! + +### Конфигурация + +Если вам нужно настроить конфигурацию для Runway, вы можете создать файл `.runway-config.json` в корне вашего проекта. Ниже приведены некоторые дополнительные конфигурации, которые вы можете установить: + +```js +{ + + // Здесь находится директория вашего приложения + "app_root": "app/", + + // Это директория, где находится ваш корневой индексный файл + "index_root": "public/", + + // Это пути к корням других проектов + "root_paths": [ + "/home/user/different-project", + "/var/www/another-project" + ], + + // Базовые пути, скорее всего, не нужно настраивать, но они здесь, если вы хотите + "base_paths": { + "/includes/libs/vendor", // если у вас есть действительно уникальный путь для директории vendor или чего-то подобного + }, + + // Финальные пути — это расположения внутри проекта для поиска файлов команд + "final_paths": { + "src/diff-path/commands", + "app/module/admin/commands", + }, + + // Если вы хотите просто добавить полный путь, вперед (абсолютный или относительный к корню проекта) + "paths": [ + "/home/user/different-project/src/diff-path/commands", + "/var/www/another-project/app/module/admin/commands", + "app/my-unique-commands" + ] +} +``` \ No newline at end of file diff --git a/content/v3/ru/examples.md b/content/v3/ru/examples.md index d50aa5f7..0dde426b 100644 --- a/content/v3/ru/examples.md +++ b/content/v3/ru/examples.md @@ -3,24 +3,25 @@ У вас есть два варианта для начала работы с новым проектом Flight: - [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Более полный пример с контроллерами и представлениями. -- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Один файл, содержащий всё необходимое для запуска вашего приложения в одном простом файле. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Один файл, содержащий всё необходимое для запуска вашего приложения в простом единственном файле. Примеры, внесённые сообществом: - [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP с директориями Laravel, с инструментами PHP + GH Actions -- [fleact](https://github.com/flightphp/fleact) - Стартовый комплект FlightPHP с интеграцией ReactJS. -- [flastro](https://github.com/flightphp/flastro) - Стартовый комплект FlightPHP с интеграцией Astro. -- [velt](https://github.com/flightphp/velt) - Velt — это быстрый и простой шаблон Svelte для старта с бэкендом на FlightPHP. +- [fleact](https://github.com/flightphp/fleact) - Стартовый набор FlightPHP с интеграцией ReactJS. +- [flastro](https://github.com/flightphp/flastro) - Стартовый набор FlightPHP с интеграцией Astro. +- [velt](https://github.com/flightphp/velt) - Velt — это быстрый и простой шаблон стартера Svelte с бэкендом на FlightPHP. -## Нужен ли вам источник вдохновения? +## Нужен ли вам некоторый вдохновение? -Хотя эти проекты не спонсируются официально командой Flight, они могут дать вам идеи о том, как структурировать свои собственные проекты, построенные на Flight! +Хотя эти примеры не спонсируются официально командой Flight, они могут дать вам идеи о том, как структурировать свои собственные проекты, построенные на Flight! +- [ASC REST API Spell Checker](https://github.com/AlMosahih-ASC/asc-api-sample) - Лёгкий REST API для проверки орфографии арабского языка, построенный на FlightPHP и библиотеке ArPHP. Этот API предоставляет возможности проверки орфографии арабского текста, включая обнаружение ошибочно написанных слов и предложения по исправлению. - [Eventify](https://github.com/ilhanklisura/eventify) - Eventify — это одностраничное приложение, соединяющее организаторов событий с участниками. Построено на PHP (FlightPHP), JavaScript и MySQL, с функциями JWT-аутентификации, управления событиями и документацией RESTful API с использованием OpenAPI. -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental — это одностраничное, мобильно-дружественное веб-приложение для аренды автомобилей, построенное на PHP (FlightPHP), JavaScript и MySQL. Оно поддерживает регистрацию пользователей, просмотр и бронирование автомобилей, а администраторы могут управлять автомобилями, пользователями и бронированиями. Приложение включает REST API, JWT-аутентификацию и адаптивный дизайн для современного опыта аренды. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental — это одностраничное, мобильно-дружественное веб-приложение для аренды автомобилей, построенное на PHP (FlightPHP), JavaScript и MySQL. Оно поддерживает регистрацию пользователей, просмотр и бронирование автомобилей, в то время как администраторы могут управлять автомобилями, пользователями и бронированиями. Приложение включает REST API, JWT-аутентификацию и адаптивный дизайн для современного опыта аренды. - [Decay](https://github.com/boxybird/decay) - Flight v3 с HTMX и SleekDB, всё о зомби! ([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 с Middleware, Controllers, Active Record и Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Простой проект CRUD API с использованием фреймворка Flight, который предоставляет базовую структуру для новых пользователей, чтобы быстро настроить PHP-приложение с операциями CRUD и подключением к базе данных. Проект демонстрирует, как использовать Flight для разработки RESTful API, делая его идеальным инструментом для обучения новичков и полезным стартовым комплектом для более опытных разработчиков. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Простой проект CRUD API с использованием фреймворка Flight, который предоставляет базовую структуру для новых пользователей, чтобы быстро настроить PHP-приложение с операциями CRUD и подключением к базе данных. Проект демонстрирует, как использовать Flight для разработки RESTful API, делая его идеальным инструментом для обучения для начинающих и полезным стартовым набором для более опытных разработчиков. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -31,8 +32,8 @@ - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Готовый для производства фреймворк аутентификации, который сэкономит вам недели разработки. Функции корпоративного уровня безопасности: 2FA/TOTP, интеграция LDAP, Azure SSO, интеллектуальное ограничение скорости, отпечатки сессий, защита от brute-force, панель аналитики безопасности, всестороннее ведение логов аудита и гранулярный контроль доступа на основе ролей. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Готовый к производству фреймворк аутентификации, который сэкономит вам недели разработки. Функции корпоративного уровня безопасности: 2FA/TOTP, интеграция LDAP, Azure SSO, интеллектуальное ограничение скорости, отпечатки сессий, защита от brute-force, панель аналитики безопасности, всестороннее логирование аудита и гранулярный контроль доступа на основе ролей. -## Хотите поделиться своим примером? +## Хотите поделиться своим собственным примером? Если у вас есть проект, которым вы хотите поделиться, пожалуйста, отправьте pull request, чтобы добавить его в этот список! \ No newline at end of file diff --git a/content/v3/uk/awesome-plugins/active_record.md b/content/v3/uk/awesome-plugins/active_record.md index c7fea3bd..e26f8cd0 100644 --- a/content/v3/uk/awesome-plugins/active_record.md +++ b/content/v3/uk/awesome-plugins/active_record.md @@ -1,12 +1,12 @@ -# Flight Active Record +# Flight Active Record -Активний запис - це відображення сутності бази даних на об'єкт PHP. Простими словами, якщо у вас є таблиця користувачів у вашій базі даних, ви можете "перекласти" рядок у цій таблиці в клас `User` і об'єкт `$user` у вашому коді. Дивіться [основний приклад](#basic-example). +Активний запис — це відображення сутності бази даних на об'єкт PHP. Простіше кажучи, якщо у вас є таблиця users у базі даних, ви можете "перекласти" рядок у цій таблиці на клас `User` та об'єкт `$user` у вашому коді. Див. [основний приклад](#basic-example). -Натисніть [тут](https://github.com/flightphp/active-record) для доступу до репозиторію на GitHub. +Натисніть [тут](https://github.com/flightphp/active-record) для репозиторію на GitHub. ## Основний приклад -Припустимо, у вас є наступна таблиця: +Припустимо, у вас є така таблиця: ```sql CREATE TABLE users ( @@ -22,7 +22,7 @@ CREATE TABLE users ( /** * Клас ActiveRecord зазвичай є одниною * - * Рекомендується додати властивості таблиці як коментарі тут + * Дуже рекомендується додавати властивості таблиці як коментарі тут * * @property int $id * @property string $name @@ -31,7 +31,7 @@ CREATE TABLE users ( class User extends flight\ActiveRecord { public function __construct($database_connection) { - // ви можете встановити таким чином + // ви можете налаштувати це таким чином parent::__construct($database_connection, 'users'); // або таким чином parent::__construct($database_connection, null, [ 'table' => 'users']); @@ -39,18 +39,18 @@ class User extends flight\ActiveRecord { } ``` -Тепер спостерігайте, як відбувається магія! +Тепер спостерігайте за магією! ```php // для sqlite -$database_connection = new PDO('sqlite:test.db'); // це лише для прикладу, ви, ймовірно, будете використовувати реальне з'єднання з базою даних +$database_connection = new PDO('sqlite:test.db'); // це просто для прикладу, ви ймовірно використовуватимете реальне з'єднання з базою даних // для mysql $database_connection = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'username', 'password'); // або mysqli $database_connection = new mysqli('localhost', 'username', 'password', 'test_db'); -// або mysqli з не об'єктним створенням +// або mysqli з створенням не на основі об'єкта $database_connection = mysqli_connect('localhost', 'username', 'password', 'test_db'); $user = new User($database_connection); @@ -64,31 +64,31 @@ echo $user->id; // 1 $user->name = 'Joseph Mamma'; $user->password = password_hash('some cool password again!!!'); $user->insert(); -// не можна використовувати $user->save() тут, інакше воно вважатиме, що це оновлення! +// не можна використовувати $user->save() тут, інакше це вважатиме оновленням! echo $user->id; // 2 ``` -І це було так легко додати нового користувача! Тепер, коли в базі даних є рядок користувача, як витягти його? +І було так просто додати нового користувача! Тепер, коли в базі даних є рядок користувача, як ви його витягнете? ```php -$user->find(1); // знайти id = 1 у базі даних і повернути його. +$user->find(1); // знаходить id = 1 у базі даних і повертає його. echo $user->name; // 'Bobby Tables' ``` -А що якщо ви хочете знайти всіх користувачів? +А що, якщо ви хочете знайти всіх користувачів? ```php $users = $user->findAll(); ``` -Що щодо певної умови? +А з певною умовою? ```php $users = $user->like('name', '%mamma%')->findAll(); ``` -Бачите, як це весело? Давайте встановимо це і почнемо! +Бачите, наскільки це весело? Давайте встановимо це та почнемо! ## Встановлення @@ -100,33 +100,33 @@ composer require flightphp/active-record ## Використання -Це можна використовувати як окрему бібліотеку або з PHP Framework Flight. Цілком на ваш розсуд. +Це можна використовувати як самостійну бібліотеку або з PHP Framework Flight. Повністю залежить від вас. -### Окремо -Просто переконайтеся, що передали з'єднання PDO в конструктор. +### Самостійно +Просто переконайтеся, що ви передаєте з'єднання PDO до конструктора. ```php -$pdo_connection = new PDO('sqlite:test.db'); // це лише для прикладу, ви, ймовірно, будете використовувати реальне з'єднання з базою даних +$pdo_connection = new PDO('sqlite:test.db'); // це просто для прикладу, ви ймовірно використовуватимете реальне з'єднання з базою даних $User = new User($pdo_connection); ``` -> Не хочете завжди встановлювати з'єднання з базою даних у конструкторі? Дивіться [Управління з'єднаннями з базою даних](#database-connection-management) для інших ідей! +> Не хочете завжди встановлювати з'єднання з базою даних у конструкторі? Див. [Керування з'єднанням з базою даних](#database-connection-management) для інших ідей! -### Зареєструвати як метод у Flight -Якщо ви використовуєте PHP Framework Flight, ви можете зареєструвати клас ActiveRecord як сервіс, але насправді вам не потрібно. +### Реєстрація як методу у Flight +Якщо ви використовуєте PHP Framework Flight, ви можете зареєструвати клас ActiveRecord як сервіс, але чесно кажучи, це не обов'язково. ```php Flight::register('user', 'User', [ $pdo_connection ]); -// тоді ви можете використовувати це так у контролері, функції тощо. +// потім ви можете використовувати це так у контролері, функції тощо. Flight::user()->find(1); ``` ## Методи `runway` -[runway](/awesome-plugins/runway) - це інструмент CLI для Flight, який має користувацьку команду для цієї бібліотеки. +[runway](/awesome-plugins/runway) — це CLI-інструмент для Flight, який має спеціальну команду для цієї бібліотеки. ```bash # Використання @@ -136,7 +136,7 @@ php runway make:record database_table_name [class_name] php runway make:record users ``` -Це створить новий клас у каталозі `app/records/` під назвою `UserRecord.php` з наступним вмістом: +Це створить новий клас у директорії `app/records/` як `UserRecord.php` з таким вмістом: ```php notNull('password')->orderBy('id DESC')->find(); -// знайти запис за конкретним id +// знаходить запис за конкретним id $id = 123; $user->find($id); ``` #### `findAll(): array` -Знайдіть усі записи в зазначеній вами таблиці. +Знаходить всі записи в таблиці, яку ви вказуєте. ```php $user->findAll(); @@ -222,9 +222,9 @@ $user->password = md5('demo'); $user->insert(); ``` -##### Текстові первинні ключі +##### Первинні ключі на основі тексту -Якщо у вас є текстовий первинний ключ (такий як UUID), ви можете встановити значення первинного ключа перед вставкою одним з двох способів. +Якщо у вас є первинний ключ на основі тексту (наприклад, UUID), ви можете встановити значення первинного ключа перед вставкою одним з двох способів. ```php $user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]); @@ -234,27 +234,24 @@ $user->password = md5('demo'); $user->insert(); // або $user->save(); ``` -або ви можете мати первинний ключ, автоматично згенерований для вас через події. +або ви можете мати автоматично згенерований первинний ключ для вас через події. ```php class User extends flight\ActiveRecord { public function __construct($database_connection) { parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]); - // ви можете також встановити primaryKey таким чином замість масиву вище. + // ви також можете встановити primaryKey таким чином замість масиву вище. $this->primaryKey = 'uuid'; } protected function beforeInsert(self $self) { - $self->uuid = uniqid(); // або як вам потрібно генерувати ваші унікальні id + $self->uuid = uniqid(); // або як вам потрібно генерувати унікальні id } } ``` -Якщо ви не встановите первинний ключ перед вставкою, він буде встановлений на `rowid`, і -база даних згенерує його для вас, але не збережеться, оскільки цього поля може не бути -в вашій таблиці. Це чому рекомендується використовувати подію, щоб автоматично обробити це -для вас. +Якщо ви не встановите первинний ключ перед вставкою, він буде встановлено на `rowid`, і база даних згенерує його для вас, але він не збережеться, оскільки це поле може не існувати в вашій таблиці. Тому рекомендується використовувати подію для автоматичного керування цим. #### `update(): boolean|ActiveRecord` @@ -268,7 +265,7 @@ $user->update(); #### `save(): boolean|ActiveRecord` -Вставляє або оновлює поточний запис у базі даних. Якщо запис має id, він оновить, в іншому випадку вставить. +Вставляє або оновлює поточний запис у базі даних. Якщо запис має id, це оновить, інакше вставить. ```php $user = new User($pdo_connection); @@ -277,7 +274,7 @@ $user->password = md5('demo'); $user->save(); ``` -**Примітка:** Якщо у вас є визначені в класі зв'язки, він рекурсивно збереже ці зв'язки також, якщо вони були визначені, ініційовані та мають "брудні" дані для оновлення. (v0.4.0 і вище) +**Примітка:** Якщо у вас визначені відносини в класі, це рекурсивно збереже ці відносини, якщо вони визначені, створені та мають брудні дані для оновлення. (v0.4.0 та вище) #### `delete(): boolean` @@ -288,40 +285,40 @@ $user->gt('id', 0)->orderBy('id desc')->find(); $user->delete(); ``` -Ви також можете видалити кілька записів, виконуючи пошук заздалегідь. +Ви також можете видалити кілька записів, виконавши пошук заздалегідь. ```php $user->like('name', 'Bob%')->delete(); ``` -#### `dirty(array $dirty = []): ActiveRecord` +#### `dirty(array $dirty = []): ActiveRecord` -"Брудні" дані стосуються даних, які були змінені в запису. +Брудні дані стосуються даних, які були змінені в записі. ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); -// на даний момент нічого не є "брудним". +// на цьому етапі нічого не є "брудним". -$user->email = 'test@example.com'; // тепер email вважається "брудним", оскільки він змінився. +$user->email = 'test@example.com'; // тепер email вважається "брудним", оскільки він змінений. $user->update(); -// тепер немає даних, які є брудними, оскільки вони були оновлені та збережені в базі даних +// тепер немає даних, які є брудними, оскільки вони оновлені та збережені в базі даних -$user->password = password_hash('newpassword'); // тепер це брудно -$user->dirty(); // передання нічого очистить усі брудні записи. -$user->update(); // нічого не буде оновлено, оскільки нічого не було захоплено як брудне. +$user->password = password_hash()'newpassword'); // тепер це брудне +$user->dirty(); // передача нічого очистить всі брудні записи. +$user->update(); // нічого не оновиться, оскільки нічого не було захоплено як брудне. $user->dirty([ 'name' => 'something', 'password' => password_hash('a different password') ]); -$user->update(); // і ім'я, і пароль оновлюються. +$user->update(); // обидва name та password оновлені. ``` #### `copyFrom(array $data): ActiveRecord` (v0.4.0) -Це псевдонім для методу `dirty()`. Це трохи ясніше, що ви робите. +Це псевдонім для методу `dirty()`. Трохи зрозуміліше, що ви робите. ```php $user->copyFrom([ 'name' => 'something', 'password' => password_hash('a different password') ]); -$user->update(); // і ім'я, і пароль оновлюються. +$user->update(); // обидва name та password оновлені. ``` #### `isDirty(): boolean` (v0.4.0) @@ -336,15 +333,15 @@ $user->isDirty(); // true #### `reset(bool $include_query_data = true): ActiveRecord` -Скидає поточний запис до його початкового стану. Це дійсно добре використовувати в циклі. -Якщо ви передасте `true`, він також скине дані запиту, які були використані для знаходження поточного об'єкта (за замовчуванням). +Скидає поточний запис до його початкового стану. Це дуже корисно для поведінки типу циклу. +Якщо ви передасте `true`, це також скине дані запиту, які використовувалися для пошуку поточного об'єкта (поведінка за замовчуванням). ```php $users = $user->greaterThan('id', 0)->orderBy('id desc')->find(); $user_company = new UserCompany($pdo_connection); foreach($users as $user) { - $user_company->reset(); // почати з чистого аркуша + $user_company->reset(); // почніть з чистого аркуша $user_company->user_id = $user->id; $user_company->company_id = $some_company_id; $user_company->insert(); @@ -353,12 +350,12 @@ foreach($users as $user) { #### `getBuiltSql(): string` (v0.4.1) -Після того, як ви запустите `find()`, `findAll()`, `insert()`, `update()`, або `save()` метод, ви можете отримати SQL, який був побудований, і використовувати його для налагодження. +Після виконання методу `find()`, `findAll()`, `insert()`, `update()` або `save()` ви можете отримати SQL, який був побудований, і використовувати його для цілей налагодження. -## Методи SQL Запитів +## Методи SQL-запиту #### `select(string $field1 [, string $field2 ... ])` -Ви можете вибрати лише кілька стовпців у таблиці, якщо хочете (це ефективніше на справді широких таблицях з багатьма стовпцями) +Ви можете вибрати лише кілька стовпців у таблиці, якщо бажаєте (це ефективніше для дуже широких таблиць з багатьма стовпцями) ```php $user->select('id', 'name')->find(); @@ -366,7 +363,7 @@ $user->select('id', 'name')->find(); #### `from(string $table)` -Ви також можете вибрати іншу таблицю! Чому б і ні?! +Ви технічно можете вибрати іншу таблицю також! Чому б і ні?! ```php $user->select('id', 'name')->from('user')->find(); @@ -374,7 +371,7 @@ $user->select('id', 'name')->from('user')->find(); #### `join(string $table_name, string $join_condition)` -Ви також можете виконати з'єднання з іншою таблицею в базі даних. +Ви навіть можете приєднатися до іншої таблиці в базі даних. ```php $user->join('contacts', 'contacts.user_id = users.id')->find(); @@ -382,17 +379,17 @@ $user->join('contacts', 'contacts.user_id = users.id')->find(); #### `where(string $where_conditions)` -Ви можете встановити деякі власні аргументи where (ви не можете встановити параметри в цьому операторі where) +Ви можете встановити деякі власні аргументи where (ви не можете встановити параметри в цій інструкції where) ```php $user->where('id=1 AND name="demo"')->find(); ``` -**Примітка безпеки** - Ви можете бути спокушені зробити щось на зразок `$user->where("id = '{$id}' AND name = '{$name}'")->find();`. Будь ласка, НЕ РОБІТЬ ЦЬОГО!!! Це піддається атакам SQL-ін'єкцій. Є багато статей в Інтернеті, будь ласка, Google "sql injection attacks php", і ви знайдете багато статей на цю тему. Правильний спосіб обробити це з цією бібліотекою - замість цього методу `where()`, ви повинні зробити щось на зразок `$user->eq('id', $id)->eq('name', $name)->find();` Якщо вам дійсно потрібно це зробити, бібліотека `PDO` має `$pdo->quote($var)`, щоб екранізувати його для вас. Тільки після того, як ви використовуєте `quote()`, ви можете використовувати це в операторі `where()`. +**Примітка щодо безпеки** - Ви можете бути спокушені зробити щось на кшталт `$user->where("id = '{$id}' AND name = '{$name}'")->find();`. Будь ласка, НЕ РОБІТЬ ЦЬОГО!!! Це вразливе до того, що відомо як атаки SQL-ін'єкцій. Є багато статей онлайн, будь ласка, погугліть "sql injection attacks php" і ви знайдете багато статей на цю тему. Правильний спосіб обробити це з цією бібліотекою — замість цього методу `where()`, ви б зробили щось на кшталт `$user->eq('id', $id)->eq('name', $name)->find();` Якщо вам абсолютно необхідно це зробити, бібліотека `PDO` має `$pdo->quote($var)` для екранування. Тільки після використання `quote()` ви можете використовувати це в інструкції `where()`. #### `group(string $group_by_statement)/groupBy(string $group_by_statement)` -Групуйте свої результати за певною умовою. +Групуйте ваші результати за певною умовою. ```php $user->select('COUNT(*) as count')->groupBy('name')->findAll(); @@ -400,7 +397,7 @@ $user->select('COUNT(*) as count')->groupBy('name')->findAll(); #### `order(string $order_by_statement)/orderBy(string $order_by_statement)` -Сортуйте повернуті запити певним чином. +Сортуйте повернутий запит певним чином. ```php $user->orderBy('name DESC')->find(); @@ -408,7 +405,7 @@ $user->orderBy('name DESC')->find(); #### `limit(string $limit)/limit(int $offset, int $limit)` -Обмежте кількість повернених записів. Якщо задано другий int, він буде зсувати, обмежуючи так, як у SQL. +Обмежте кількість повернених записів. Якщо надано другий int, це буде зсув, обмеження, як у SQL. ```php $user->orderby('name DESC')->limit(0, 10)->findAll(); @@ -502,48 +499,48 @@ $user->between('id', [1, 2])->find(); ### Умови OR -Можливо обернути ваші умови в оператор OR. Це здійснюється або за допомогою методів `startWrap()` та `endWrap()`, або заповнюючи третій параметр умови після поля та значення. +Можна обгорнути ваші умови в інструкцію OR. Це робиться за допомогою методу `startWrap()` та `endWrap()` або заповненням 3-го параметра умови після поля та значення. ```php // Метод 1 $user->eq('id', 1)->startWrap()->eq('name', 'demo')->or()->eq('name', 'test')->endWrap('OR')->find(); -// Це буде оцінено як `id = 1 AND (name = 'demo' OR name = 'test')` +// Це оцінюється як `id = 1 AND (name = 'demo' OR name = 'test')` // Метод 2 $user->eq('id', 1)->eq('name', 'demo', 'OR')->find(); -// Це буде оцінено як `id = 1 OR name = 'demo'` +// Це оцінюється як `id = 1 OR name = 'demo'` ``` -## Взаємовідносини -Ви можете налаштувати декілька видів взаємовідносин, використовуючи цю бібліотеку. Ви можете налаштувати один->багато та один->один взаємовідносини між таблицями. Це потребує незначної додаткової підготовки у класі заздалегідь. +## Відносини +Ви можете встановити кілька видів відносин за допомогою цієї бібліотеки. Ви можете встановити відносини один-до-багатьох та один-до-одного між таблицями. Це вимагає трохи додаткового налаштування в класі заздалегідь. -Налаштування масиву `$relations` не є важким, але вгадування правильного синтаксису може бути заплутаним. +Встановлення масиву `$relations` не важко, але вгадування правильного синтаксису може бути заплутаним. ```php protected array $relations = [ - // ви можете назвати ключ будь-як. Назва класу ActiveRecord, мабуть, підійде. Наприклад: user, contact, client + // ви можете назвати ключ будь-як. Назва ActiveRecord, ймовірно, хороша. Наприклад: user, contact, client 'user' => [ // обов'язково // self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO - self::HAS_ONE, // це тип взаємовідносини + self::HAS_ONE, // це тип відносини // обов'язково - 'Some_Class', // це "інший" клас ActiveRecord, з яким це буде посилатися + 'Some_Class', // це "інший" клас ActiveRecord, на який буде посилання // обов'язково - // в залежності від типу взаємовідносини + // залежно від типу відносини // self::HAS_ONE = зовнішній ключ, що посилається на з'єднання // self::HAS_MANY = зовнішній ключ, що посилається на з'єднання // self::BELONGS_TO = локальний ключ, що посилається на з'єднання 'local_or_foreign_key', - // до вашого відома, це також лише приєднує до первинного ключа "іншої" моделі + // просто для інформації, це також приєднує лише до первинного ключа "іншої" моделі // необов'язково - [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // додаткові умови, які ви хочете при приєднанні зв'язку + [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // додаткові умови, які ви хочете при приєднанні відносини // $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5)) // необов'язково - 'back_reference_name' // це якщо ви хочете повернути цю взаємовідносину назад до себе, наприклад: $user->contact->user; + 'back_reference_name' // це якщо ви хочете посилатися назад на цю відносини Ex: $user->contact->user; ]; ] ``` @@ -573,41 +570,142 @@ class Contact extends ActiveRecord{ } ``` -Тепер у нас налаштовані посилання, щоб ми могли використовувати їх дуже зручно! +Тепер у нас налаштовані посилання, тому ми можемо використовувати їх дуже легко! ```php $user = new User($pdo_connection); -// знайти найостаннішого користувача. +// знаходимо найновішого користувача. $user->notNull('id')->orderBy('id desc')->find(); -// отримати контакти, використовуючи зв'язок: +// отримуємо контакти за допомогою відносини: foreach($user->contacts as $contact) { echo $contact->id; } -// або ми можемо піти в іншу сторону. +// або ми можемо піти іншим шляхом. $contact = new Contact(); -// знайти один контакт +// знаходимо один контакт $contact->find(); -// отримати користувача за допомогою зв'язку: +// отримуємо користувача за допомогою відносини: echo $contact->user->name; // це ім'я користувача ``` -Досить круто, чи не так? +Досить круто, еге? -## Налаштування нестандартних даних -Іноді вам може знадобитися прикріпити щось унікальне до вашого ActiveRecord, наприклад, нестандартне обчислення, яке може бути легше просто прикріпити до об'єкта, який потім буде переданий, скажімо, шаблону. +### Eager Loading + +#### Огляд +Eager loading розв'язує проблему N+1 запитів, завантажуючи відносини заздалегідь. Замість виконання окремого запиту для відносин кожного запису, eager loading отримує всі пов'язані дані лише в одному додатковому запиті на відносини. + +> **Примітка:** Eager loading доступний лише для v0.7.0 та вище. + +#### Основне використання +Використовуйте метод `with()` для вказівки, які відносини завантажити заздалегідь: +```php +// Завантажуємо користувачів з їх контактами в 2 запити замість N+1 +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + foreach ($u->contacts as $contact) { + echo $contact->email; // Без додаткового запиту! + } +} +``` + +#### Кілька відносин +Завантажуйте кілька відносин одразу: +```php +$users = $user->with(['contacts', 'profile', 'settings'])->findAll(); +``` + +#### Типи відносин + +##### HAS_MANY +```php +// Eager завантажуємо всі контакти для кожного користувача +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + // $u->contacts вже завантажено як масив + foreach ($u->contacts as $contact) { + echo $contact->email; + } +} +``` +##### HAS_ONE +```php +// Eager завантажуємо один контакт для кожного користувача +$users = $user->with('contact')->findAll(); +foreach ($users as $u) { + // $u->contact вже завантажено як об'єкт + echo $u->contact->email; +} +``` + +##### BELONGS_TO +```php +// Eager завантажуємо батьківських користувачів для всіх контактів +$contacts = $contact->with('user')->findAll(); +foreach ($contacts as $c) { + // $c->user вже завантажено + echo $c->user->name; +} +``` +##### З find() +Eager loading працює як з +findAll() +, так і з +find() +: + +```php +$user = $user->with('contacts')->find(1); +// Користувач і всі їхні контакти завантажені в 2 запити +``` +#### Переваги продуктивності +Без eager loading (проблема N+1): +```php +$users = $user->findAll(); // 1 запит +foreach ($users as $u) { + $contacts = $u->contacts; // N запитів (один на користувача!) +} +// Всього: 1 + N запитів +``` + +З eager loading: + +```php +$users = $user->with('contacts')->findAll(); // 2 запити всього +foreach ($users as $u) { + $contacts = $u->contacts; // 0 додаткових запитів! +} +// Всього: 2 запити (1 для користувачів + 1 для всіх контактів) +``` +Для 10 користувачів це зменшує запити з 11 до 2 — зменшення на 82%! + +#### Важливі примітки +- Eager loading повністю необов'язковий — lazy loading все ще працює як раніше +- Вже завантажені відносини автоматично пропускаються +- Зворотні посилання працюють з eager loading +- Колбеки відносин поважаються під час eager loading + +#### Обмеження +- Вкладене eager loading (наприклад, +with(['contacts.addresses']) +) наразі не підтримується +- Обмеження eager завантаження через замикання не підтримуються в цій версії + +## Встановлення власних даних +Іноді вам може знадобитися прикріпити щось унікальне до вашого ActiveRecord, наприклад, власний розрахунок, який може бути простішим прикріпити до об'єкта, який потім передається, скажімо, шаблону. #### `setCustomData(string $field, mixed $value)` -Ви прикріплюєте нестандартні дані за допомогою методу `setCustomData()`. +Ви прикріплюєте власні дані за допомогою методу `setCustomData()`. ```php $user->setCustomData('page_view_count', $page_view_count); ``` -І тоді ви просто посилаєтеся на це, як на звичайну властивість об'єкта. +А потім ви просто посилаєтеся на це як на звичайну властивість об'єкта. ```php echo $user->page_view_count; @@ -615,11 +713,11 @@ echo $user->page_view_count; ## Події -Ще одна надзвичайно класна функція цієї бібліотеки - це події. Події спрацьовують в певний час на основі певних методів, які ви викликаєте. Вони дуже корисні для автоматичного налаштування даних. +Ще одна супер крута функція цієї бібліотеки — це події. Події запускаються в певні моменти на основі певних методів, які ви викликаєте. Вони дуже корисні для автоматичного налаштування даних для вас. #### `onConstruct(ActiveRecord $ActiveRecord, array &config)` -Це дійсно корисно, якщо вам потрібно встановити з'єднання за замовчуванням або щось подібне. +Це дуже корисно, якщо вам потрібно встановити з'єднання за замовчуванням або щось подібне. ```php // index.php або bootstrap.php @@ -632,13 +730,13 @@ Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php class User extends flight\ActiveRecord { - protected function onConstruct(self $self, array &$config) { // не забувайте про посилання & - // ви могли б зробити це, щоб автоматично налаштувати з'єднання + protected function onConstruct(self $self, array &$config) { // не забудьте посилання & + // ви могли б зробити це для автоматичного встановлення з'єднання $config['connection'] = Flight::db(); - // або так + // або це $self->transformAndPersistConnection(Flight::db()); - // Також ви можете встановити ім'я таблиці таким чином. + // Ви також можете встановити назву таблиці таким чином. $config['table'] = 'users'; } } @@ -646,7 +744,7 @@ class User extends flight\ActiveRecord { #### `beforeFind(ActiveRecord $ActiveRecord)` -Це, ймовірно, лише корисно, якщо вам потрібно маніпулювати запитом щоразу. +Це, ймовірно, корисно лише якщо вам потрібно маніпулювати запитом кожного разу. ```php class User extends flight\ActiveRecord { @@ -657,7 +755,7 @@ class User extends flight\ActiveRecord { } protected function beforeFind(self $self) { - // завжди виконувати id >= 0, якщо це ваше + // завжди запускайте id >= 0, якщо це ваш стиль $self->gte('id', 0); } } @@ -665,7 +763,7 @@ class User extends flight\ActiveRecord { #### `afterFind(ActiveRecord $ActiveRecord)` -Ця функція, ймовірно, корисніша, якщо ви завжди повинні виконувати якусь логіку кожного разу, коли цей запис отримується. Вам потрібно розшифрувати щось? Вам потрібно виконати налаштування запиту кожен раз (не продуктивно, але байдуже)? +Цей, ймовірно, корисніший, якщо вам завжди потрібно запускати деяку логіку кожного разу, коли цей запис отримується. Вам потрібно дешифрувати щось? Вам потрібно запускати власний запит підрахунку кожного разу (не ефективно, але ну)? ```php class User extends flight\ActiveRecord { @@ -676,18 +774,18 @@ class User extends flight\ActiveRecord { } protected function afterFind(self $self) { - // розшифрування чогось + // дешифрування чогось $self->secret = yourDecryptFunction($self->secret, $some_key); - // можливо, зберігання чогось нестандартного, як запит??? - $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']); + // можливо, зберігання чогось власного, як запит??? + $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']; } } ``` #### `beforeFindAll(ActiveRecord $ActiveRecord)` -Це, ймовірно, лише корисно, якщо вам потрібно маніпулювати запитом щоразу. +Це, ймовірно, корисно лише якщо вам потрібно маніпулювати запитом кожного разу. ```php class User extends flight\ActiveRecord { @@ -698,7 +796,7 @@ class User extends flight\ActiveRecord { } protected function beforeFindAll(self $self) { - // завжди виконувати id >= 0, якщо це ваше + // завжди запускайте id >= 0, якщо це ваш стиль $self->gte('id', 0); } } @@ -706,7 +804,7 @@ class User extends flight\ActiveRecord { #### `afterFindAll(array $results)` -Подібно до `afterFind()`, але ви можете зробити це для усіх записів! +Подібно до `afterFind()`, але ви можете зробити це для всіх записів! ```php class User extends flight\ActiveRecord { @@ -719,7 +817,7 @@ class User extends flight\ActiveRecord { protected function afterFindAll(array $results) { foreach($results as $self) { - // зробити щось класне, як і при afterFind() + // робіть щось круте, як afterFind() } } } @@ -727,7 +825,7 @@ class User extends flight\ActiveRecord { #### `beforeInsert(ActiveRecord $ActiveRecord)` -Дійсно корисно, якщо вам потрібно встановити деякі значення за замовчуванням щоразу. +Дуже корисно, якщо вам потрібно встановити деякі значення за замовчуванням кожного разу. ```php class User extends flight\ActiveRecord { @@ -738,7 +836,7 @@ class User extends flight\ActiveRecord { } protected function beforeInsert(self $self) { - // встановити якісь правильні значення за замовчуванням + // встановіть деякі розумні значення за замовчуванням if(!$self->created_date) { $self->created_date = gmdate('Y-m-d'); } @@ -752,7 +850,7 @@ class User extends flight\ActiveRecord { #### `afterInsert(ActiveRecord $ActiveRecord)` -Можливо, у вас є випадок для зміни даних після їх вставки? +Можливо, у вас є випадок використання для зміни даних після вставки? ```php class User extends flight\ActiveRecord { @@ -763,7 +861,7 @@ class User extends flight\ActiveRecord { } protected function afterInsert(self $self) { - // робіть що хочете + // робіть, що хочете Flight::cache()->set('most_recent_insert_id', $self->id); // або що завгодно.... } @@ -772,7 +870,7 @@ class User extends flight\ActiveRecord { #### `beforeUpdate(ActiveRecord $ActiveRecord)` -Дійсно корисно, якщо вам потрібно встановити деякі значення за замовчуванням щоразу на оновлення. +Дуже корисно, якщо вам потрібно встановити деякі значення за замовчуванням кожного разу під час оновлення. ```php class User extends flight\ActiveRecord { @@ -782,8 +880,8 @@ class User extends flight\ActiveRecord { parent::__construct($database_connection, 'users'); } - protected function beforeUpdate(self $self) { - // встановити якісь правильні значення за замовчуванням + protected function beforeInsert(self $self) { + // встановіть деякі розумні значення за замовчуванням if(!$self->updated_date) { $self->updated_date = gmdate('Y-m-d'); } @@ -793,7 +891,7 @@ class User extends flight\ActiveRecord { #### `afterUpdate(ActiveRecord $ActiveRecord)` -Можливо, у вас є випадок для зміни даних після їх оновлення? +Можливо, у вас є випадок використання для зміни даних після оновлення? ```php class User extends flight\ActiveRecord { @@ -803,8 +901,8 @@ class User extends flight\ActiveRecord { parent::__construct($database_connection, 'users'); } - protected function afterUpdate(self $self) { - // робіть що хочете + protected function afterInsert(self $self) { + // робіть, що хочете Flight::cache()->set('most_recently_updated_user_id', $self->id); // або що завгодно.... } @@ -813,7 +911,7 @@ class User extends flight\ActiveRecord { #### `beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)` -Це корисно, якщо ви хочете, щоб події відбувалися як під час вставок, так і оновлень. Я вас не буде дратувати довгим поясненням, але ви, напевно, можете здогадатися, що це таке. +Це корисно, якщо ви хочете, щоб події відбувалися як під час вставок, так і під час оновлень. Я пощаджу вас довгим поясненням, але я впевнений, що ви можете здогадатися, що це таке. ```php class User extends flight\ActiveRecord { @@ -831,7 +929,7 @@ class User extends flight\ActiveRecord { #### `beforeDelete(ActiveRecord $ActiveRecord)/afterDelete(ActiveRecord $ActiveRecord)` -Не впевнений, що ви хочете зробити тут, але без суджень! Робіть, як хочете! +Не впевнений, що ви хотіли б зробити тут, але ніяких суджень! Рухайтеся! ```php class User extends flight\ActiveRecord { @@ -842,14 +940,14 @@ class User extends flight\ActiveRecord { } protected function beforeDelete(self $self) { - echo 'Він був сміливим солдатом... :cry-face:'; + echo 'He was a brave soldier... :cry-face:'; } } ``` -## Управління з'єднаннями з базою даних +## Керування з'єднанням з базою даних -Коли ви користуєтеся цією бібліотекою, ви можете встановити з'єднання з базою даних кількома різними способами. Ви можете встановити з'єднання в конструкторі, ви можете встановити його через змінну конфігурації `$config['connection']` або ви можете встановити його через `setDatabaseConnection()` (v0.4.1). +Коли ви використовуєте цю бібліотеку, ви можете встановити з'єднання з базою даних кількома різними способами. Ви можете встановити з'єднання в конструкторі, ви можете встановити його через змінну конфігурації `$config['connection']` або ви можете встановити його через `setDatabaseConnection()` (v0.4.1). ```php $pdo_connection = new PDO('sqlite:test.db'); // для прикладу @@ -861,7 +959,7 @@ $user = new User(); $user->setDatabaseConnection($pdo_connection); ``` -Якщо ви хочете уникнути постійного встановлення `$database_connection` щоразу, коли ви викликаєте активний запис, існують варіанти! +Якщо ви хочете уникнути завжди встановлювати `$database_connection` кожного разу, коли викликаєте active record, є способи обійти це! ```php // index.php або bootstrap.php @@ -878,24 +976,23 @@ class User extends flight\ActiveRecord { } } -// І тепер, аргументи не потрібні! +// І тепер не потрібні аргументи! $user = new User(); ``` -> **Примітка:** Якщо ви плануєте юніт-тестування, робити це може додати певні труднощі до юніт-тестування, але в цілому, оскільки ви можете впроваджувати ваше -з'єднання за допомогою `setDatabaseConnection()` або `$config['connection']`, це не так вже й погано. +> **Примітка:** Якщо ви плануєте unit-тестування, робити це таким чином може додати деякі виклики до unit-тестування, але загалом, оскільки ви можете інжектувати ваше з'єднання з `setDatabaseConnection()` або `$config['connection']`, це не так погано. -Якщо вам потрібно оновити з'єднання з базою даних, наприклад, якщо ви запускаєте тривале CLI-скрипт і вам потрібно періодично оновлювати з'єднання, ви можете заново встановити з'єднання за допомогою `$your_record->setDatabaseConnection($pdo_connection)`. +Якщо вам потрібно оновити з'єднання з базою даних, наприклад, якщо ви запускаєте довготривалий CLI-скрипт і потрібно оновлювати з'єднання час від часу, ви можете переустановити з'єднання з `$your_record->setDatabaseConnection($pdo_connection)`. -## Внески +## Співпраця -Будь ласка, робіть це. :D +Будь ласка, робіть. :D ### Налаштування -Коли ви будете брати участь, переконайтеся, що ви запустили `composer test-coverage`, щоб підтримувати 100% покриття тестами (це не 100% покриття юніт-тестами, а скоріше інтеграційне тестування). +Коли ви сприяєте, переконайтеся, що ви запускаєте `composer test-coverage`, щоб підтримувати 100% покриття тестами (це не справжнє покриття unit-тестів, більше як інтеграційне тестування). -Також переконайтеся, що ви запустили `composer beautify` та `composer phpcs`, щоб виправити будь-які помилки синтаксису. +Також переконайтеся, що ви запускаєте `composer beautify` та `composer phpcs`, щоб виправити будь-які помилки лінтингу. ## Ліцензія diff --git a/content/v3/uk/awesome-plugins/apm.md b/content/v3/uk/awesome-plugins/apm.md index 809cfea3..b5a1f18e 100644 --- a/content/v3/uk/awesome-plugins/apm.md +++ b/content/v3/uk/awesome-plugins/apm.md @@ -1,6 +1,6 @@ -# Документація FlightPHP APM +# Документація APM для FlightPHP -Ласкаво просимо до FlightPHP APM — вашого особистого тренера продуктивності для додатку! Цей посібник — ваша дорожня карта для налаштування, використання та освоєння Application Performance Monitoring (APM) з FlightPHP. Чи то ви полюєте на повільні запити, чи просто хочете зануритися в графіки затримок, ми вас охоплюємо. Давайте зробимо ваш додаток швидшим, ваших користувачів щасливішими, а сесії налагодження — легкими! +Ласкаво просимо до FlightPHP APM — вашого особистого тренера продуктивності для додатка! Цей посібник — ваша дорожня карта для налаштування, використання та освоєння моніторингу продуктивності додатків (APM) з FlightPHP. Чи полюєте ви за повільними запитами, чи просто хочете занудьгувати над графіками затримок, ми вас покриваємо. Давайте зробимо ваш додаток швидшим, ваших користувачів щасливішими, а ваші сесії налагодження — легкими! Перегляньте [демо](https://flightphp-docs-apm.sky-9.com/apm/dashboard) панелі керування для сайту Flight Docs. @@ -8,7 +8,7 @@ ## Чому APM важливий -Уявіть: ваш додаток — це зайнятий ресторан. Без способу відстежувати, скільки часу займають замовлення чи де кухня гальмує, ви вгадуєте, чому клієнти йдуть незадоволеними. APM — ваш помічник на кухні: він стежить за кожним кроком, від вхідних запитів до запитів до бази даних, і позначає все, що вас сповільнює. Повільні сторінки втрачають користувачів (дослідження кажуть, що 53% відскакують, якщо сайт завантажується понад 3 секунди!), а APM допомагає вам ловити ці проблеми *до* того, як вони вжаліть. Це проактивний спокій — менше моментів «чому це зламано?», більше перемог «дивись, як гладко це працює!». +Уявіть: ваш додаток — це зайнятий ресторан. Без способу відстежувати, скільки часу займають замовлення чи де кухня гальмує, ви здогадуєтеся, чому клієнти йдуть незадоволеними. APM — ваш помічник на кухні: він стежить за кожним кроком, від вхідних запитів до запитів до бази даних, і позначає все, що вас сповільнює. Повільні сторінки втрачають користувачів (дослідження кажуть, що 53% відскакують, якщо сайт завантажується понад 3 секунди!), а APM допомагає вам ловити ці проблеми *до* того, як вони вжаліть. Це проактивний спокій — менше моментів «чому це зламано?», більше перемог «дивись, як гладко це працює!». ## Встановлення @@ -24,12 +24,12 @@ composer require flightphp/apm ## Підтримувані бази даних -FlightPHP APM зараз підтримує такі бази даних для зберігання метрик: +FlightPHP APM наразі підтримує такі бази даних для зберігання метрик: -- **SQLite3**: Простий, на основі файлів, чудовий для локальної розробки чи малих додатків. Варіант за замовчуванням у більшості налаштувань. +- **SQLite3**: Простий, на основі файлів, чудовий для локальної розробки чи маленьких додатків. Варіант за замовчуванням у більшості налаштувань. - **MySQL/MariaDB**: Ідеальний для більших проєктів чи продакшн-середовищ, де потрібне надійне, масштабоване сховище. -Ви можете обрати тип бази даних під час кроку конфігурації (див. нижче). Переконайтеся, що ваше середовище PHP має встановлені необхідні розширення (наприклад, `pdo_sqlite` чи `pdo_mysql`). +Ви можете обрати тип бази даних під час кроку конфігурації (див. нижче). Переконайтеся, що ваше середовище PHP має встановлені необхідні розширення (наприклад, `pdo_sqlite` або `pdo_mysql`). ## Початок роботи @@ -37,10 +37,11 @@ FlightPHP APM зараз підтримує такі бази даних для ### 1. Зареєструйте APM -Додайте це до вашого `index.php` чи файлу `services.php`, щоб почати відстеження: +Вставте це у ваш `index.php` або файл `services.php`, щоб почати відстеження: ```php use flight\apm\logger\LoggerFactory; +use flight\database\PdoWrapper; use flight\Apm; $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); @@ -48,7 +49,7 @@ $Apm = new Apm($ApmLogger); $Apm->bindEventsToFlightInstance($app); // Якщо ви додаєте з'єднання з базою даних -// Має бути PdoWrapper або PdoQueryCapture з Tracy Extensions +// Має бути PdoWrapper або PdoQueryCapture з розширень Tracy $pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True обов'язково для увімкнення відстеження в APM. $Apm->addPdoConnection($pdo); ``` @@ -58,16 +59,16 @@ $Apm->addPdoConnection($pdo); - `Apm` — зірка: він слухає події Flight (запити, маршрути, помилки тощо) і збирає метрики. - `bindEventsToFlightInstance($app)` пов'язує все з вашим додатком Flight. -**Про порада: Збірка зразків** -Якщо ваш додаток зайнятий, логування *кожного* запиту може перевантажити. Використовуйте рівень вибірки (від 0.0 до 1.0): +**Про порада: Збірка вибірки** +Якщо ваш додаток зайнятий, логування *кожного* запиту може перевантажити. Використовуйте коефіцієнт вибірки (0.0 до 1.0): ```php $Apm = new Apm($ApmLogger, 0.1); // Логує 10% запитів ``` -Це тримає продуктивність жвавою, але все одно дає солідні дані. +Це тримає продуктивність жвавою, але все ж дає вам солідні дані. -### 2. Налаштуйте це +### 2. Налаштуйте його Запустіть це, щоб створити `.runway-config.json`: @@ -76,8 +77,8 @@ php vendor/bin/runway apm:init ``` **Що це робить?** -- Запускає майстер, який запитує, звідки беруться сирі метрики (джерело) і куди йде оброблені дані (призначення). -- За замовчуванням SQLite — наприклад, `sqlite:/tmp/apm_metrics.sqlite` для джерела, інше для призначення. +- Запускає майстер, який запитує, звідки беруться сирі метрики (джерело) і куди йде оброблені дані (пункт призначення). +- За замовчуванням SQLite — наприклад, `sqlite:/tmp/apm_metrics.sqlite` для джерела, інший для пункту призначення. - Ви отримаєте конфігурацію на кшталт: ```json { @@ -90,14 +91,14 @@ php vendor/bin/runway apm:init } ``` -> Цей процес також запитає, чи хочете ви запустити міграції для цього налаштування. Якщо це перше налаштування, відповідь — так. +> Цей процес також запитає, чи хочете ви запустити міграції для цієї налаштування. Якщо ви налаштовуєте це вперше, відповідь — так. **Чому два місця?** -Сирі метрики накопичуються швидко (уявіть нефільтровані логи). Робочий процес обробляє їх у структуроване призначення для панелі керування. Тримає все охайним! +Сирі метрики накопичуються швидко (уявіть нефільтровані логи). Робочий процес обробляє їх у структуроване пункт призначення для панелі керування. Тримає все в порядку! -### 3. Обробіть метрики з Worker +### 3. Обробіть метрики з робочим процесом -Робочий процес перетворює сирі метрики на дані, готові для панелі керування. Запустіть один раз: +Робочий процес перетворює сирі метрики на дані, готові для панелі керування. Запустіть його один раз: ```bash php vendor/bin/runway apm:worker @@ -105,33 +106,33 @@ php vendor/bin/runway apm:worker **Що він робить?** - Читає з вашого джерела (наприклад, `apm_metrics.sqlite`). -- Обробляє до 100 метрик (розмір партії за замовчуванням) у ваше призначення. -- Зупиняється, коли завершено або якщо метрик не лишилося. +- Обробляє до 100 метрик (розмір пакета за замовчуванням) у ваш пункт призначення. +- Зупиняється, коли закінчить або якщо метрик не лишилося. **Тримайте його запущеним** Для живих додатків ви захочете безперервну обробку. Ось ваші варіанти: -- **Режим Daemon**: +- **Режим демона**: ```bash php vendor/bin/runway apm:worker --daemon ``` - Працює вічно, обробляючи метрики по мірі надходження. Чудово для розробки чи малих налаштувань. + Працює вічно, обробляючи метрики по мірі надходження. Чудово для розробки чи маленьких налаштувань. - **Crontab**: Додайте це до вашого crontab (`crontab -e`): ```bash * * * * * php /path/to/project/vendor/bin/runway apm:worker ``` - Запускається щохвилини — ідеально для продакшну. + Запускається щохвилини — ідеально для продакшену. - **Tmux/Screen**: Почніть відокремлену сесію: ```bash tmux new -s apm-worker php vendor/bin/runway apm:worker --daemon - # Ctrl+B, then D to detach; `tmux attach -t apm-worker` to reconnect + # Ctrl+B, потім D для від'єднання; `tmux attach -t apm-worker` для під'єднання ``` - Тримає запущеним навіть якщо ви вийшли з логіну. + Тримає його запущеним навіть якщо ви вийшли з логіну. - **Кастомні налаштування**: ```bash @@ -146,7 +147,7 @@ php vendor/bin/runway apm:worker ### 4. Запустіть панель керування -Побачите життєві показники вашого додатку: +Подивіться на життєві показники вашого додатка: ```bash php vendor/bin/runway apm:dashboard @@ -156,29 +157,29 @@ php vendor/bin/runway apm:dashboard - Запускає PHP-сервер на `http://localhost:8001/apm/dashboard`. - Показує логи запитів, повільні маршрути, рівень помилок і більше. -**Налаштуйте це**: +**Налаштуйте його**: ```bash php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/local/bin/php ``` - `--host 0.0.0.0`: Доступний з будь-якого IP (корисно для віддаленого перегляду). - `--port 8080`: Використовуйте інший порт, якщо 8001 зайнятий. -- `--php-path`: Вкажіть на PHP, якщо його немає в PATH. +- `--php-path`: Вкажіть на PHP, якщо його немає в вашому PATH. Відкрийте URL у браузері та досліджуйте! -#### Режим продакшну +#### Режим продакшену -Для продакшну вам може знадобитися спробувати кілька технік, щоб запустити панель керування, оскільки, ймовірно, є фаєрволи та інші заходи безпеки. Ось кілька варіантів: +Для продакшену вам може знадобитися спробувати кілька технік, щоб запустити панель керування, оскільки, ймовірно, є фаєрволи та інші заходи безпеки. Ось кілька варіантів: -- **Використовуйте зворотний проксі**: Налаштуйте Nginx чи Apache для перенаправлення запитів до панелі керування. +- **Використовуйте зворотний проксі**: Налаштуйте Nginx або Apache для перенаправлення запитів на панель керування. - **SSH-тунель**: Якщо ви можете SSH на сервер, використовуйте `ssh -L 8080:localhost:8001 youruser@yourserver`, щоб тунелювати панель керування на вашу локальну машину. -- **VPN**: Якщо ваш сервер за VPN, підключіться до нього та отримайте доступ до панелі керування безпосередньо. -- **Налаштуйте фаєрвол**: Відкрийте порт 8001 для вашого IP чи мережі сервера. (або який порт ви встановили). -- **Налаштуйте Apache/Nginx**: Якщо у вас є веб-сервер перед додатком, ви можете налаштувати його на домен чи піддомен. Якщо ви це робите, ви встановите корінь документів на `/path/to/your/project/vendor/flightphp/apm/dashboard` +- **VPN**: Якщо ваш сервер за VPN, під'єднайтеся до нього та отримайте доступ до панелі керування безпосередньо. +- **Налаштуйте фаєрвол**: Відкрийте порт 8001 для вашого IP або мережі сервера (або будь-якого порту, який ви встановили). +- **Налаштуйте Apache/Nginx**: Якщо у вас є веб-сервер перед вашим додатком, ви можете налаштувати його на домен або піддомен. Якщо ви це робите, ви встановите корінь документа на `/path/to/your/project/vendor/flightphp/apm/dashboard`. #### Хочете іншу панель керування? -Ви можете побудувати свою власну панель керування, якщо хочете! Подивіться на директорію vendor/flightphp/apm/src/apm/presenter для ідей, як представити дані для вашої власної панелі керування! +Ви можете побудувати свою власну панель керування, якщо хочете! Подивіться на директорію vendor/flightphp/apm/src/apm/presenter для ідей, як презентувати дані для вашої власної панелі керування! ## Функції панелі керування @@ -193,9 +194,9 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l - **Довгі запити/Middleware**: Топ 5 повільних викликів бази даних та шарів middleware. - **Попадання/промах кешу**: Як часто ваш кеш рятує ситуацію. -**Додатково**: -- Фільтруйте за «Останню годину», «Останній день» чи «Останній тиждень». -- Перемикайте темний режим для пізніх сесій. +**Додатки**: +- Фільтруйте за «Останню годину», «Останній день» або «Останній тиждень.» +- Перемикайте темний режим для тих пізніх сесій. **Приклад**: Запит до `/users` може показати: @@ -231,11 +232,11 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -Тепер ви побачите, чи той API тягне ваш додаток вниз! +Тепер ви побачите, чи цей API тягне ваш додаток вниз! ## Моніторинг бази даних -Відстежуйте PDO-запити ось так: +Відстежуйте запити PDO ось так: ```php use flight\database\PdoWrapper; @@ -252,14 +253,14 @@ $Apm->addPdoConnection($pdo); **Увага**: - **Опціонально**: Пропустіть це, якщо не потрібно відстеження БД. - **Тільки PdoWrapper**: Основний PDO ще не підключений — чекайте! -- **Попередження про продуктивність**: Логування кожного запиту на БД-важкому сайті може сповільнити. Використовуйте вибірку (`$Apm = new Apm($ApmLogger, 0.1)`), щоб полегшити навантаження. +- **Попередження про продуктивність**: Логування кожного запиту на сайті з важкою БД може сповільнити. Використовуйте вибірку (`$Apm = new Apm($ApmLogger, 0.1)`), щоб полегшити навантаження. **Приклад виводу**: - Запит: `SELECT name FROM products WHERE price > 100` - Час: 0.023s - Рядки: 15 -## Опції Worker +## Опції робочого процесу Налаштуйте робочий процес на свій смак: @@ -274,9 +275,9 @@ php vendor/bin/runway apm:worker --daemon --batch_size 100 --timeout 3600 ``` Працює годину, обробляючи 100 метрик за раз. -## Request ID у додатку +## ID запиту в додатку -Кожен запит має унікальний ID запиту для відстеження. Ви можете використовувати цей ID у своєму додатку для кореляції логів і метрик. Наприклад, ви можете додати ID запиту на сторінку помилки: +Кожен запит має унікальний ID запиту для відстеження. Ви можете використовувати цей ID у вашому додатку для кореляції логів і метрик. Наприклад, ви можете додати ID запиту на сторінку помилки: ```php Flight::map('error', function($message) { @@ -302,9 +303,19 @@ php vendor/bin/runway apm:migrate **Примітка:** Якщо ваша база даних APM велика за розміром, ці міграції можуть зайняти деякий час. Ви можете запустити цю команду під час непікових годин. +### Оновлення з 0.4.3 -> 0.5.0 + +Якщо ви оновлюєтеся з 0.4.3 до 0.5.0, вам потрібно запустити таку команду: + +```bash +php vendor/bin/runway apm:config-migrate +``` + +Це мігрує вашу конфігурацію зі старого формату з використанням файлу `.runway-config.json` до нового формату, який зберігає ключі/значення в файлі `config.php`. + ## Очищення старих даних -Щоб тримати вашу базу даних охайною, ви можете очистити старі дані. Це особливо корисно, якщо ви ведете зайнятий додаток і хочете тримати розмір бази даних керованою. +Щоб тримати вашу базу даних в порядку, ви можете очистити старі дані. Це особливо корисно, якщо ви ведете зайнятий додаток і хочете тримати розмір бази даних керованим. Ви можете зробити це, запустивши таку команду: ```bash @@ -327,7 +338,7 @@ php vendor/bin/runway apm:purge --days 7 - Запустіть `php vendor/bin/runway apm:worker` вручну для обробки очікуваних метрик. - **Помилки робочого процесу?** - - Подивіться на ваші SQLite-файли (наприклад, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). + - Подивіться на ваші файли SQLite (наприклад, `sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`). - Перевірте логи PHP на стек-трейси. - **Панель керування не запускається?** @@ -336,12 +347,12 @@ php vendor/bin/runway apm:purge --days 7 - Фаєрвол блокує? Відкрийте порт або використовуйте `--host localhost`. - **Занадто повільно?** - - Зменште рівень вибірки: `$Apm = new Apm($ApmLogger, 0.05)` (5%). - - Зменште розмір партії: `--batch_size 20`. + - Зменште коефіцієнт вибірки: `$Apm = new Apm($ApmLogger, 0.05)` (5%). + - Зменште розмір пакета: `--batch_size 20`. - **Не відстежує винятки/помилки?** - - Якщо у вас увімкнено [Tracy](https://tracy.nette.org/) для проєкту, це перекриє обробку помилок Flight. Вам потрібно вимкнути Tracy і переконатися, що `Flight::set('flight.handle_errors', true);` встановлено. + - Якщо у вас увімкнено [Tracy](https://tracy.nette.org/) для вашого проєкту, це перекриє обробку помилок Flight. Вам потрібно вимкнути Tracy і переконатися, що `Flight::set('flight.handle_errors', true);` встановлено. - **Не відстежує запити до бази даних?** - Переконайтеся, що ви використовуєте `PdoWrapper` для з'єднань з базою даних. - - Переконайтеся, що останній аргумент у конструкторі — `true`. \ No newline at end of file + - Переконайтеся, що останній аргумент у конструкторі `true`. \ No newline at end of file diff --git a/content/v3/uk/awesome-plugins/awesome_plugins.md b/content/v3/uk/awesome-plugins/awesome_plugins.md index 545434b5..1343b185 100644 --- a/content/v3/uk/awesome-plugins/awesome_plugins.md +++ b/content/v3/uk/awesome-plugins/awesome_plugins.md @@ -1,28 +1,28 @@ -# Круті Плагіни +# Класні Плагіни -Flight є надзвичайно розширюваним. Існує низка плагінів, які можна використовувати для додавання функціональності до вашого додатка Flight. Деякі з них офіційно підтримуються командою Flight, а інші є мікро/лайт бібліотеками, щоб допомогти вам розпочати. +Flight є надзвичайно розширюваним. Існує низка плагінів, які можна використовувати для додавання функціональності до вашої програми Flight. Деякі з них офіційно підтримуються командою Flight, а інші є мікро/лайт бібліотеками, щоб допомогти вам розпочати. ## Документація API -Документація API є ключовою для будь-якого API. Вона допомагає розробникам зрозуміти, як взаємодіяти з вашим API та що очікувати натомість. Існує кілька інструментів, доступних для допомоги у генерації документації API для ваших проєктів Flight. +Документація API є критичною для будь-якого API. Вона допомагає розробникам зрозуміти, як взаємодіяти з вашим API та що очікувати у відповідь. Існує кілька інструментів, доступних для генерації документації API для ваших проєктів Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Блог-пост, написаний Даніелем Шрайбером, про те, як використовувати специфікацію OpenAPI з FlightPHP для побудови вашого API з використанням підходу API first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI є чудовим інструментом для допомоги у генерації документації API для ваших проєктів Flight. Його дуже легко використовувати, і його можна налаштувати відповідно до ваших потреб. Це PHP-бібліотека для допомоги у генерації документації Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Блог-пост, написаний Даніелем Шрайбером, про те, як використовувати специфікацію OpenAPI з FlightPHP для побудови вашого API з підходом API first. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI є чудовим інструментом для генерації документації API для ваших проєктів Flight. Його дуже легко використовувати, і його можна налаштувати відповідно до ваших потреб. Це PHP-бібліотека для генерації документації Swagger. -## Моніторинг продуктивності додатків (APM) +## Моніторинг Продуктивності Додатків (APM) -Моніторинг продуктивності додатків (APM) є ключовим для будь-якого додатка. Він допомагає вам зрозуміти, як працює ваш додаток і де знаходяться вузькі місця. Існує низка інструментів APM, які можна використовувати з Flight. -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM є простою бібліотекою APM, яка може бути використана для моніторингу ваших додатків Flight. Її можна використовувати для моніторингу продуктивності вашого додатка та допомоги у виявленні вузьких місць. +Моніторинг продуктивності додатків (APM) є критичним для будь-якого додатка. Він допомагає вам зрозуміти, як працює ваш додаток, і де знаходяться вузькі місця. Існує низка інструментів APM, які можна використовувати з Flight. +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM є простою бібліотекою APM, яка може використовуватися для моніторингу ваших додатків Flight. Її можна використовувати для моніторингу продуктивності вашого додатка та допомоги в ідентифікації вузьких місць. ## Асинхронність Flight вже є швидким фреймворком, але додавання до нього турбо-двигуна робить все ще веселішим (і складнішим)! -- [flightphp/async](/awesome-plugins/async) - Офіційна бібліотека Flight Async. Ця бібліотека є простим способом додати асинхронну обробку до вашого додатка. Вона використовує Swoole/Openswoole під капотом, щоб надати простий та ефективний спосіб запуску завдань асинхронно. +- [flightphp/async](/awesome-plugins/async) - Офіційна бібліотека Flight Async. Ця бібліотека є простим способом додати асинхронну обробку до вашого додатка. Вона використовує Swoole/Openswoole під капотом для надання простого та ефективного способу запуску завдань асинхронно. ## Авторизація/Дозволи -Авторизація та дозволи є ключовими для будь-якого додатка, який вимагає контролю за тим, хто може отримати доступ до чого. +Авторизація та дозволи є критичними для будь-якого додатка, який вимагає контролю за тим, хто може отримати доступ до чого. - official [flightphp/permissions](/awesome-plugins/permissions) - Офіційна бібліотека Flight Permissions. Ця бібліотека є простим способом додати дозволи на рівні користувача та додатка до вашого додатка. @@ -34,24 +34,24 @@ Flight вже є швидким фреймворком, але додаванн ## CLI -CLI-додатки є чудовим способом взаємодіяти з вашим додатком. Їх можна використовувати для генерації контролерів, відображення всіх маршрутів та багато іншого. +CLI-додатки є чудовим способом взаємодіяти з вашим додатком. Ви можете використовувати їх для генерації контролерів, відображення всіх маршрутів та інше. - official [flightphp/runway](/awesome-plugins/runway) - Runway є CLI-додатком, який допомагає вам керувати вашими додатками Flight. ## Куки -Кукі є чудовим способом зберігати невеликі обсяги даних на стороні клієнта. Їх можна використовувати для зберігання уподобань користувача, налаштувань додатка та багато іншого. +Куки є чудовим способом зберігати невеликі обсяги даних на стороні клієнта. Їх можна використовувати для зберігання уподобань користувача, налаштувань додатка та інше. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie є PHP-бібліотекою, яка надає простий та ефективний спосіб керування куками. ## Налагодження -Налагодження є ключовим під час розробки у вашому локальному середовищі. Існує кілька плагінів, які можуть покращити ваш досвід налагодження. +Налагодження є критичним, коли ви розробляєте у локальному середовищі. Існує кілька плагінів, які можуть покращити ваш досвід налагодження. - [tracy/tracy](/awesome-plugins/tracy) - Це повнофункціональний обробник помилок, який можна використовувати з Flight. Він має низку панелей, які можуть допомогти вам налагоджувати ваш додаток. Його також дуже легко розширювати та додавати власні панелі. -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Використовується з обробником помилок [Tracy](/awesome-plugins/tracy), цей плагін додає кілька додаткових панелей для допомоги з налагодженням, спеціально для проєктів Flight. +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Використовується з обробником помилок [Tracy](/awesome-plugins/tracy), цей плагін додає кілька додаткових панелей для допомоги в налагодженні спеціально для проєктів Flight. -## Бази даних +## Бази Даних Бази даних є основою для більшості додатків. Це спосіб зберігати та отримувати дані. Деякі бібліотеки баз даних є просто обгортками для написання запитів, а деякі є повноцінними ORM. @@ -61,36 +61,36 @@ CLI-додатки є чудовим способом взаємодіяти з ## Шифрування -Шифрування є ключовим для будь-якого додатка, який зберігає чутливі дані. Шифрування та дешифрування даних не є надто складними, але правильне зберігання ключа шифрування [може](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [бути](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [складним](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Найважливіше — ніколи не зберігати ключ шифрування в публічній директорії або комітити його до вашого репозиторію коду. +Шифрування є критичним для будь-якого додатка, який зберігає чутливі дані. Шифрування та дешифрування даних не є надто складним, але правильне зберігання ключа шифрування [може](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [бути](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [складним](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Найважливіше — ніколи не зберігати ключ шифрування в публічній директорії або комітити його до вашого репозиторію коду. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Це бібліотека, яка може бути використана для шифрування та дешифрування даних. Запуск та налагодження є досить простими для початку шифрування та дешифрування даних. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - Це бібліотека, яка може використовуватися для шифрування та дешифрування даних. Запуск та налагодження є досить простим для початку шифрування та дешифрування даних. -## Черга завдань +## Черга Завдань -Черги завдань дійсно корисні для асинхронної обробки завдань. Це може бути відправка email, обробка зображень або будь-що, що не потребує виконання в реальному часі. +Черги завдань дійсно корисні для асинхронної обробки завдань. Це може бути відправка електронних листів, обробка зображень або будь-що, що не потребує виконання в реальному часі. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue є бібліотекою, яка може бути використана для асинхронної обробки завдань. Її можна використовувати з beanstalkd, MySQL/MariaDB, SQLite та PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue є бібліотекою, яка може використовуватися для асинхронної обробки завдань. Її можна використовувати з beanstalkd, MySQL/MariaDB, SQLite та PostgreSQL. ## Сесії -Сесії не дуже корисні для API, але для побудови веб-додатка сесії можуть бути ключовими для підтримки стану та інформації про вхід. +Сесії не дуже корисні для API, але для побудови веб-додатка сесії можуть бути критичними для підтримки стану та інформації про вхід. -- official [flightphp/session](/awesome-plugins/session) - Офіційна бібліотека Flight Session. Це проста бібліотека сесій, яка може бути використана для зберігання та отримання даних сесії. Вона використовує вбудовану обробку сесій PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (неблокуючий, flash, сегмент, шифрування сесії). Використовує PHP open_ssl для опціонального шифрування/дешифрування даних сесії. +- official [flightphp/session](/awesome-plugins/session) - Офіційна бібліотека Flight Session. Це проста бібліотека сесій, яка може використовуватися для зберігання та отримання даних сесії. Вона використовує вбудоване керування сесіями PHP. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (неблокуючий, flash, сегмент, шифрування сесій). Використовує PHP open_ssl для опціонального шифрування/дешифрування даних сесії. ## Шаблонізація -Шаблонізація є основою для будь-якого веб-додатка з UI. Існує низка шаблонних двигунів, які можна використовувати з Flight. +Шаблонізація є основою для будь-якого веб-додатка з UI. Існує низка рушіїв шаблонізації, які можна використовувати з Flight. -- deprecated [flightphp/core View](/learn#views) - Це дуже базовий шаблонний двигун, який є частиною ядра. Не рекомендується використовувати, якщо у вашому проєкті більше кількох сторінок. -- [latte/latte](/awesome-plugins/latte) - Latte є повнофункціональним шаблонним двигуном, який дуже легко використовувати та ближчий до синтаксису PHP, ніж Twig чи Smarty. Його також дуже легко розширювати та додавати власні фільтри та функції. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate є потужним PHP-шаблонним двигуном з компіляцією активів, спадкуванням шаблонів та обробкою змінних. Має автоматичну мініфікацію CSS/JS, кешування, кодування Base64 та опціональну інтеграцію з фреймворком Flight PHP. +- deprecated [flightphp/core View](/learn#views) - Це дуже базовий рушій шаблонізації, який є частиною ядра. Не рекомендується використовувати, якщо у вашому проєкті більше кількох сторінок. +- [latte/latte](/awesome-plugins/latte) - Latte є повнофункціональним рушієм шаблонізації, який дуже легко використовувати та відчувається ближчим до синтаксису PHP, ніж Twig чи Smarty. Його також дуже легко розширювати та додавати власні фільтри та функції. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate є потужним PHP-рушієм шаблонів з компіляцією активів, успадкуванням шаблонів та обробкою змінних. Підтримує автоматичне мініфікацію CSS/JS, кешування, кодування Base64 та опціональну інтеграцію з фреймворком Flight PHP. ## Інтеграція з WordPress Хочете використовувати Flight у вашому проєкті WordPress? Є зручний плагін для цього! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Цей плагін WordPress дозволяє запускати Flight прямо поруч з WordPress. Він ідеальний для додавання кастомних API, мікросервісів або навіть повноцінних додатків до вашого сайту WordPress з використанням фреймворку Flight. Надзвичайно корисний, якщо ви хочете найкраще з обох світів! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Цей плагін WordPress дозволяє запускати Flight поруч з WordPress. Він ідеальний для додавання кастомних API, мікросервісів або навіть повних додатків до вашого сайту WordPress з використанням фреймворку Flight. Надзвичайно корисний, якщо ви хочете найкраще з обох світів! ## Внесок diff --git a/content/v3/uk/awesome-plugins/comment_template.md b/content/v3/uk/awesome-plugins/comment_template.md index 828f7cc5..5bcd67a7 100644 --- a/content/v3/uk/awesome-plugins/comment_template.md +++ b/content/v3/uk/awesome-plugins/comment_template.md @@ -1,14 +1,14 @@ # CommentTemplate -[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) — потужний рушій шаблонів PHP з компіляцією активів, успадкуванням шаблонів та обробкою змінних. Він надає простий, але гнучкий спосіб керування шаблонами з вбудованою мініфікацією CSS/JS та кешуванням. +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) — це потужний шаблонний двигун PHP з компіляцією активів, успадкуванням шаблонів та обробкою змінних. Він надає простий, але гнучкий спосіб керування шаблонами з вбудованою мініфікацією CSS/JS та кешуванням. ## Особливості - **Успадкування шаблонів**: Використовуйте макети та включайте інші шаблони -- **Компіляція активів**: Автоматична мініфікація CSS/JS та кешування +- **Компіляція активів**: Автоматична мініфікація та кешування CSS/JS - **Обробка змінних**: Змінні шаблонів з фільтрами та командами - **Кодування Base64**: Вбудовані активи як data URI -- **Інтеграція з Flight Framework**: Опціональна інтеграція з PHP фреймворком Flight +- **Інтеграція з Flight Framework**: Опціональна інтеграція з PHP-фреймворком Flight ## Встановлення @@ -20,7 +20,7 @@ composer require knifelemon/comment-template ## Базова конфігурація -Є деякі базові опції конфігурації для початку. Ви можете прочитати більше про них у [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate). +Є деякі базові опції конфігурації для початку роботи. Ви можете прочитати більше про них у [CommentTemplate Repo](https://github.com/KnifeLemon/CommentTemplate). ### Метод 1: Використання функції зворотного виклику @@ -33,14 +33,14 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // Кореневий каталог (де знаходиться index.php) - кореневий документ вашого веб-застосунку + // Кореневий каталог (де знаходиться index.php) — корінь документа вашого веб-додатка $engine->setPublicPath(__DIR__); - // Каталог файлів шаблонів - підтримує відносні та абсолютні шляхи - $engine->setSkinPath('views'); // Відносно публічного шляху + // Каталог файлів шаблонів — підтримує як відносні, так і абсолютні шляхи + $engine->setSkinPath('views'); // Відносно до public path - // Де зберігатимуться скомпільовані активи - підтримує відносні та абсолютні шляхи - $engine->setAssetPath('assets'); // Відносно публічного шляху + // Де зберігатимуться скомпільовані активи — підтримує як відносні, так і абсолютні шляхи + $engine->setAssetPath('assets'); // Відносно до public path // Розширення файлу шаблону $engine->setFileExtension('.php'); @@ -63,10 +63,10 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ - __DIR__, // publicPath - кореневий каталог (де знаходиться index.php) - 'views', // skinPath - шлях шаблонів (підтримує відносні/абсолютні) - 'assets', // assetPath - шлях скомпільованих активів (підтримує відносні/абсолютні) - '.php' // fileExtension - розширення файлу шаблону + __DIR__, // publicPath — кореневий каталог (де index.php) + 'views', // skinPath — шлях до шаблонів (підтримує відносні/абсолютні) + 'assets', // assetPath — шлях до скомпільованих активів (підтримує відносні/абсолютні) + '.php' // fileExtension — розширення файлу шаблону ]); $app->map('render', function(string $template, array $data) use ($app): void { @@ -76,37 +76,37 @@ $app->map('render', function(string $template, array $data) use ($app): void { ## Конфігурація шляхів -CommentTemplate забезпечує інтелектуальну обробку шляхів для відносних та абсолютних шляхів: +CommentTemplate надає інтелектуальне керування шляхами як для відносних, так і для абсолютних шляхів: -### Публічний шлях +### Public Path -**Публічний шлях** - це кореневий каталог вашого веб-застосунку, зазвичай де знаходиться `index.php`. Це кореневий документ, з якого веб-сервери надають файли. +**Public Path** — це кореневий каталог вашого веб-додатка, зазвичай де розташовано `index.php`. Це корінь документа, з якого веб-сервери обслуговують файли. ```php // Приклад: якщо ваш index.php знаходиться в /var/www/html/myapp/index.php $template->setPublicPath('/var/www/html/myapp'); // Кореневий каталог -// Приклад Windows: якщо ваш index.php знаходиться в C:\xampp\htdocs\myapp\index.php +// Приклад для Windows: якщо ваш index.php знаходиться в C:\xampp\htdocs\myapp\index.php $template->setPublicPath('C:\\xampp\\htdocs\\myapp'); ``` -### Конфігурація шляху шаблонів +### Конфігурація шляху до шаблонів -Шлях шаблонів підтримує як відносні, так і абсолютні шляхи: +Шлях до шаблонів підтримує як відносні, так і абсолютні шляхи: ```php $template = new Engine(); -$template->setPublicPath('/var/www/html/myapp'); // Кореневий каталог (де знаходиться index.php) +$template->setPublicPath('/var/www/html/myapp'); // Кореневий каталог (де index.php) -// Відносні шляхи - автоматично поєднуються з публічним шляхом +// Відносні шляхи — автоматично об'єднуються з public path $template->setSkinPath('views'); // → /var/www/html/myapp/views/ $template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ -// Абсолютні шляхи - використовуються як є (Unix/Linux) +// Абсолютні шляхи — використовуються як є (Unix/Linux) $template->setSkinPath('/var/www/templates'); // → /var/www/templates/ $template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ -// Абсолютні шляхи Windows +// Абсолютні шляхи для Windows $template->setSkinPath('C:\\www\\templates'); // → C:\www\templates\ $template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ @@ -114,20 +114,20 @@ $template->setSkinPath('D:/projects/templates'); // → D:/projects/templates/ $template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\templates\ ``` -### Конфігурація шляху активів +### Конфігурація шляху до активів -Шлях активів також підтримує як відносні, так і абсолютні шляхи: +Шлях до активів також підтримує як відносні, так і абсолютні шляхи: ```php -// Відносні шляхи - автоматично поєднуються з публічним шляхом +// Відносні шляхи — автоматично об'єднуються з public path $template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ $template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ -// Абсолютні шляхи - використовуються як є (Unix/Linux) +// Абсолютні шляхи — використовуються як є (Unix/Linux) $template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ $template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ -// Абсолютні шляхи Windows +// Абсолютні шляхи для Windows $template->setAssetPath('C:\\www\\static'); // → C:\www\static\ $template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ @@ -135,21 +135,21 @@ $template->setAssetPath('D:/projects/assets'); // → D:/projects/assets/ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\assets\ ``` -**Розумне визначення шляхів:** +**Інтелектуальне виявлення шляхів:** -- **Відносні шляхи**: Без початкових роздільників (`/`, `\`) або літер дисків -- **Unix абсолютні**: Починаються з `/` (напр. `/var/www/assets`) -- **Windows абсолютні**: Починаються з літери диска (напр. `C:\www`, `D:/assets`) -- **UNC шляхи**: Починаються з `\\` (напр. `\\server\share`) +- **Відносні шляхи**: Без початкових розділювачів (`/`, `\`) або букв дисків +- **Абсолютні Unix**: Починаються з `/` (наприклад, `/var/www/assets`) +- **Абсолютні Windows**: Починаються з літери диска (наприклад, `C:\www`, `D:/assets`) +- **UNC шляхи**: Починаються з `\\` (наприклад, `\\server\share`) **Як це працює:** -- Всі шляхи автоматично розв'язуються на основі типу (відносний vs абсолютний) -- Відносні шляхи поєднуються з публічним шляхом -- `@css` та `@js` створюють мінімізовані файли в: `{resolvedAssetPath}/css/` або `{resolvedAssetPath}/js/` +- Усі шляхи автоматично розв'язуються на основі типу (відносний проти абсолютного) +- Відносні шляхи об'єднуються з public path +- `@css` та `@js` створюють мініфіковані файли в: `{resolvedAssetPath}/css/` або `{resolvedAssetPath}/js/` - `@asset` копіює окремі файли до: `{resolvedAssetPath}/{relativePath}` - `@assetDir` копіює каталоги до: `{resolvedAssetPath}/{relativePath}` -- Розумне кешування: файли копіюються лише коли джерело новіше за призначення +- Інтелектуальне кешування: файли копіюються тільки коли джерело новіше за призначення ## Директиви шаблонів @@ -202,11 +202,11 @@ CommentTemplate підтримує різні стратегії заванта #### Директиви активів у файлах CSS/JS -CommentTemplate також обробляє директиви активів у CSS та JavaScript файлах під час компіляції: +CommentTemplate також обробляє директиви активів у файлах CSS та JavaScript під час компіляції: **Приклад CSS:** ```css -/* У ваших CSS файлах */ +/* У ваших файлах CSS */ @font-face { font-family: 'CustomFont'; src: url('') format('woff2'); @@ -223,7 +223,7 @@ CommentTemplate також обробляє директиви активів у **Приклад JavaScript:** ```javascript -/* У ваших JS файлах */ +/* У ваших файлах JS */ const fontUrl = ''; const imageData = ''; ``` @@ -243,16 +243,16 @@ const imageData = ''; #### Копіювання активів ```html - - + + ``` ** Приклад: ** ```html Hero Banner -Завантажити Брошуру +Завантажити брошуру - + ``` @@ -271,7 +271,7 @@ const imageData = '';
          -

          Основний контент тут...

          +

          Основний вміст тут...

          @@ -288,14 +288,14 @@ const imageData = ''; #### Фільтри змінних ```html -{$title|upper} -{$content|lower} -{$html|striptag} +{$title|upper} +{$content|lower} +{$html|striptag} {$text|escape} {$multiline|nl2br} -{$html|br2nl} +{$html|br2nl} {$description|trim} -{$subject|title} +{$subject|title} ``` #### Команди змінних @@ -304,30 +304,30 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### Ланцюжок кількох фільтрів +#### Команди змінних ```html {$content|striptag|trim|escape} ``` ### Коментарі -Коментарі шаблонів повністю видаляються з виводу і не з'являються в кінцевому HTML: +Коментарі шаблонів повністю видаляються з виводу та не з'являються в остаточному HTML: ```html {* Це однорядковий коментар шаблону *} {* - Це багаторядковий + Це багаторядковий коментар шаблону - на кілька рядків + що охоплює кілька рядків *}

          {$title}

          -{* Відлагоджувальний коментар: перевіряємо чи працює змінна title *} +{* Коментар для налагодження: перевірка, чи працює змінна title *}

          {$content}

          ``` -**Примітка**: Коментарі шаблонів `{* ... *}` відрізняються від HTML коментарів ``. Коментарі шаблонів видаляються під час обробки і ніколи не досягають браузера. +**Примітка**: Коментарі шаблонів `{* ... *}` відрізняються від HTML-коментарів ``. Коментарі шаблонів видаляються під час обробки та ніколи не досягають браузера. ## Приклад структури проекту diff --git a/content/v3/uk/awesome-plugins/runway.md b/content/v3/uk/awesome-plugins/runway.md index b978cf78..bb9dfd96 100644 --- a/content/v3/uk/awesome-plugins/runway.md +++ b/content/v3/uk/awesome-plugins/runway.md @@ -1,6 +1,6 @@ -# Розгін +# Runway -Розгін - це CLI-додаток, який допомагає вам керувати вашими застосунками Flight. Він може генерувати контролери, відображати всі маршрути та багато іншого. Він базується на відмінній бібліотеці [adhocore/php-cli](https://github.com/adhocore/php-cli). +Runway — це CLI-додаток, який допомагає керувати вашими додатками Flight. Він може генерувати контролери, відображати всі маршрути та інше. Він базується на чудовій бібліотеці [adhocore/php-cli](https://github.com/adhocore/php-cli). Натисніть [тут](https://github.com/flightphp/runway), щоб переглянути код. @@ -12,18 +12,18 @@ composer require flightphp/runway ``` -## Основна конфігурація +## Базова конфігурація -Перший раз, коли ви запустите Розгін, він проведе вас через процес налаштування і створить файл конфігурації `.runway.json` у корені вашого проєкту. Цей файл міститиме необхідні конфігурації для коректної роботи Розгону. +Вперше запускаючи Runway, він проведе вас через процес налаштування та створить файл конфігурації `.runway.json` у корені вашого проекту. Цей файл міститиме деякі необхідні конфігурації для правильної роботи Runway. ## Використання -Розгін має кілька команд, які ви можете використовувати для керування вашим застосунком Flight. Є два простих способи використовувати Розгін. +Runway має низку команд, які ви можете використовувати для керування вашим додатком Flight. Є два простих способи використовувати Runway. -1. Якщо ви використовуєте скелетний проєкт, ви можете запустити `php runway [command]` з кореня вашого проєкту. -1. Якщо ви використовуєте Розгін як пакет, встановлений через composer, ви можете запустити `vendor/bin/runway [command]` з кореня вашого проєкту. +1. Якщо ви використовуєте скелетний проект, ви можете запустити `php runway [command]` з кореня вашого проекту. +1. Якщо ви використовуєте Runway як пакет, встановлений через composer, ви можете запустити `vendor/bin/runway [command]` з кореня вашого проекту. -Для будь-якої команди ви можете передати прапор `--help`, щоб отримати більше інформації про те, як використовувати команду. +Для будь-якої команди ви можете передати прапорець `--help`, щоб отримати більше інформації про те, як використовувати команду. ```bash php runway routes --help @@ -33,7 +33,7 @@ php runway routes --help ### Генерація контролера -На основі конфігурації у вашому файлі `.runway.json`, за замовчуванням буде згенеровано контролер у каталозі `app/controllers/`. +На основі конфігурації у вашому файлі `.runway.json`, за замовчуванням буде згенеровано контролер у директорії `app/controllers/`. ```bash php runway make:controller MyController @@ -41,13 +41,13 @@ php runway make:controller MyController ### Генерація моделі Active Record -На основі конфігурації у вашому файлі `.runway.json`, за замовчуванням буде згенеровано контролер у каталозі `app/records/`. +На основі конфігурації у вашому файлі `.runway.json`, за замовчуванням буде згенеровано контролер у директорії `app/records/`. ```bash php runway make:record users ``` -Якщо, наприклад, у вас є таблиця `users` з наступною схемою: `id`, `name`, `email`, `created_at`, `updated_at`, буде створено файл подібний до наступного у файлі `app/records/UserRecord.php`: +Наприклад, якщо у вас є таблиця `users` з такою схемою: `id`, `name`, `email`, `created_at`, `updated_at`, буде створено файл, подібний до наступного, у файлі `app/records/UserRecord.php`: ```php $config JSON конфігурація з .runway-config.json + * @param array $config JSON config from .runway-config.json */ public function __construct(array $config) { - parent::__construct('make:example', 'Створити приклад для документації', $config); - $this->argument('', 'Назва смішного гіфу'); + parent::__construct('make:example', 'Create an example for the documentation', $config); + $this->argument('', 'The name of the funny gif'); } /** - * Виконує функцію + * Executes the function * * @return void */ - public function execute(string $controller) + public function execute() { $io = $this->app()->io(); - $io->info('Створення прикладу...'); + $io->info('Creating example...'); - // Зробіть щось тут + // Do something here - $io->ok('Приклад створено!'); + $io->ok('Example created!'); } } ``` -Дивіться [adhocore/php-cli Документацію](https://github.com/adhocore/php-cli) для отримання додаткової інформації про те, як створити свої власні команди у вашому застосунку Flight! \ No newline at end of file +Дивіться [Документацію adhocore/php-cli](https://github.com/adhocore/php-cli) для отримання додаткової інформації про те, як створювати власні власні команди для вашого додатка Flight! + +### Конфігурація + +Якщо вам потрібно налаштувати конфігурацію для Runway, ви можете створити файл `.runway-config.json` у корені вашого проекту. Нижче наведено деякі додаткові конфігурації, які ви можете встановити: + +```js +{ + + // This is where your application directory is located + "app_root": "app/", + + // This is the directory where your root index file is located + "index_root": "public/", + + // These are the paths to the roots of other projects + "root_paths": [ + "/home/user/different-project", + "/var/www/another-project" + ], + + // Base paths most likely don't need to be configured, but it's here if you want it + "base_paths": { + "/includes/libs/vendor", // if you have a really unique path for your vendor directory or something + }, + + // Final paths are locations within a project to search for the command files + "final_paths": { + "src/diff-path/commands", + "app/module/admin/commands", + }, + + // If you want to just add the full path, go right ahead (absolute or relative to project root) + "paths": [ + "/home/user/different-project/src/diff-path/commands", + "/var/www/another-project/app/module/admin/commands", + "app/my-unique-commands" + ] +} +``` \ No newline at end of file diff --git a/content/v3/uk/examples.md b/content/v3/uk/examples.md index 56ecfe79..19e8de70 100644 --- a/content/v3/uk/examples.md +++ b/content/v3/uk/examples.md @@ -2,25 +2,26 @@ У вас є два варіанти для початку роботи з новим проектом Flight: -- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Більш повноцінний приклад з контролерами та видами. -- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Один файл, що включає все необхідне для запуску вашого додатка в одному простому файлі. +- [Full Skeleton Boilerplate](https://github.com/flightphp/skeleton): Більш повноцінний приклад з контролерами та views. +- [Single File Skeleton Boilerplate](https://github.com/flightphp/skeleton-simple): Один файл, який містить усе необхідне для запуску вашого додатка в одному простому файлі. Приклади, надані спільнотою: - [flightravel](https://github.com/fadrian06-templates/flighravel): FlightPHP з директоріями Laravel, з інструментами PHP + GH Actions -- [fleact](https://github.com/flightphp/fleact) - Стартер-кіт FlightPHP з інтеграцією ReactJS. -- [flastro](https://github.com/flightphp/flastro) - Стартер-кіт FlightPHP з інтеграцією Astro. -- [velt](https://github.com/flightphp/velt) - Velt — це швидкий і простий шаблон стартера Svelte з бекендом FlightPHP. +- [fleact](https://github.com/flightphp/fleact) - Стартові набір FlightPHP з інтеграцією ReactJS. +- [flastro](https://github.com/flightphp/flastro) - Стартові набір FlightPHP з інтеграцією Astro. +- [velt](https://github.com/flightphp/velt) - Velt — це швидкий і простий шаблон старту Svelte з бекендом на FlightPHP. ## Потрібне натхнення? -Хоча ці приклади не є офіційно спонсорованими командою Flight, вони можуть дати вам ідеї щодо структуризації власних проектів, побудованих на Flight! +Хоча ці приклади не є офіційно спонсорованими командою Flight, вони можуть дати вам ідеї щодо того, як структурувати ваші власні проекти, побудовані на Flight! -- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify — це односторінковий додаток, що з'єднує організаторів подій з учасниками. Побудований на PHP (FlightPHP), JavaScript та MySQL, з JWT-аутентифікацією, керуванням подіями та документацією RESTful API за допомогою OpenAPI. -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental — це односторінковий, мобільно-дружній веб-додаток для оренди автомобілів, побудований на PHP (FlightPHP), JavaScript та MySQL. Він підтримує реєстрацію користувачів, перегляд та бронювання автомобілів, тоді як адміністратори можуть керувати автомобілями, користувачами та бронюваннями. Додаток має REST API, JWT-аутентифікацію та адаптивний дизайн для сучасного досвіду оренди. +- [ASC REST API Spell Checker](https://github.com/AlMosahih-ASC/asc-api-sample) - Легкий REST API для перевірки орфографії арабської мови, побудований на FlightPHP та бібліотеці ArPHP. Цей API надає можливості перевірки орфографії арабського тексту, включаючи виявлення помилково написаних слів та пропозиції виправлень. +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify — це односторінковий додаток, що з'єднує організаторів подій з учасниками. Побудований на PHP (FlightPHP), JavaScript та MySQL, він включає JWT автентифікацію, керування подіями та документацію RESTful API за допомогою OpenAPI. +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental — це односторінковий, мобільно-дружній веб-додаток для оренди автомобілів, побудований на PHP (FlightPHP), JavaScript та MySQL. Він підтримує реєстрацію користувачів, перегляд та бронювання автомобілів, тоді як адміністратори можуть керувати автомобілями, користувачами та бронюваннями. Додаток має REST API, JWT автентифікацію та адаптивний дизайн для сучасного досвіду оренди. - [Decay](https://github.com/boxybird/decay) - Flight v3 з HTMX та SleekDB, все про зомбі! ([Demo](https://decay.andrewrhyand.com)) - [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 з Middleware, Controllers, Active Record та Latte. -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Простий проект CRUD API з використанням фреймворку Flight, який надає базову структуру для нових користувачів, щоб швидко налаштувати PHP-додаток з операціями CRUD та підключенням до бази даних. Проект демонструє, як використовувати Flight для розробки RESTful API, роблячи його ідеальним інструментом для навчання для початківців та корисним стартер-кітом для більш досвідчених розробників. +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - Простий проект CRUD API з використанням фреймворку Flight, який надає базову структуру для нових користувачів, щоб швидко налаштувати PHP-додаток з операціями CRUD та підключенням до бази даних. Проект демонструє, як використовувати Flight для розробки RESTful API, роблячи його ідеальним інструментом навчання для початківців та корисним стартовим набором для більш досвідчених розробників. - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -31,7 +32,7 @@ - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Готовий до виробництва фреймворк аутентифікації, що заощаджує тижні розробки. Функції корпоративного рівня безпеки: 2FA/TOTP, інтеграція LDAP, Azure SSO, інтелектуальне обмеження швидкості, відбиток сесії, захист від brute-force, панель аналітики безпеки, всебічний аудит-логування та гранульований контроль доступу на основі ролей. +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - Готовий до виробництва фреймворк автентифікації, який заощаджує тижні розробки. Функції корпоративного рівня безпеки: 2FA/TOTP, інтеграція LDAP, Azure SSO, інтелектуальне обмеження швидкості, відбитки сесій, захист від brute-force, панель аналітики безпеки, всебічний аудит логування та гранульований контроль доступу на основі ролей. ## Хочете поділитися своїм прикладом? diff --git a/content/v3/zh/awesome-plugins/active_record.md b/content/v3/zh/awesome-plugins/active_record.md index b2ac777f..3677b2c1 100644 --- a/content/v3/zh/awesome-plugins/active_record.md +++ b/content/v3/zh/awesome-plugins/active_record.md @@ -1,12 +1,12 @@ -# Flight 活跃记录 +# Flight Active Record -活跃记录是将数据库实体映射到 PHP 对象。通俗地讲,如果你的数据库中有一个用户表,你可以将该表中的一行“翻译”为 `User` 类和你代码库中的 `$user` 对象。请参见 [基本示例](#basic-example)。 +Active Record 是将数据库实体映射到 PHP 对象的机制。简单来说,如果你的数据库中有一个 users 表,你可以将该表中的一行“翻译”成代码库中的 `User` 类和 `$user` 对象。请参阅 [基本示例](#basic-example)。 -点击 [这里](https://github.com/flightphp/active-record) 查看 GitHub 中的代码库。 +点击 [这里](https://github.com/flightphp/active-record) 查看 GitHub 仓库。 ## 基本示例 -假设你有以下表格: +假设你有以下表: ```sql CREATE TABLE users ( @@ -16,13 +16,13 @@ CREATE TABLE users ( ); ``` -现在你可以设置一个新类来表示该表: +现在你可以设置一个新类来表示这个表: ```php /** - * 活跃记录类通常是单数形式 + * ActiveRecord 类通常使用单数形式 * - * 强烈建议在这里添加表的属性作为注释 + * 强烈建议在此处将表属性作为注释添加 * * @property int $id * @property string $name @@ -39,40 +39,40 @@ class User extends flight\ActiveRecord { } ``` -现在看魔法发生吧! +现在看看魔力如何发生! ```php -// 用于 sqlite -$database_connection = new PDO('sqlite:test.db'); // 这只是示例,你可能会使用实际的数据库连接 +// 对于 SQLite +$database_connection = new PDO('sqlite:test.db'); // 这只是示例,你可能使用真实的数据库连接 -// 用于 mysql +// 对于 MySQL $database_connection = new PDO('mysql:host=localhost;dbname=test_db&charset=utf8bm4', 'username', 'password'); // 或者 mysqli $database_connection = new mysqli('localhost', 'username', 'password', 'test_db'); -// 或者通过非面向对象的方式创建 mysqli +// 或者非对象创建的 mysqli $database_connection = mysqli_connect('localhost', 'username', 'password', 'test_db'); $user = new User($database_connection); $user->name = 'Bobby Tables'; $user->password = password_hash('some cool password'); $user->insert(); -// 或 $user->save(); +// 或者 $user->save(); echo $user->id; // 1 $user->name = 'Joseph Mamma'; $user->password = password_hash('some cool password again!!!'); $user->insert(); -// 不能在这里使用 $user->save() 否则会认为这是一个更新! +// 这里不能使用 $user->save(),否则它会认为这是更新! echo $user->id; // 2 ``` -添加新用户就是这么简单!现在数据库中有一个用户行,你如何提取它? +添加新用户就是这么简单!现在数据库中已经有用户行,如何提取它? ```php -$user->find(1); // 在数据库中查找 id = 1 并返回。 +$user->find(1); // 在数据库中查找 id = 1 并返回它。 echo $user->name; // 'Bobby Tables' ``` @@ -82,61 +82,61 @@ echo $user->name; // 'Bobby Tables' $users = $user->findAll(); ``` -带有某个条件呢? +带有特定条件的呢? ```php $users = $user->like('name', '%mamma%')->findAll(); ``` -看看这有多有趣?让我们安装它并开始吧! +这有多有趣?让我们安装它并开始吧! ## 安装 -只需通过 Composer 安装 +使用 Composer 简单安装 ```php composer require flightphp/active-record ``` -## 用法 +## 使用 -这可以作为独立库使用或与 Flight PHP 框架一起使用。完全由你决定。 +这可以作为独立库使用,也可以与 Flight PHP Framework 一起使用。完全取决于你。 ### 独立使用 只需确保将 PDO 连接传递给构造函数。 ```php -$pdo_connection = new PDO('sqlite:test.db'); // 这只是示例,你可能会使用实际的数据库连接 +$pdo_connection = new PDO('sqlite:test.db'); // 这只是示例,你可能使用真实的数据库连接 $User = new User($pdo_connection); ``` -> 不想在构造函数中总是设置你的数据库连接?请参见 [数据库连接管理](#database-connection-management) 以获取其他想法! +> 不想每次都在构造函数中设置数据库连接?请参阅 [数据库连接管理](#database-connection-management) 获取其他想法! ### 在 Flight 中注册为方法 -如果你正在使用 Flight PHP 框架,可以将 ActiveRecord 类注册为服务,但你实际上不必这样做。 +如果你正在使用 Flight PHP Framework,你可以将 ActiveRecord 类注册为服务,但诚实地,你不必这么做。 ```php Flight::register('user', 'User', [ $pdo_connection ]); -// 然后你可以在控制器、函数等中这样使用它。 +// 然后你可以在控制器、函数等中使用它。 Flight::user()->find(1); ``` ## `runway` 方法 -[runway](/awesome-plugins/runway) 是一个用于 Flight 的 CLI 工具,它为该库有一个自定义命令。 +[runway](/awesome-plugins/runway) 是 Flight 的 CLI 工具,具有此库的自定义命令。 ```bash -# 用法 +# 使用方法 php runway make:record database_table_name [class_name] # 示例 php runway make:record users ``` -这将在 `app/records/` 目录中创建一个名为 `UserRecord.php` 的新类,内容如下: +这将在 `app/records/` 目录中创建一个新类 `UserRecord.php`,内容如下: ```php notNull('password')->orderBy('id DESC')->find(); -// 按特定 id 查找记录 +// 通过特定 id 查找记录 $id = 123; $user->find($id); ``` @@ -203,11 +203,11 @@ $user->findAll(); #### `isHydrated(): boolean` (v0.4.0) -如果当前记录已被填充(从数据库中获取),则返回 `true`。 +如果当前记录已从数据库中填充(获取),则返回 `true`。 ```php $user->find(1); -// 如果找到的数据记录... +// 如果找到具有数据的记录... $user->isHydrated(); // true ``` @@ -224,34 +224,34 @@ $user->insert(); ##### 基于文本的主键 -如果你有一个基于文本的主键(例如 UUID),你可以通过两种方式在插入之前设置主键值。 +如果你有基于文本的主键(例如 UUID),你可以在插入前以两种方式之一设置主键值。 ```php $user = new User($pdo_connection, [ 'primaryKey' => 'uuid' ]); $user->uuid = 'some-uuid'; $user->name = 'demo'; $user->password = md5('demo'); -$user->insert(); // 或 $user->save(); +$user->insert(); // 或者 $user->save(); ``` -或者你可以通过事件自动为你生成主键。 +或者你可以通过事件让主键自动生成。 ```php class User extends flight\ActiveRecord { public function __construct($database_connection) { parent::__construct($database_connection, 'users', [ 'primaryKey' => 'uuid' ]); - // 你也可以用这种方式来设置 primaryKey,而不是上面的数组。 + // 你也可以用这种方式设置 primaryKey 而不是上面的数组。 $this->primaryKey = 'uuid'; } protected function beforeInsert(self $self) { - $self->uuid = uniqid(); // 或者你需要用来生成唯一 ID 的任何方式 + $self->uuid = uniqid(); // 或者你生成唯一 id 的方式 } } ``` -如果在插入之前没有设置主键,它将被设置为 `rowid`,数据库会为你生成它,但它不会持久化,因为该字段可能在你的表中不存在。这就是为什么推荐使用事件来自动处理它。 +如果你在插入前没有设置主键,它将被设置为 `rowid`,数据库将为你生成它,但它不会持久化,因为该字段可能不存在于你的表中。这就是为什么推荐使用事件来自动处理这个。 #### `update(): boolean|ActiveRecord` @@ -265,7 +265,7 @@ $user->update(); #### `save(): boolean|ActiveRecord` -将当前记录插入或更新到数据库。如果记录有 id,它将更新;否则将插入。 +将当前记录插入或更新到数据库。如果记录有 id,它将更新,否则将插入。 ```php $user = new User($pdo_connection); @@ -274,7 +274,7 @@ $user->password = md5('demo'); $user->save(); ``` -**注意:** 如果你在类中定义了关系,它将递归地保存那些关系,如果它们已被定义、实例化并且有脏数据以便更新。(v0.4.0 及以上版本) +**注意:** 如果你在类中定义了关系,它将递归保存那些已定义、实例化和有脏数据更新的关系。(v0.4.0 及以上) #### `delete(): boolean` @@ -285,7 +285,7 @@ $user->gt('id', 0)->orderBy('id desc')->find(); $user->delete(); ``` -你还可以在执行搜索之前删除多条记录。 +你也可以在执行搜索前删除多条记录。 ```php $user->like('name', 'Bob%')->delete(); @@ -293,32 +293,32 @@ $user->like('name', 'Bob%')->delete(); #### `dirty(array $dirty = []): ActiveRecord` -脏数据是指记录中已更改的数据。 +脏数据指的是记录中已更改的数据。 ```php $user->greaterThan('id', 0)->orderBy('id desc')->find(); -// 到目前为止,没有任何数据是“脏”的。 +// 到目前为止没有任何“脏”数据。 -$user->email = 'test@example.com'; // 现在 email 被认为是“脏的”,因为它已更改。 +$user->email = 'test@example.com'; // 现在 email 被认为是“脏”的,因为它已更改。 $user->update(); -// 现在没有脏数据,因为它已经在数据库中更新和持久化 +// 现在没有脏数据了,因为它已被更新并持久化到数据库中 -$user->password = password_hash('newpassword'); // 现在这也是脏的 -$user->dirty(); // 不传任何内容将清除所有脏条目。 -$user->update(); // 不会更新任何东西,因为没有被捕获为脏数据。 +$user->password = password_hash()'newpassword'); // 现在这是脏的 +$user->dirty(); // 不传递任何内容将清除所有脏条目。 +$user->update(); // 不会更新任何内容,因为没有捕获到脏数据。 $user->dirty([ 'name' => 'something', 'password' => password_hash('a different password') ]); -$user->update(); // 姓名和密码都已更新。 +$user->update(); // name 和 password 都会更新。 ``` #### `copyFrom(array $data): ActiveRecord` (v0.4.0) -这是 `dirty()` 方法的别名。这样你所做的更加清晰。 +这是 `dirty()` 方法的别名。它更清楚你在做什么。 ```php $user->copyFrom([ 'name' => 'something', 'password' => password_hash('a different password') ]); -$user->update(); // 姓名和密码都已更新。 +$user->update(); // name 和 password 都会更新。 ``` #### `isDirty(): boolean` (v0.4.0) @@ -333,8 +333,7 @@ $user->isDirty(); // true #### `reset(bool $include_query_data = true): ActiveRecord` -将当前记录重置为其初始状态。这在循环行为中非常好用。 -如果你传递 `true`,它还将重置用于查找当前对象的查询数据(默认行为)。 +将当前记录重置为其初始状态。这在循环类型行为中非常有用。如果你传递 `true`,它还将重置用于查找当前对象的查询数据(默认行为)。 ```php $users = $user->greaterThan('id', 0)->orderBy('id desc')->find(); @@ -350,12 +349,12 @@ foreach($users as $user) { #### `getBuiltSql(): string` (v0.4.1) -在你运行 `find()`、`findAll()`、`insert()`、`update()` 或 `save()` 方法后,你可以获取构建的 SQL,并将其用于调试目的。 +在运行 `find()`、`findAll()`、`insert()`、`update()` 或 `save()` 方法后,你可以获取构建的 SQL 并用于调试目的。 ## SQL 查询方法 #### `select(string $field1 [, string $field2 ... ])` -如果你愿意,可以只选择表中的少数列(对于列很多的宽表来说,这更高效) +如果你愿意,你可以仅选择表中的几列(对于具有许多列的非常宽的表,这更高效) ```php $user->select('id', 'name')->find(); @@ -363,7 +362,7 @@ $user->select('id', 'name')->find(); #### `from(string $table)` -你也可以选择其他表!为什么不呢? +你也可以选择另一个表!为什么不呢?! ```php $user->select('id', 'name')->from('user')->find(); @@ -371,7 +370,7 @@ $user->select('id', 'name')->from('user')->find(); #### `join(string $table_name, string $join_condition)` -你甚至可以连接到数据库中的另一张表。 +你甚至可以连接到数据库中的另一个表。 ```php $user->join('contacts', 'contacts.user_id = users.id')->find(); @@ -379,17 +378,17 @@ $user->join('contacts', 'contacts.user_id = users.id')->find(); #### `where(string $where_conditions)` -你可以设置一些自定义的 where 参数(你不能在此 where 语句中设置参数) +你可以设置一些自定义的 where 参数(在此 where 语句中不能设置参数) ```php $user->where('id=1 AND name="demo"')->find(); ``` -**安全注意** - 你可能会想做这样的事情 `$user->where("id = '{$id}' AND name = '{$name}'")->find();`。请不要这样做!!!这容易受到所谓的 SQL 注入攻击。网上有很多文章,请搜索“sql injection attacks php”,你会发现很多关于这个主题的文章。使用这个库时,处理此问题的正确方法是, вместо этого вы должны сделать что-то более подобное `$user->eq('id', $id)->eq('name', $name)->find();` 如果你绝对不得不这样做,`PDO` 库有 `$pdo->quote($var)` 可以为你转义。只有在你使用 `quote()` 后,你才能在 `where()` 语句中使用它。 +**安全注意** - 你可能会被诱惑做类似 `$user->where("id = '{$id}' AND name = '{$name}'")->find();` 的事情。请千万不要这样做!!!这容易受到已知为 SQL 注入攻击的威胁。网上有很多文章,请 Google “sql injection attacks php”,你会找到很多关于这个主题的文章。使用此库正确处理此问题的正确方式是代替此 `where()` 方法,你应该做类似 `$user->eq('id', $id)->eq('name', $name)->find();` 的操作。如果你绝对必须这样做,`PDO` 库有 `$pdo->quote($var)` 来为你转义它。只有在使用 `quote()` 后,你才能在 `where()` 语句中使用它。 #### `group(string $group_by_statement)/groupBy(string $group_by_statement)` -根据特定条件对结果进行分组。 +按特定条件对结果进行分组。 ```php $user->select('COUNT(*) as count')->groupBy('name')->findAll(); @@ -397,7 +396,7 @@ $user->select('COUNT(*) as count')->groupBy('name')->findAll(); #### `order(string $order_by_statement)/orderBy(string $order_by_statement)` -以特定方式对返回的查询进行排序。 +以某种方式对返回的查询进行排序。 ```php $user->orderBy('name DESC')->find(); @@ -405,7 +404,7 @@ $user->orderBy('name DESC')->find(); #### `limit(string $limit)/limit(int $offset, int $limit)` -限制返回的记录数量。如果给定第二个整数,它将像 SQL 一样进行偏移和限制。 +限制返回的记录数量。如果给出第二个整数,它将是偏移量、限制,就像在 SQL 中一样。 ```php $user->orderby('name DESC')->limit(0, 10)->findAll(); @@ -414,7 +413,7 @@ $user->orderby('name DESC')->limit(0, 10)->findAll(); ## WHERE 条件 #### `equal(string $field, mixed $value) / eq(string $field, mixed $value)` -其中 `field = $value` +Where `field = $value` ```php $user->eq('id', 1)->find(); @@ -422,7 +421,7 @@ $user->eq('id', 1)->find(); #### `notEqual(string $field, mixed $value) / ne(string $field, mixed $value)` -其中 `field <> $value` +Where `field <> $value` ```php $user->ne('id', 1)->find(); @@ -430,14 +429,14 @@ $user->ne('id', 1)->find(); #### `isNull(string $field)` -其中 `field IS NULL` +Where `field IS NULL` ```php $user->isNull('id')->find(); ``` #### `isNotNull(string $field) / notNull(string $field)` -其中 `field IS NOT NULL` +Where `field IS NOT NULL` ```php $user->isNotNull('id')->find(); @@ -445,7 +444,7 @@ $user->isNotNull('id')->find(); #### `greaterThan(string $field, mixed $value) / gt(string $field, mixed $value)` -其中 `field > $value` +Where `field > $value` ```php $user->gt('id', 1)->find(); @@ -453,21 +452,21 @@ $user->gt('id', 1)->find(); #### `lessThan(string $field, mixed $value) / lt(string $field, mixed $value)` -其中 `field < $value` +Where `field < $value` ```php $user->lt('id', 1)->find(); ``` #### `greaterThanOrEqual(string $field, mixed $value) / ge(string $field, mixed $value) / gte(string $field, mixed $value)` -其中 `field >= $value` +Where `field >= $value` ```php $user->ge('id', 1)->find(); ``` #### `lessThanOrEqual(string $field, mixed $value) / le(string $field, mixed $value) / lte(string $field, mixed $value)` -其中 `field <= $value` +Where `field <= $value` ```php $user->le('id', 1)->find(); @@ -475,7 +474,7 @@ $user->le('id', 1)->find(); #### `like(string $field, mixed $value) / notLike(string $field, mixed $value)` -其中 `field LIKE $value` 或 `field NOT LIKE $value` +Where `field LIKE $value` 或 `field NOT LIKE $value` ```php $user->like('name', 'de')->find(); @@ -483,7 +482,7 @@ $user->like('name', 'de')->find(); #### `in(string $field, array $values) / notIn(string $field, array $values)` -其中 `field IN($value)` 或 `field NOT IN($value)` +Where `field IN($value)` 或 `field NOT IN($value)` ```php $user->in('id', [1, 2])->find(); @@ -491,7 +490,7 @@ $user->in('id', [1, 2])->find(); #### `between(string $field, array $values)` -其中 `field BETWEEN $value AND $value1` +Where `field BETWEEN $value AND $value1` ```php $user->between('id', [1, 2])->find(); @@ -499,33 +498,33 @@ $user->between('id', [1, 2])->find(); ### OR 条件 -可以将您的条件包装在 OR 语句中。这是通过使用 `startWrap()` 和 `endWrap()` 方法或通过在字段和值之后填充条件的第三个参数来完成的。 +你可以将条件包装在 OR 语句中。这可以通过 `startWrap()` 和 `endWrap()` 方法,或者通过在字段和值后填充条件的第三个参数来完成。 ```php // 方法 1 $user->eq('id', 1)->startWrap()->eq('name', 'demo')->or()->eq('name', 'test')->endWrap('OR')->find(); -// 这将计算为 `id = 1 AND (name = 'demo' OR name = 'test')` +// 这将评估为 `id = 1 AND (name = 'demo' OR name = 'test')` // 方法 2 $user->eq('id', 1)->eq('name', 'demo', 'OR')->find(); -// 这将计算为 `id = 1 OR name = 'demo'` +// 这将评估为 `id = 1 OR name = 'demo'` ``` ## 关系 -你可以使用这个库设置多种类型的关系。你可以在表之间设置一对多和一对一的关系。这需要在类中进行一些额外的设置。 +使用此库,你可以设置几种关系。你可以设置表之间的一对多和一对一关系。这需要在类中进行一些额外的设置。 -设置 `$relations` 数组并不困难,但猜测正确的语法可能会让人困惑。 +设置 `$relations` 数组并不难,但猜测正确的语法可能会令人困惑。 ```php protected array $relations = [ - // 你可以为键命名为任何你喜欢的名称。活跃记录的名称可能是一个不错的选择。例如:user,contact,client + // 你可以为键命名任何你喜欢的东西。ActiveRecord 的名称可能不错。例如:user, contact, client 'user' => [ // 必需 - // self::HAS_MANY,self::HAS_ONE,self::BELONGS_TO - self::HAS_ONE, // 这是关系的类型 + // self::HAS_MANY, self::HAS_ONE, self::BELONGS_TO + self::HAS_ONE, // 这是关系类型 // 必需 - 'Some_Class', // 这是将被引用的“其他”活跃记录类 + 'Some_Class', // 这是将引用的“其他” ActiveRecord 类 // 必需 // 取决于关系类型 @@ -533,14 +532,14 @@ protected array $relations = [ // self::HAS_MANY = 引用连接的外键 // self::BELONGS_TO = 引用连接的本地键 'local_or_foreign_key', - // 仅供参考,这仅连接到“其他”模型的主键 + // 顺便说一句,这也仅连接到“其他”模型的主键 // 可选 - [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // 你在连接关系时想要的额外条件 + [ 'eq' => [ 'client_id', 5 ], 'select' => 'COUNT(*) as count', 'limit' 5 ], // 连接关系时想要的额外条件 // $record->eq('client_id', 5)->select('COUNT(*) as count')->limit(5)) // 可选 - 'back_reference_name' // 如果你想将此关系反向引用回自身,例如:$user->contact->user; + 'back_reference_name' // 如果你想反向引用此关系回自身,例如 $user->contact->user; ]; ] ``` @@ -570,41 +569,142 @@ class Contact extends ActiveRecord{ } ``` -现在我们已经设置好引用,这样我们可以非常方便地使用它们! +现在我们已经设置了引用,可以非常轻松地使用它们! ```php $user = new User($pdo_connection); -// 查找最新的用户。 +// 查找最近的用户。 $user->notNull('id')->orderBy('id desc')->find(); -// 通过使用关系获取联系人: +// 使用关系获取联系人: foreach($user->contacts as $contact) { echo $contact->id; } -// 或者我们可以反过来。 +// 或者我们可以反向进行。 $contact = new Contact(); // 查找一个联系人 $contact->find(); -// 通过使用关系获取用户: +// 使用关系获取用户: echo $contact->user->name; // 这是用户名 ``` 很酷吧? +### 预加载 + +#### 概述 +预加载通过提前加载关系来解决 N+1 查询问题。预加载不是为每个记录的关系执行单独的查询,而是为每个关系仅执行一个额外的查询来获取所有相关数据。 + +> **注意:** 预加载仅适用于 v0.7.0 及以上版本。 + +#### 基本用法 +使用 `with()` 方法指定要预加载的关系: +```php +// 使用 2 个查询加载用户及其联系人,而不是 N+1 +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + foreach ($u->contacts as $contact) { + echo $contact->email; // 没有额外的查询! + } +} +``` + +#### 多个关系 +一次加载多个关系: +```php +$users = $user->with(['contacts', 'profile', 'settings'])->findAll(); +``` + +#### 关系类型 + +##### HAS_MANY +```php +// 为每个用户预加载所有联系人 +$users = $user->with('contacts')->findAll(); +foreach ($users as $u) { + // $u->contacts 已加载为数组 + foreach ($u->contacts as $contact) { + echo $contact->email; + } +} +``` +##### HAS_ONE +```php +// 为每个用户预加载一个联系人 +$users = $user->with('contact')->findAll(); +foreach ($users as $u) { + // $u->contact 已加载为对象 + echo $u->contact->email; +} +``` + +##### BELONGS_TO +```php +// 为所有联系人预加载父用户 +$contacts = $contact->with('user')->findAll(); +foreach ($contacts as $c) { + // $c->user 已加载 + echo $c->user->name; +} +``` +##### 与 find() +预加载适用于 +findAll() + 和 +find() +: + +```php +$user = $user->with('contacts')->find(1); +// 用户及其所有联系人使用 2 个查询加载 +``` +#### 性能优势 +没有预加载(N+1 问题): +```php +$users = $user->findAll(); // 1 个查询 +foreach ($users as $u) { + $contacts = $u->contacts; // N 个查询(每个用户一个!) +} +// 总计:1 + N 个查询 +``` + +使用预加载: + +```php +$users = $user->with('contacts')->findAll(); // 总计 2 个查询 +foreach ($users as $u) { + $contacts = $u->contacts; // 0 个额外查询! +} +// 总计:2 个查询(1 个用于用户 + 1 个用于所有联系人) +``` +对于 10 个用户,这将查询从 11 个减少到 2 个 - 减少 82%! + +#### 重要注意事项 +- 预加载完全是可选的 - 延迟加载仍按之前工作 +- 已加载的关系会自动跳过 +- 反向引用与预加载兼容 +- 预加载期间尊重关系回调 + +#### 限制 +- 嵌套预加载(例如, +with(['contacts.addresses']) +)当前不支持 +- 通过闭包的预加载约束在此版本中不支持 + ## 设置自定义数据 -有时你可能需要将某些唯一的东西附加到你的活跃记录中,例如一个自定义计算,这可能更容易附加到对象上,然后传递给模板。 +有时你可能需要将独特的东西附加到你的 ActiveRecord,例如自定义计算,这可能更容易附加到将传递给模板的对象。 #### `setCustomData(string $field, mixed $value)` -你可以使用 `setCustomData()` 方法附加自定义数据。 +你使用 `setCustomData()` 方法附加自定义数据。 ```php $user->setCustomData('page_view_count', $page_view_count); ``` -然后你可以像正常对象属性一样引用它。 +然后你只需像正常对象属性一样引用它。 ```php echo $user->page_view_count; @@ -612,11 +712,11 @@ echo $user->page_view_count; ## 事件 -关于这个库的另一个超级棒的功能是事件。事件在你调用的某些方法的特定时间触发。它们在自动为你设置数据时非常有帮助。 +此库的另一个超级棒的功能是关于事件的。事件在你调用某些方法时基于某些时间触发。它们在自动设置数据方面非常非常有用。 #### `onConstruct(ActiveRecord $ActiveRecord, array &config)` -如果你需要设置默认连接或类似的东西,这个功能非常有用。 +如果需要设置默认连接或其他类似的东西,这非常有用。 ```php // index.php 或 bootstrap.php @@ -629,13 +729,13 @@ Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php class User extends flight\ActiveRecord { - protected function onConstruct(self $self, array &$config) { // 不要忘记引用 & - // 你可以这样自动设置连接 + protected function onConstruct(self $self, array &$config) { // 不要忘记 & 引用 + // 你可以这样做来自动设置连接 $config['connection'] = Flight::db(); // 或者这样 $self->transformAndPersistConnection(Flight::db()); - // 你也可以通过这种方式设置表名称。 + // 你也可以这样设置表名。 $config['table'] = 'users'; } } @@ -643,7 +743,7 @@ class User extends flight\ActiveRecord { #### `beforeFind(ActiveRecord $ActiveRecord)` -如果你每次需要查询操作,这可能只对你有用。 +如果每次都需要查询操作,这可能只有用处。 ```php class User extends flight\ActiveRecord { @@ -654,7 +754,7 @@ class User extends flight\ActiveRecord { } protected function beforeFind(self $self) { - // 如果这是你的习惯,总是运行 id >= 0 + // 如果这是你的风格,总是运行 id >= 0 $self->gte('id', 0); } } @@ -662,7 +762,7 @@ class User extends flight\ActiveRecord { #### `afterFind(ActiveRecord $ActiveRecord)` -这个可能更有用,如果你需要每次获取此记录时运行一些逻辑。你需要解密某些东西吗?你需要每次运行自定义计数查询吗(虽然不高效,但也无所谓)? +如果每次获取此记录时都需要运行某些逻辑,这个可能更有用。你需要解密某些东西吗?每次都需要运行自定义计数查询吗(不高效,但无所谓)? ```php class User extends flight\ActiveRecord { @@ -676,15 +776,15 @@ class User extends flight\ActiveRecord { // 解密某些东西 $self->secret = yourDecryptFunction($self->secret, $some_key); - // 也许存储一些自定义的数据,比如查询??? - $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']); + // 也许存储自定义的东西,比如查询??? + $self->setCustomData('view_count', $self->select('COUNT(*) count')->from('user_views')->eq('user_id', $self->id)['count']; } } ``` #### `beforeFindAll(ActiveRecord $ActiveRecord)` -这可能只对你每次需要查询操作时有用。 +如果每次都需要查询操作,这可能只有用处。 ```php class User extends flight\ActiveRecord { @@ -695,7 +795,7 @@ class User extends flight\ActiveRecord { } protected function beforeFindAll(self $self) { - // 如果这是你的习惯,总是运行 id >= 0 + // 如果这是你的风格,总是运行 id >= 0 $self->gte('id', 0); } } @@ -703,7 +803,7 @@ class User extends flight\ActiveRecord { #### `afterFindAll(array $results)` -与 `afterFind()` 类似,但你可以对所有记录执行此操作! +类似于 `afterFind()`,但你可以对所有记录执行它! ```php class User extends flight\ActiveRecord { @@ -716,7 +816,7 @@ class User extends flight\ActiveRecord { protected function afterFindAll(array $results) { foreach($results as $self) { - // 做一些酷的事情,像 afterFind() + // 做一些酷的事情,就像 afterFind() } } } @@ -724,7 +824,7 @@ class User extends flight\ActiveRecord { #### `beforeInsert(ActiveRecord $ActiveRecord)` -如果每次需要设置默认值,这非常有用。 +如果每次都需要设置一些默认值,这非常有用。 ```php class User extends flight\ActiveRecord { @@ -749,7 +849,7 @@ class User extends flight\ActiveRecord { #### `afterInsert(ActiveRecord $ActiveRecord)` -也许你有用例,在数据插入后更改数据? +也许你有在插入后更改数据的用例? ```php class User extends flight\ActiveRecord { @@ -762,14 +862,14 @@ class User extends flight\ActiveRecord { protected function afterInsert(self $self) { // 你随意 Flight::cache()->set('most_recent_insert_id', $self->id); - // 或者别的…… + // 或者其他.... } } ``` #### `beforeUpdate(ActiveRecord $ActiveRecord)` -每次需要在更新时设置一些默认值,这真的很有用。 +如果每次更新时都需要设置一些默认值,这非常有用。 ```php class User extends flight\ActiveRecord { @@ -790,7 +890,7 @@ class User extends flight\ActiveRecord { #### `afterUpdate(ActiveRecord $ActiveRecord)` -也许你有用例,在数据更新后更改数据? +也许你有在更新后更改数据的用例? ```php class User extends flight\ActiveRecord { @@ -803,14 +903,14 @@ class User extends flight\ActiveRecord { protected function afterInsert(self $self) { // 你随意 Flight::cache()->set('most_recently_updated_user_id', $self->id); - // 或者别的…… + // 或者其他.... } } ``` #### `beforeSave(ActiveRecord $ActiveRecord)/afterSave(ActiveRecord $ActiveRecord)` -如果你想在插入或更新时都发生事件,这很有用。我就不多说了,但你肯定能猜到它的用途。 +如果希望在插入或更新时都发生事件,这很有用。我就不长篇解释了,但我想你能猜到是什么。 ```php class User extends flight\ActiveRecord { @@ -828,7 +928,7 @@ class User extends flight\ActiveRecord { #### `beforeDelete(ActiveRecord $ActiveRecord)/afterDelete(ActiveRecord $ActiveRecord)` -不确定你想在这里做什么,但在这里没有评判!去做吧! +不确定你想在这里做什么,但这里没有判断!去吧! ```php class User extends flight\ActiveRecord { @@ -839,30 +939,30 @@ class User extends flight\ActiveRecord { } protected function beforeDelete(self $self) { - echo '他是一名勇敢的士兵... :cry-face:'; + echo 'He was a brave soldier... :cry-face:'; } } ``` ## 数据库连接管理 -当你使用此库时,可以通过几种不同的方式设置数据库连接。你可以在构造函数中设置连接,可以通过配置变量 `$config['connection']` 来设置,或者可以通过 `setDatabaseConnection()` 来设置(v0.4.1)。 +使用此库时,你可以以几种不同的方式设置数据库连接。你可以在构造函数中设置它,通过配置变量 `$config['connection']` 设置它,或者通过 `setDatabaseConnection()` 设置它 (v0.4.1)。 ```php $pdo_connection = new PDO('sqlite:test.db'); // 例如 $user = new User($pdo_connection); -// 或 +// 或者 $user = new User(null, [ 'connection' => $pdo_connection ]); -// 或 +// 或者 $user = new User(); $user->setDatabaseConnection($pdo_connection); ``` -如果你想避免在每次调用活跃记录时设置 `$database_connection`,可以有其他方法! +如果你想避免每次调用 active record 时都设置 `$database_connection`,有办法绕过它! ```php // index.php 或 bootstrap.php -// 将其作为一个已注册的类设置在 Flight 中 +// 在 Flight 中将其设置为注册类 Flight::register('db', 'PDO', [ 'sqlite:test.db' ]); // User.php @@ -875,23 +975,23 @@ class User extends flight\ActiveRecord { } } -// 现在,不需要任何参数! +// 现在,不需要参数! $user = new User(); ``` -> **注意:** 如果你打算进行单元测试,这种方式可能会给单元测试带来一些挑战,但总体来说,因为可以通过 `setDatabaseConnection()` 或 `$config['connection']` 注入连接,所以还不错。 +> **注意:** 如果你计划进行单元测试,这样做可能会给单元测试带来一些挑战,但总体上,因为你可以使用 `setDatabaseConnection()` 或 `$config['connection']` 注入连接,所以不是太糟糕。 -如果你需要刷新数据库连接,比如如果你正在运行一个长时间运行的 CLI 脚本,并且需要定期刷新连接,可以通过 `$your_record->setDatabaseConnection($pdo_connection)` 重新设置连接。 +如果你需要刷新数据库连接,例如如果你正在运行一个长时间运行的 CLI 脚本并需要每隔一段时间刷新连接,你可以使用 `$your_record->setDatabaseConnection($pdo_connection)` 重新设置连接。 ## 贡献 -请这样做。 :D +请贡献。:D ### 设置 -当你贡献时,请确保运行 `composer test-coverage` 以保持 100% 的测试覆盖率(这不是准确的单元测试覆盖率,更像是集成测试)。 +贡献时,请确保运行 `composer test-coverage` 以保持 100% 测试覆盖率(这不是真正的单元测试覆盖率,更像是集成测试)。 -还要确保运行 `composer beautify` 和 `composer phpcs` 来修复任何语法错误。 +还要确保运行 `composer beautify` 和 `composer phpcs` 以修复任何 linting 错误。 ## 许可证 diff --git a/content/v3/zh/awesome-plugins/apm.md b/content/v3/zh/awesome-plugins/apm.md index 344bf19c..b9cb24c4 100644 --- a/content/v3/zh/awesome-plugins/apm.md +++ b/content/v3/zh/awesome-plugins/apm.md @@ -1,14 +1,14 @@ # FlightPHP APM 文档 -欢迎来到 FlightPHP APM——您应用的个人性能教练!本指南是您设置、使用和掌握使用 FlightPHP 的应用性能监控 (APM) 的路线图。无论您是在追查慢请求,还是只是想对延迟图表着迷,我们都会为您提供支持。让我们让您的应用更快,让您的用户更快乐,让您的调试会话变得轻松! +欢迎来到 FlightPHP APM——您应用的个人性能教练!本指南是您设置、使用和掌握使用 FlightPHP 的应用性能监控 (APM) 的路线图。无论您是在追查慢请求,还是只是想对延迟图表进行 geek 出神,我们都会为您提供支持。让我们让您的应用更快,让您的用户更快乐,让您的调试会话变得轻松! -查看 Flight Docs 站点的仪表板[演示](https://flightphp-docs-apm.sky-9.com/apm/dashboard)。 +查看 Flight Docs 站点的仪表板 [demo](https://flightphp-docs-apm.sky-9.com/apm/dashboard)。 ![FlightPHP APM](/images/apm.png) ## 为什么 APM 重要 -想象一下:您的应用就像一家繁忙的餐厅。没有一种方法来跟踪订单需要多长时间或厨房在哪里卡住,您只能猜测为什么客户离开时心情不好。APM 是您的副厨师——它监视每一个步骤,从传入请求到数据库查询,并标记任何减慢您速度的东西。慢页面会丢失用户(研究表明,如果网站加载超过 3 秒,53% 的用户会跳出!),APM 帮助您在问题刺痛之前抓住它们。它是主动的安心——更少的“为什么这个坏了?”时刻,更多的“看这个运行得多顺畅!”胜利。 +想象一下:您的应用是一家繁忙的餐厅。如果没有一种方法来跟踪订单需要多长时间或厨房在哪里卡住,您就会猜测为什么客户离开时不高兴。APM 是您的副厨师——它监视每一个步骤,从传入请求到数据库查询,并标记任何减慢您速度的东西。慢页面会丢失用户(研究表明,如果网站加载超过 3 秒,53% 的用户会反弹!),而 APM 帮助您在问题刺痛之前抓住它们。它是主动的安心——更少的“为什么这个坏了?”时刻,更多的“看这个运行得多流畅!”胜利。 ## 安装 @@ -24,48 +24,49 @@ composer require flightphp/apm ## 支持的数据库 -FlightPHP APM 当前支持以下数据库来存储指标: +FlightPHP APM 当前支持以下数据库用于存储指标: -- **SQLite3**:简单、基于文件,非常适合本地开发或小型应用。大多数设置中的默认选项。 +- **SQLite3**:简单、基于文件,适合本地开发或小型应用。大多数设置中的默认选项。 - **MySQL/MariaDB**:适合大型项目或生产环境,您需要健壮、可扩展的存储。 -您可以在配置步骤(见下文)中选择您的数据库类型。请确保您的 PHP 环境安装了必要的扩展(例如,`pdo_sqlite` 或 `pdo_mysql`)。 +您可以在配置步骤(见下文)中选择您的数据库类型。确保您的 PHP 环境安装了必要的扩展(例如,`pdo_sqlite` 或 `pdo_mysql`)。 -## 快速开始 +## 入门 -以下是通往 APM 卓越的逐步指南: +以下是通往 APM 精彩的逐步指南: ### 1. 注册 APM -将此代码放入您的 `index.php` 或 `services.php` 文件中以开始跟踪: +将此代码放入您的 `index.php` 或 `services.php` 文件中开始跟踪: ```php use flight\apm\logger\LoggerFactory; +use flight\database\PdoWrapper; use flight\Apm; $ApmLogger = LoggerFactory::create(__DIR__ . '/../../.runway-config.json'); $Apm = new Apm($ApmLogger); $Apm->bindEventsToFlightInstance($app); -// 如果您正在添加数据库连接 -// 必须是来自 Tracy Extensions 的 PdoWrapper 或 PdoQueryCapture -$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- 需要 true 以在 APM 中启用跟踪。 +// 如果您添加数据库连接 +// 必须是 PdoWrapper 或来自 Tracy Extensions 的 PdoQueryCapture +$pdo = new PdoWrapper('mysql:host=localhost;dbname=example', 'user', 'pass', null, true); // <-- True 必需以在 APM 中启用跟踪。 $Apm->addPdoConnection($pdo); ``` **这里发生了什么?** -- `LoggerFactory::create()` 获取您的配置(稍后详述)并设置一个日志记录器——默认是 SQLite。 -- `Apm` 是明星——它监听 Flight 的事件(请求、路由、错误等)并收集指标。 -- `bindEventsToFlightInstance($app)` 将其全部绑定到您的 Flight 应用。 +- `LoggerFactory::create()` 获取您的配置(很快会详细说明)并设置一个日志记录器——默认是 SQLite。 +- `Apm` 是主角——它监听 Flight 的事件(请求、路由、错误等)并收集指标。 +- `bindEventsToFlightInstance($app)` 将它与您的 Flight 应用绑定。 **专业提示:采样** -如果您的应用很繁忙,记录*每个*请求可能会过载。用采样率(0.0 到 1.0): +如果您的应用很繁忙,记录*每个*请求可能会超载系统。使用采样率(0.0 到 1.0): ```php $Apm = new Apm($ApmLogger, 0.1); // 记录 10% 的请求 ``` -这保持性能敏捷,同时仍提供可靠的数据。 +这保持性能敏捷,同时仍为您提供可靠的数据。 ### 2. 配置它 @@ -75,10 +76,10 @@ $Apm = new Apm($ApmLogger, 0.1); // 记录 10% 的请求 php vendor/bin/runway apm:init ``` -**这是做什么?** +**这做什么?** - 启动一个向导,询问原始指标来自哪里(源)和处理后的数据去哪里(目标)。 -- 默认是 SQLite——例如,源是 `sqlite:/tmp/apm_metrics.sqlite`,目标是另一个。 -- 您将得到类似这样的配置: +- 默认是 SQLite——例如,源为 `sqlite:/tmp/apm_metrics.sqlite`,目标为另一个。 +- 您将得到一个像这样的配置: ```json { "apm": { @@ -90,14 +91,14 @@ php vendor/bin/runway apm:init } ``` -> 此过程还会询问您是否要为此设置运行迁移。如果您是第一次设置,答案是是的。 +> 此过程还会询问您是否要为此设置运行迁移。如果您是第一次设置,答案是 yes。 **为什么有两个位置?** -原始指标堆积很快(想想未过滤的日志)。工作进程将它们处理成仪表板用的结构化目标。保持一切整洁! +原始指标堆积很快(想想未过滤的日志)。工作进程将它们处理成仪表板用的结构化目标。保持事物整洁! -### 3. 使用 Worker 处理指标 +### 3. 使用工作进程处理指标 -Worker 将原始指标转换为仪表板就绪数据。运行一次: +工作进程将原始指标转换为仪表板就绪数据。运行一次: ```bash php vendor/bin/runway apm:worker @@ -105,17 +106,17 @@ php vendor/bin/runway apm:worker **它在做什么?** - 从您的源读取(例如,`apm_metrics.sqlite`)。 -- 处理最多 100 个指标(默认批次大小)到您的目标。 -- 完成后停止,或如果没有剩余指标。 +- 将最多 100 个指标(默认批次大小)处理到您的目标。 +- 处理完毕或没有指标剩余时停止。 -**保持它运行** +**保持运行** 对于实时应用,您需要连续处理。以下是您的选项: - **守护进程模式**: ```bash php vendor/bin/runway apm:worker --daemon ``` - 永远运行,处理指标如它们到来。适合开发或小型设置。 + 永远运行,处理传入的指标。适合开发或小型设置。 - **Crontab**: 将此添加到您的 crontab(`crontab -e`): @@ -138,11 +139,11 @@ php vendor/bin/runway apm:worker php vendor/bin/runway apm:worker --batch_size 50 --max_messages 1000 --timeout 300 ``` - `--batch_size 50`:一次处理 50 个指标。 - - `--max_messages 1000`:处理 1000 个指标后停止。 + - `--max_messages 1000`:1000 个指标后停止。 - `--timeout 300`:5 分钟后退出。 **为什么费心?** -没有 Worker,您的仪表板是空的。它是原始日志和可操作洞察之间的桥梁。 +没有工作进程,您的仪表板是空的。它是原始日志和可操作洞察之间的桥梁。 ### 4. 启动仪表板 @@ -168,13 +169,13 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l #### 生产模式 -对于生产,您可能需要尝试一些技巧来运行仪表板,因为可能有防火墙和其他安全措施。以下是几个选项: +对于生产,您可能需要尝试一些技术来运行仪表板,因为可能有防火墙和其他安全措施。以下是几个选项: - **使用反向代理**:设置 Nginx 或 Apache 将请求转发到仪表板。 - **SSH 隧道**:如果您可以 SSH 到服务器,使用 `ssh -L 8080:localhost:8001 youruser@yourserver` 将仪表板隧道到您的本地机器。 - **VPN**:如果您的服务器在 VPN 后面,连接到它并直接访问仪表板。 - **配置防火墙**:为您的 IP 或服务器网络打开端口 8001(或您设置的任何端口)。 -- **配置 Apache/Nginx**:如果您的应用前面有 Web 服务器,您可以配置它到域名或子域名。如果您这样做,您将文档根目录设置为 `/path/to/your/project/vendor/flightphp/apm/dashboard` +- **配置 Apache/Nginx**:如果您的应用前面有 Web 服务器,您可以配置它到域名或子域名。如果这样做,您将文档根目录设置为 `/path/to/your/project/vendor/flightphp/apm/dashboard`。 #### 想要不同的仪表板? @@ -185,28 +186,28 @@ php vendor/bin/runway apm:dashboard --host 0.0.0.0 --port 8080 --php-path=/usr/l 仪表板是您的 APM 总部——以下是您将看到的内容: - **请求日志**:每个请求带有时间戳、URL、响应代码和总时间。点击“Details”查看中间件、查询和错误。 -- **最慢请求**:占用时间最多的前 5 个请求(例如,“/api/heavy” 2.5 秒)。 -- **最慢路由**:按平均时间的前 5 个路由——非常适合发现模式。 -- **错误率**:失败请求的百分比(例如,2.3% 500 错误)。 +- **最慢请求**:占用时间最多的前 5 个请求(例如,“/api/heavy” 2.5s)。 +- **最慢路由**:按平均时间排序的前 5 个路由——适合发现模式。 +- **错误率**:失败请求的百分比(例如,2.3% 500s)。 - **延迟百分位**:95th (p95) 和 99th (p99) 响应时间——了解您的最坏情况。 -- **响应代码图表**:随时间可视化 200、404、500 等。 +- **响应代码图表**:随时间可视化 200s、404s、500s。 - **长查询/中间件**:前 5 个慢数据库调用和中间件层。 - **缓存命中/未命中**:您的缓存拯救局面的频率。 -**额外功能**: +**额外**: - 按“Last Hour”、“Last Day”或“Last Week”过滤。 -- 为那些深夜会话切换暗黑模式。 +- 为那些深夜会话切换暗模式。 **示例**: 对 `/users` 的请求可能显示: - 总时间:150ms - 中间件:`AuthMiddleware->handle` (50ms) - 查询:`SELECT * FROM users` (80ms) -- 缓存:命中 `user_list` (5ms) +- 缓存:`user_list` 命中 (5ms) ## 添加自定义事件 -跟踪任何东西——如 API 调用或支付过程: +跟踪任何东西——如 API 调用或支付流程: ```php use flight\apm\CustomEvent; @@ -219,7 +220,7 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('api_call', [ ``` **它在哪里显示?** -在仪表板的请求详细信息下“Custom Events”——带有漂亮的 JSON 格式,可展开。 +在仪表板的请求详细信息下的“Custom Events”——带有漂亮的 JSON 格式,可扩展。 **用例**: ```php @@ -231,7 +232,7 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ 'success' => $apiResponse !== false ])); ``` -现在您将看到那个 API 是否拖慢了您的应用! +现在您将看到那个 API 是否在拖慢您的应用! ## 数据库监控 @@ -240,7 +241,7 @@ $app->eventDispatcher()->trigger('apm.custom', new CustomEvent('external_api', [ ```php use flight\database\PdoWrapper; -$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- 需要 true 以在 APM 中启用跟踪。 +$pdo = new PdoWrapper('sqlite:/path/to/db.sqlite', null, null, null, true); // <-- True 必需以在 APM 中启用跟踪。 $Apm->addPdoConnection($pdo); ``` @@ -250,7 +251,7 @@ $Apm->addPdoConnection($pdo); - 行数(例如,42) **注意**: -- **可选**:如果您不需要 DB 跟踪,请跳过。 +- **可选**:如果您不需要 DB 跟踪,跳过此项。 - **仅 PdoWrapper**:核心 PDO 尚未钩住——敬请期待! - **性能警告**:在 DB 密集型站点记录每个查询可能会减慢速度。使用采样(`$Apm = new Apm($ApmLogger, 0.1)`)来减轻负载。 @@ -259,14 +260,14 @@ $Apm->addPdoConnection($pdo); - 时间:0.023s - 行:15 -## Worker 选项 +## 工作进程选项 -根据您的喜好调整 Worker: +根据您的喜好调整工作进程: - `--timeout 300`:5 分钟后停止——适合测试。 - `--max_messages 500`:上限 500 个指标——保持有限。 - `--batch_size 200`:一次处理 200 个——平衡速度和内存。 -- `--daemon`:不间断运行——适合实时监控。 +- `--daemon`:不停运行——适合实时监控。 **示例**: ```bash @@ -293,40 +294,50 @@ Flight::map('error', function($message) { ## 升级 -如果您正在升级到 APM 的较新版本,有可能需要运行数据库迁移。您可以通过运行以下命令来完成: +如果您正在升级到 APM 的较新版本,有可能需要运行数据库迁移。您可以通过运行以下命令来实现: ```bash php vendor/bin/runway apm:migrate ``` -这将运行任何必要的迁移,以将数据库模式更新到最新版本。 +这将运行任何必要的迁移,以将数据库架构更新到最新版本。 **注意:** 如果您的 APM 数据库大小很大,这些迁移可能需要一些时间运行。您可能希望在非高峰时段运行此命令。 +### 从 0.4.3 升级到 0.5.0 + +如果您从 0.4.3 升级到 0.5.0,您需要运行以下命令: + +```bash +php vendor/bin/runway apm:config-migrate +``` + +这将您的配置从使用 `.runway-config.json` 文件的旧格式迁移到新格式,该格式将键/值存储在 `config.php` 文件中。 + ## 清除旧数据 -为了保持您的数据库整洁,您可以清除旧数据。这特别有用,如果您正在运行一个繁忙的应用并希望保持数据库大小可管理。 -您可以通过运行以下命令来完成: +为了保持数据库整洁,您可以清除旧数据。这对于运行繁忙应用并希望保持数据库大小可管理的用户特别有用。 +您可以通过运行以下命令来实现: ```bash php vendor/bin/runway apm:purge ``` -这将从数据库中移除所有超过 30 天的数据。您可以通过将不同值传递给 `--days` 选项来调整天数: +这将从数据库中删除超过 30 天的数据。您可以通过将不同值传递给 `--days` 选项来调整天数: ```bash php vendor/bin/runway apm:purge --days 7 ``` -这将从数据库中移除所有超过 7 天的数据。 +这将从数据库中删除超过 7 天的数据。 ## 故障排除 卡住了?试试这些: - **没有仪表板数据?** - - Worker 运行了吗?检查 `ps aux | grep apm:worker`。 + - 工作进程在运行吗?检查 `ps aux | grep apm:worker`。 - 配置路径匹配吗?验证 `.runway-config.json` DSN 指向真实文件。 - 手动运行 `php vendor/bin/runway apm:worker` 来处理待处理指标。 -- **Worker 错误?** +- **工作进程错误?** - 窥视您的 SQLite 文件(例如,`sqlite3 /tmp/apm_metrics.sqlite "SELECT * FROM apm_metrics_log LIMIT 5"`)。 - 检查 PHP 日志以获取堆栈跟踪。 diff --git a/content/v3/zh/awesome-plugins/awesome_plugins.md b/content/v3/zh/awesome-plugins/awesome_plugins.md index 34042188..e832fcf3 100644 --- a/content/v3/zh/awesome-plugins/awesome_plugins.md +++ b/content/v3/zh/awesome-plugins/awesome_plugins.md @@ -1,30 +1,30 @@ -# 优秀的插件 +# 精彩插件 -Flight 具有极强的可扩展性。有许多插件可用于为您的 Flight 应用程序添加功能。其中一些由 Flight 团队官方支持,其他则是一些微型/轻量级库,帮助您快速上手。 +Flight 极具扩展性。有许多插件可用于为您的 Flight 应用程序添加功能。其中一些由 Flight 团队官方支持,其他则是微型/轻量级库,帮助您快速上手。 ## API 文档 -API 文档对于任何 API 都至关重要。它帮助开发者理解如何与您的 API 交互以及预期返回结果。有几个工具可用于帮助您为 Flight 项目生成 API 文档。 +API 文档对任何 API 都至关重要。它帮助开发者了解如何与您的 API 交互以及预期返回结果。有几个工具可用于帮助您为 Flight 项目生成 API 文档。 - [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - 由 Daniel Schreiber 撰写的博客文章,介绍如何使用 OpenAPI 规范与 FlightPHP 结合,采用 API 优先方法构建您的 API。 -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI 是一个优秀的工具,可帮助您为 Flight 项目生成 API 文档。它非常易用,并且可以自定义以满足您的需求。这是用于生成 Swagger 文档的 PHP 库。 +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI 是一个优秀的工具,可帮助您为 Flight 项目生成 API 文档。它非常易用,并可自定义以满足您的需求。这是用于生成 Swagger 文档的 PHP 库。 ## 应用程序性能监控 (APM) -应用程序性能监控 (APM) 对于任何应用程序都至关重要。它帮助您了解应用程序的性能表现以及瓶颈所在。有许多 APM 工具可与 Flight 一起使用。 +应用程序性能监控 (APM) 对任何应用程序都至关重要。它帮助您了解应用程序的性能表现以及瓶颈所在。有许多 APM 工具可与 Flight 一起使用。 - official [flightphp/apm](/awesome-plugins/apm) - Flight APM 是一个简单的 APM 库,可用于监控您的 Flight 应用程序。它可用于监控应用程序性能并帮助您识别瓶颈。 ## 异步 Flight 已经是一个快速的框架,但为其添加涡轮引擎会让一切变得更有趣(且更具挑战性)! -- [flightphp/async](/awesome-plugins/async) - 官方 Flight Async 库。此库是一种简单的方式,为您的应用程序添加异步处理。它在底层使用 Swoole/Openswoole,提供简单有效的异步运行任务的方法。 +- [flightphp/async](/awesome-plugins/async) - 官方 Flight Async 库。此库提供了一种简单的方式,为您的应用程序添加异步处理。它在底层使用 Swoole/Openswoole,提供简单有效的异步运行任务的方法。 ## 授权/权限 -授权和权限对于任何需要控制访问权限的应用程序都至关重要。 +授权和权限对任何需要控制访问权限的应用程序都至关重要。 -- official [flightphp/permissions](/awesome-plugins/permissions) - 官方 Flight Permissions 库。此库是一种简单的方式,为您的应用程序添加用户和应用程序级别的权限。 +- official [flightphp/permissions](/awesome-plugins/permissions) - 官方 Flight Permissions 库。此库提供了一种简单的方式,为您的应用程序添加用户和应用程序级别的权限。 ## 缓存 @@ -38,59 +38,59 @@ CLI 应用程序是与您的应用程序交互的绝佳方式。您可以使用 - official [flightphp/runway](/awesome-plugins/runway) - Runway 是一个 CLI 应用程序,帮助您管理 Flight 应用程序。 -## Cookies +## Cookie -Cookies 是存储客户端小量数据的绝佳方式。它们可用于存储用户偏好、应用程序设置等。 +Cookie 是存储客户端小量数据的绝佳方式。它们可用于存储用户偏好、应用程序设置等。 -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie 是一个 PHP 库,提供简单有效的方式来管理 cookies。 +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie 是一个 PHP 库,提供简单有效的 Cookie 管理方式。 ## 调试 在本地环境中开发时,调试至关重要。有几个插件可以提升您的调试体验。 - [tracy/tracy](/awesome-plugins/tracy) - 这是一个功能齐全的错误处理器,可与 Flight 一起使用。它有多个面板可帮助您调试应用程序。它也非常易于扩展并添加您自己的面板。 -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - 与 [Tracy](/awesome-plugins/tracy) 错误处理器一起使用,此插件添加了一些额外的面板,专门帮助调试 Flight 项目。 +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - 与 [Tracy](/awesome-plugins/tracy) 错误处理器一起使用,此插件添加了一些额外面板,专门帮助调试 Flight 项目。 ## 数据库 -数据库是大多数应用程序的核心。这是存储和检索数据的方式。有些数据库库只是用于编写查询的包装器,有些则是完整的 ORM。 +数据库是大多数应用程序的核心。这是存储和检索数据的方式。有些数据库库只是查询的包装器,有些则是完整的 ORM。 -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 官方 Flight PDO Wrapper,是核心的一部分。这是一个简单的包装器,帮助简化编写和执行查询的过程。它不是 ORM。 -- official [flightphp/active-record](/awesome-plugins/active-record) - 官方 Flight ActiveRecord ORM/Mapper。一个优秀的库,用于轻松检索和存储数据库中的数据。 -- [byjg/php-migration](/awesome-plugins/migrations) - 用于跟踪项目中所有数据库更改的插件。 +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 官方 Flight PDO 包装器,是核心的一部分。这是一个简单的包装器,帮助简化编写和执行查询的过程。它不是 ORM。 +- official [flightphp/active-record](/awesome-plugins/active-record) - 官方 Flight ActiveRecord ORM/映射器。用于轻松检索和存储数据库数据的出色小库。 +- [byjg/php-migration](/awesome-plugins/migrations) - 用于跟踪项目中所有数据库变更的插件。 ## 加密 -对于任何存储敏感数据的应用程序,加密至关重要。加密和解密数据并不难,但正确存储加密密钥 [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [会](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [困难](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)。最重要的是,切勿将加密密钥存储在公共目录中或提交到您的代码仓库。 +加密对任何存储敏感数据的应用程序都至关重要。加密和解密数据并不难,但正确存储加密密钥 [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [很](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [困难](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)。最重要的是,切勿将加密密钥存储在公共目录中或提交到代码仓库。 - [defuse/php-encryption](/awesome-plugins/php-encryption) - 这是一个可用于加密和解密数据的库。启动并运行非常简单,即可开始加密和解密数据。 ## 作业队列 -作业队列对于异步处理任务非常有用。这可以是发送电子邮件、处理图像,或任何不需要实时完成的任务。 +作业队列对于异步处理任务非常有帮助。这可以是发送电子邮件、处理图像,或任何不需要实时完成的任务。 - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue 是一个可用于异步处理作业的库。它可与 beanstalkd、MySQL/MariaDB、SQLite 和 PostgreSQL 一起使用。 ## 会话 -会话对于 API 并不太有用,但对于构建 Web 应用程序,会话对于维护状态和登录信息至关重要。 +会话对 API 不是很有用,但对于构建 Web 应用程序,会话对于维护状态和登录信息至关重要。 - official [flightphp/session](/awesome-plugins/session) - 官方 Flight Session 库。这是一个简单的会话库,可用于存储和检索会话数据。它使用 PHP 内置的会话处理。 -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 会话管理器(非阻塞、闪存、段、会话加密)。使用 PHP open_ssl 可选地加密/解密会话数据。 +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 会话管理器(非阻塞、闪存、分段、会话加密)。使用 PHP open_ssl 可选加密/解密会话数据。 ## 模板 -模板是任何具有 UI 的 Web 应用程序的核心。有许多模板引擎可与 Flight 一起使用。 +模板是任何带 UI 的 Web 应用程序的核心。有许多模板引擎可与 Flight 一起使用。 -- deprecated [flightphp/core View](/learn#views) - 这是一个非常基本的模板引擎,是核心的一部分。如果您的项目超过几个页面,不推荐使用。 +- deprecated [flightphp/core View](/learn#views) - 这是一个非常基本的模板引擎,是核心的一部分。如果您的项目超过几页,不推荐使用。 - [latte/latte](/awesome-plugins/latte) - Latte 是一个功能齐全的模板引擎,非常易用,其语法比 Twig 或 Smarty 更接近 PHP。它也非常易于扩展并添加您自己的过滤器和函数。 - [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate 是一个强大的 PHP 模板引擎,支持资产生成、模板继承和变量处理。具有自动 CSS/JS 压缩、缓存、Base64 编码,以及可选的 Flight PHP 框架集成。 ## WordPress 集成 -想在您的 WordPress 项目中使用 Flight 吗?有一个方便的插件可供使用! +想在您的 WordPress 项目中使用 Flight 吗?有一个方便的插件! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 此 WordPress 插件让您可以与 WordPress 并行运行 Flight。它非常适合使用 Flight 框架为您的 WordPress 站点添加自定义 API、微服务,甚至完整应用程序。如果您想兼得两者的优点,这超级有用! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 此 WordPress 插件允许您在 WordPress 旁边运行 Flight。它非常适合使用 Flight 框架为您的 WordPress 站点添加自定义 API、微服务,甚至完整应用程序。如果您想兼得两者的优点,这超级有用! ## 贡献 diff --git a/content/v3/zh/awesome-plugins/comment_template.md b/content/v3/zh/awesome-plugins/comment_template.md index 37b7dc4b..2678ce4f 100644 --- a/content/v3/zh/awesome-plugins/comment_template.md +++ b/content/v3/zh/awesome-plugins/comment_template.md @@ -1,13 +1,13 @@ # CommentTemplate -[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) 是一个强大的 PHP 模板引擎,具有资产生成、模板继承和变量处理功能。它提供了一种简单而灵活的管理模板的方式,内置 CSS/JS 压缩和缓存。 +[CommentTemplate](https://github.com/KnifeLemon/CommentTemplate) 是一个强大的 PHP 模板引擎,支持资产编译、模板继承和变量处理。它提供了一种简单而灵活的管理模板的方式,内置 CSS/JS 压缩和缓存功能。 -## 功能 +## 功能特性 - **模板继承**:使用布局并包含其他模板 -- **资产生成**:自动 CSS/JS 压缩和缓存 +- **资产编译**:自动 CSS/JS 压缩和缓存 - **变量处理**:带有过滤器和命令的模板变量 -- **Base64 编码**:将内联资产生成为数据 URI +- **Base64 编码**:将内联资产作为数据 URI - **Flight 框架集成**:与 Flight PHP 框架的可选集成 ## 安装 @@ -33,13 +33,13 @@ use KnifeLemon\CommentTemplate\Engine; $app = Flight::app(); $app->register('view', Engine::class, [], function (Engine $engine) use ($app) { - // 根目录(index.php 所在位置)- Web 应用程序的文档根目录 + // 根目录(index.php 所在位置) - Web 应用程序的文档根目录 $engine->setPublicPath(__DIR__); - // 模板文件目录 - 支持相对路径和绝对路径 + // 模板文件目录 - 支持相对和绝对路径 $engine->setSkinPath('views'); // 相对于公共路径 - // 编译资产的存储位置 - 支持相对路径和绝对路径 + // 编译资产存储位置 - 支持相对和绝对路径 $engine->setAssetPath('assets'); // 相对于公共路径 // 模板文件扩展名 @@ -64,8 +64,8 @@ $app = Flight::app(); // __construct(string $publicPath = "", string $skinPath = "", string $assetPath = "", string $fileExtension = "") $app->register('view', Engine::class, [ __DIR__, // publicPath - 根目录(index.php 所在位置) - 'views', // skinPath - 模板路径(支持相对/绝对路径) - 'assets', // assetPath - 编译资产路径(支持相对/绝对路径) + 'views', // skinPath - 模板路径(支持相对/绝对) + 'assets', // assetPath - 编译资产路径(支持相对/绝对) '.php' // fileExtension - 模板文件扩展名 ]); @@ -76,11 +76,11 @@ $app->map('render', function(string $template, array $data) use ($app): void { ## 路径配置 -CommentTemplate 为相对路径和绝对路径提供智能路径处理: +CommentTemplate 为相对和绝对路径提供智能路径处理: ### 公共路径 -**公共路径**是您的 Web 应用程序的根目录,通常是 `index.php` 所在的位置。这是 Web 服务器提供文件的文档根目录。 +**公共路径** 是 Web 应用程序的根目录,通常是 `index.php` 所在的位置。这是 Web 服务器提供文件的文档根目录。 ```php // 示例:如果您的 index.php 位于 /var/www/html/myapp/index.php @@ -92,7 +92,7 @@ $template->setPublicPath('C:\\xampp\\htdocs\\myapp'); ### 模板路径配置 -模板路径支持相对路径和绝对路径: +模板路径支持相对和绝对路径: ```php $template = new Engine(); @@ -102,7 +102,7 @@ $template->setPublicPath('/var/www/html/myapp'); // 根目录(index.php 所 $template->setSkinPath('views'); // → /var/www/html/myapp/views/ $template->setSkinPath('templates/pages'); // → /var/www/html/myapp/templates/pages/ -// 绝对路径 - 按原样使用(Unix/Linux) +// 绝对路径 - 原样使用(Unix/Linux) $template->setSkinPath('/var/www/templates'); // → /var/www/templates/ $template->setSkinPath('/full/path/to/templates'); // → /full/path/to/templates/ @@ -116,14 +116,14 @@ $template->setSkinPath('\\\\server\\share\\templates'); // → \\server\share\te ### 资产路径配置 -资产路径也支持相对路径和绝对路径: +资产路径也支持相对和绝对路径: ```php // 相对路径 - 自动与公共路径组合 $template->setAssetPath('assets'); // → /var/www/html/myapp/assets/ $template->setAssetPath('static/files'); // → /var/www/html/myapp/static/files/ -// 绝对路径 - 按原样使用(Unix/Linux) +// 绝对路径 - 原样使用(Unix/Linux) $template->setAssetPath('/var/www/cdn'); // → /var/www/cdn/ $template->setAssetPath('/full/path/to/assets'); // → /full/path/to/assets/ @@ -137,14 +137,14 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse **智能路径检测:** -- **相对路径**:没有前导分隔符(`/`、`\`)或驱动器字母 -- **Unix 绝对**:以 `/` 开头(例如:`/var/www/assets`) -- **Windows 绝对**:以驱动器字母开头(例如:`C:\www`、`D:/assets`) -- **UNC 路径**:以 `\\` 开头(例如:`\\server\share`) +- **相对路径**:无前导分隔符(`/`、`\')或驱动器字母 +- **Unix 绝对**:以 `/` 开头(例如,`/var/www/assets`) +- **Windows 绝对**:以驱动器字母开头(例如,`C:\www`、`D:/assets`) +- **UNC 路径**:以 `\\` 开头(例如,`\\server\share`) **工作原理:** -- 所有路径都根据类型自动解析(相对 vs 绝对) +- 所有路径根据类型(相对 vs 绝对)自动解析 - 相对路径与公共路径组合 - `@css` 和 `@js` 在以下位置创建压缩文件:`{resolvedAssetPath}/css/` 或 `{resolvedAssetPath}/js/` - `@asset` 将单个文件复制到:`{resolvedAssetPath}/{relativePath}` @@ -155,7 +155,7 @@ $template->setAssetPath('\\\\server\\share\\assets'); // → \\server\share\asse ### 布局继承 -使用布局来创建共同结构: +使用布局创建通用结构: **layout/global_layout.php**: ```html @@ -190,23 +190,24 @@ CommentTemplate 支持不同的 JavaScript 加载策略: ```html - - - - - + + + + + - - + + ``` #### CSS/JS 文件中的资产指令 -CommentTemplate 还在编译期间处理 CSS 和 JavaScript 文件中的资产指令: +CommentTemplate 在编译期间还会处理 CSS 和 JavaScript 文件中的资产指令: **CSS 示例:** ```css /* 在您的 CSS 文件中 */ +/* 在您的 CSS 文件中 */ @font-face { font-family: 'CustomFont'; src: url('') format('woff2'); @@ -230,11 +231,11 @@ const imageData = ''; #### Base64 编码 ```html - + ``` ** 示例: ** ```html - + Logo
          小图标作为背景 @@ -243,14 +244,14 @@ const imageData = ''; #### 资产复制 ```html - + ``` ** 示例: ** ```html Hero Banner -下载宣传册 +Download Brochure @@ -267,11 +268,11 @@ const imageData = '';
          -

          欢迎访问我们的网站

          +

          Welcome to our website

          -

          主要内容在这里...

          +

          Main content here...

          @@ -304,30 +305,30 @@ const imageData = ''; {$name|concat= (Admin)} ``` -#### 链式多个过滤器 +#### 变量命令 ```html {$content|striptag|trim|escape} ``` ### 注释 -模板注释会从输出中完全删除,不会出现在最终的 HTML 中: +模板注释会完全从输出中移除,不会出现在最终的 HTML 中: ```html -{* 这是单行模板注释 *} +{* 这是一个单行模板注释 *} {* - 这是跨越多行的 - 多行 - 模板注释 + 这是一个多行 + 模板注释 + 跨越多行 *}

          {$title}

          -{* 调试注释:检查 title 变量是否工作 *} +{* 调试注释:检查标题变量是否工作 *}

          {$content}

          ``` -**注意**:模板注释 `{* ... *}` 与 HTML 注释 `` 不同。模板注释在处理过程中被删除,不会到达浏览器。 +**注意**:模板注释 `{* ... *}` 与 HTML 注释 `` 不同。模板注释在处理期间被移除,从未到达浏览器。 ## 示例项目结构 diff --git a/content/v3/zh/awesome-plugins/runway.md b/content/v3/zh/awesome-plugins/runway.md index 7e08c695..72d1e375 100644 --- a/content/v3/zh/awesome-plugins/runway.md +++ b/content/v3/zh/awesome-plugins/runway.md @@ -1,12 +1,12 @@ -# 跑道 +# Runway -跑道是一个CLI应用程序,可帮助您管理您的Flight应用程序。它可以生成控制器,显示所有路由等。它基于优秀的 [adhocore/php-cli](https://github.com/adhocore/php-cli) 库。 +Runway 是一个 CLI 应用程序,帮助您管理 Flight 应用程序。它可以生成控制器、显示所有路由等。它基于优秀的 [adhocore/php-cli](https://github.com/adhocore/php-cli) 库。 -点击[这里](https://github.com/flightphp/runway) 查看代码。 +点击 [这里](https://github.com/flightphp/runway) 查看代码。 ## 安装 -使用 composer 安装。 +使用 Composer 安装。 ```bash composer require flightphp/runway @@ -14,16 +14,16 @@ composer require flightphp/runway ## 基本配置 -第一次运行跑道时,它将引导您完成设置过程并在项目根目录中创建一个 `.runway.json` 配置文件。此文件将包含一些Runway正常工作所需的配置。 +首次运行 Runway 时,它会引导您完成设置过程,并在项目根目录创建一个 `.runway.json` 配置文件。此文件将包含 Runway 正常工作的必要配置。 -## 用法 +## 使用 -跑道有许多命令可用于管理您的Flight应用程序。有两种简单的方法可以使用跑道。 +Runway 具有多个命令,可用于管理您的 Flight 应用程序。有两种简单的方式使用 Runway。 -1. 如果您使用的是骨架项目,可以从项目的根目录运行 `php runway [command]`。 -1. 如果您是通过composer安装的包来使用跑道,您可以从项目的根目录运行 `vendor/bin/runway [command]`。 +1. 如果您使用的是骨架项目,可以从项目根目录运行 `php runway [command]`。 +1. 如果您通过 Composer 安装 Runway 作为包,可以从项目根目录运行 `vendor/bin/runway [command]`。 -对于任何命令,您都可以传入 `--help` 标志以获取有关如何使用命令的更多信息。 +对于任何命令,您可以传入 `--help` 标志以获取有关如何使用该命令的更多信息。 ```bash php runway routes --help @@ -33,21 +33,21 @@ php runway routes --help ### 生成控制器 -根据您的 `.runway.json` 文件中的配置,默认位置将为您在 `app/controllers/` 目录中生成一个控制器。 +基于您的 `.runway.json` 文件中的配置,默认位置将在 `app/controllers/` 目录中为您生成控制器。 ```bash php runway make:controller MyController ``` -### 生成活动记录模型 +### 生成 Active Record 模型 -根据您的 `.runway.json` 文件中的配置,默认位置将为您在 `app/records/` 目录中生成一个控制器。 +基于您的 `.runway.json` 文件中的配置,默认位置将在 `app/records/` 目录中为您生成模型。 ```bash php runway make:record users ``` -例如,如果您有以下架构的 `users` 表:`id`,`name`,`email`,`created_at`,`updated_at`,则类似以下内容的文件将在 `app/records/UserRecord.php` 文件中创建: +例如,如果您有 `users` 表,具有以下架构:`id`、`name`、`email`、`created_at`、`updated_at`,则将在 `app/records/UserRecord.php` 文件中创建类似以下的文件: ```php $config 来自 .runway-config.json 的JSON配置 + * @param array $config JSON config from .runway-config.json */ public function __construct(array $config) { - parent::__construct('make:example', '为文档创建示例', $config); - $this->argument('', '滑稽gif的名称'); + parent::__construct('make:example', 'Create an example for the documentation', $config); + $this->argument('', 'The name of the funny gif'); } /** - * 执行函数 + * Executes the function * * @return void */ - public function execute(string $controller) + public function execute() { $io = $this->app()->io(); - $io->info('创建示例...'); + $io->info('Creating example...'); - // 在这里执行操作 + // Do something here - $io->ok('示例已创建!'); + $io->ok('Example created!'); } } ``` -有关如何将自定义命令构建到您的Flight应用程序中的更多信息,请参阅 [adhocore/php-cli 文档](https://github.com/adhocore/php-cli)。 \ No newline at end of file +有关如何将自定义命令构建到 Flight 应用程序中的更多信息,请参阅 [adhocore/php-cli 文档](https://github.com/adhocore/php-cli)! + +### 配置 + +如果需要自定义 Runway 的配置,可以在项目根目录创建一个 `.runway-config.json` 文件。以下是一些可以设置的附加配置: + +```js +{ + + // This is where your application directory is located + "app_root": "app/", + + // This is the directory where your root index file is located + "index_root": "public/", + + // These are the paths to the roots of other projects + "root_paths": [ + "/home/user/different-project", + "/var/www/another-project" + ], + + // Base paths most likely don't need to be configured, but it's here if you want it + "base_paths": { + "/includes/libs/vendor", // if you have a really unique path for your vendor directory or something + }, + + // Final paths are locations within a project to search for the command files + "final_paths": { + "src/diff-path/commands", + "app/module/admin/commands", + }, + + // If you want to just add the full path, go right ahead (absolute or relative to project root) + "paths": [ + "/home/user/different-project/src/diff-path/commands", + "/var/www/another-project/app/module/admin/commands", + "app/my-unique-commands" + ] +} +``` \ No newline at end of file diff --git a/content/v3/zh/examples.md b/content/v3/zh/examples.md index 01a02082..112f9a43 100644 --- a/content/v3/zh/examples.md +++ b/content/v3/zh/examples.md @@ -7,7 +7,7 @@ 社区贡献的示例: -- [flightravel](https://github.com/fadrian06-templates/flighravel):FlightPHP 与 Laravel 目录结合,带有 PHP 工具 + GH Actions +- [flightravel](https://github.com/fadrian06-templates/flighravel):FlightPHP 与 Laravel 目录结构,带有 PHP 工具 + GH Actions - [fleact](https://github.com/flightphp/fleact) - 一个带有 ReactJS 集成的 FlightPHP 启动套件。 - [flastro](https://github.com/flightphp/flastro) - 一个带有 Astro 集成的 FlightPHP 启动套件。 - [velt](https://github.com/flightphp/velt) - Velt 是一个快速易用的 Svelte 启动模板,带有 FlightPHP 后端。 @@ -16,11 +16,12 @@ 虽然这些并非由 Flight 团队正式赞助,但它们可以为您构建基于 Flight 的项目提供结构思路! -- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify 是一个单页应用,将活动组织者与参与者连接起来。使用 PHP (FlightPHP)、JavaScript 和 MySQL 构建,具有 JWT 认证、活动管理以及使用 OpenAPI 的 RESTful API 文档。 -- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental 是一个单页、移动友好的租车网络应用,使用 PHP (FlightPHP)、JavaScript 和 MySQL 构建。它支持用户注册、浏览和预订车辆,而管理员可以管理车辆、用户和预订。该应用具有 REST API、JWT 认证以及响应式设计,提供现代租车体验。 -- [Decay](https://github.com/boxybird/decay) - Flight v3 与 HTMX 和 SleekDB 结合,全是关于僵尸的!([Demo](https://decay.andrewrhyand.com)) -- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 带有中间件、控制器、Active Record 和 Latte。 -- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - 使用 Flight 框架的简单 CRUD API 项目,为新用户提供基本结构,以便快速设置带有 CRUD 操作和数据库连接的 PHP 应用。该项目演示了如何使用 Flight 进行 RESTful API 开发,是初学者理想的学习工具,也是经验丰富的开发者的有用启动套件。 +- [ASC REST API Spell Checker](https://github.com/AlMosahih-ASC/asc-api-sample) - 一个使用 FlightPHP 和 ArPHP 库构建的轻量级 REST API,用于阿拉伯语拼写检查。该 API 提供阿拉伯语文本拼写检查功能,包括拼写错误检测和更正建议。 +- [Eventify](https://github.com/ilhanklisura/eventify) - Eventify 是一个单页应用,将活动组织者与参与者连接起来。使用 PHP (FlightPHP)、JavaScript 和 MySQL 构建,功能包括 JWT 认证、活动管理和使用 OpenAPI 的 RESTful API 文档。 +- [Ivox Car Rental](https://github.com/najtms/introductionToWeb) - Ivox Car Rental 是一个单页、移动友好的汽车租赁 Web 应用,使用 PHP (FlightPHP)、JavaScript 和 MySQL 构建。它支持用户注册、浏览和预订汽车,而管理员可以管理汽车、用户和预订。该应用具有 REST API、JWT 认证和响应式设计,提供现代租赁体验。 +- [Decay](https://github.com/boxybird/decay) - Flight v3 与 HTMX 和 SleekDB,全是关于僵尸的!([Demo](https://decay.andrewrhyand.com)) +- [Flight Example Blog](https://github.com/n0nag0n/flightphp-blog) - Flight v3 与中间件、控制器、Active Record 和 Latte。 +- [Flight CRUD RESTful API](https://github.com/soheilkhaledabdi/php-crud-api-flight) - 一个使用 Flight 框架的简单 CRUD API 项目,为新用户提供基本结构,以快速设置带有 CRUD 操作和数据库连接的 PHP 应用。该项目演示了如何使用 Flight 进行 RESTful API 开发,是初学者理想的学习工具,也是有经验开发者的有用启动套件。 - [Flight School Management System](https://github.com/krmu/FlightPHP_School) - Flight v3 - [Paste Bin with Comments](https://github.com/n0nag0n/commie2) - Flight v3 - [Basic Skeleton App](https://github.com/markhughes/flight-skeleton) @@ -31,7 +32,7 @@ - [Generic Content Management System (with....very little documentation)](https://github.com/recepuncu/cms) - [A tiny php framework based on Flight and medoo.](https://github.com/ycrao/tinyme) - [Example MVC Application](https://github.com/paddypei/Flight-MVC) -- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 生产就绪的认证框架,可节省数周开发时间。具有企业级安全功能:2FA/TOTP、LDAP 集成、Azure SSO、智能速率限制、会话指纹识别、暴力破解保护、安全分析仪表板、全面审计日志以及细粒度基于角色的访问控制。 +- [Production ready Flight Boilerplate](https://github.com/madcoda9000/SecStore) - 一个生产就绪的认证框架,可节省数周开发时间。功能包括企业级安全:2FA/TOTP、LDAP 集成、Azure SSO、智能速率限制、会话指纹识别、暴力破解保护、安全分析仪表板、全面审计日志和细粒度基于角色的访问控制。 ## 想分享您自己的示例吗? From b12ed063c740ea67abf4963e681dd8e7cb284af1 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Thu, 1 Jan 2026 08:22:47 -0700 Subject: [PATCH 27/36] updated runway docs --- content/v3/de/awesome-plugins/runway.md | 197 +++++++++++++++------ content/v3/en/awesome-plugins/runway.md | 169 +++++++++++++----- content/v3/es/awesome-plugins/runway.md | 171 ++++++++++++++----- content/v3/fr/awesome-plugins/runway.md | 179 ++++++++++++++----- content/v3/id/awesome-plugins/runway.md | 207 +++++++++++++++------- content/v3/ja/awesome-plugins/runway.md | 197 +++++++++++++++------ content/v3/ko/awesome-plugins/runway.md | 217 +++++++++++++++++------- content/v3/lv/awesome-plugins/runway.md | 191 +++++++++++++++------ content/v3/pt/awesome-plugins/runway.md | 181 +++++++++++++++----- content/v3/ru/awesome-plugins/runway.md | 199 ++++++++++++++++------ content/v3/uk/awesome-plugins/runway.md | 191 +++++++++++++++------ content/v3/zh/awesome-plugins/runway.md | 189 +++++++++++++++------ 12 files changed, 1702 insertions(+), 586 deletions(-) diff --git a/content/v3/de/awesome-plugins/runway.md b/content/v3/de/awesome-plugins/runway.md index e3dca270..283bcf58 100644 --- a/content/v3/de/awesome-plugins/runway.md +++ b/content/v3/de/awesome-plugins/runway.md @@ -1,6 +1,6 @@ # Runway -Runway ist eine CLI-Anwendung, die Ihnen hilft, Ihre Flight-Anwendungen zu verwalten. Sie kann Controller generieren, alle Routen anzeigen und mehr. Sie basiert auf der hervorragenden [adhocore/php-cli](https://github.com/adhocore/php-cli)-Bibliothek. +Runway ist eine CLI-Anwendung, die Ihnen bei der Verwaltung Ihrer Flight-Anwendungen hilft. Sie kann Controller generieren, alle Routen anzeigen und mehr. Sie basiert auf der hervorragenden [adhocore/php-cli](https://github.com/adhocore/php-cli)-Bibliothek. Klicken Sie [hier](https://github.com/flightphp/runway), um den Code anzusehen. @@ -12,18 +12,45 @@ Installieren Sie mit Composer. composer require flightphp/runway ``` -## Grundlegende Konfiguration +## Basis-Konfiguration -Beim ersten Ausführen von Runway durchläuft es einen Einrichtungsprozess und erstellt eine `.runway.json`-Konfigurationsdatei im Stammverzeichnis Ihres Projekts. Diese Datei enthält einige notwendige Konfigurationen, damit Runway ordnungsgemäß funktioniert. +Beim ersten Ausführen von Runway versucht es, eine `runway`-Konfiguration in `app/config/config.php` über den Schlüssel `'runway'` zu finden. + +```php + [ + 'app_root' => 'app/', + 'public_root' => 'public/', + ], +]; +``` + +> **HINWEIS** - Ab **v1.2.0** ist `.runway-config.json` veraltet. Bitte migrieren Sie Ihre Konfiguration zu `app/config/config.php`. Sie können dies einfach mit dem Befehl `php runway config:migrate` tun. + +### Projekt-Root-Erkennung + +Runway ist intelligent genug, um das Root-Verzeichnis Ihres Projekts zu erkennen, auch wenn Sie es aus einem Unterverzeichnis ausführen. Es sucht nach Indikatoren wie `composer.json`, `.git` oder `app/config/config.php`, um zu bestimmen, wo sich das Projekt-Root befindet. Das bedeutet, dass Sie Runway-Befehle von überall in Ihrem Projekt ausführen können! ## Verwendung -Runway verfügt über eine Reihe von Befehlen, die Sie verwenden können, um Ihre Flight-Anwendung zu verwalten. Es gibt zwei einfache Wege, Runway zu verwenden. +Runway verfügt über eine Reihe von Befehlen, die Sie zur Verwaltung Ihrer Flight-Anwendung verwenden können. Es gibt zwei einfache Wege, Runway zu nutzen. + +1. Wenn Sie das Skeleton-Projekt verwenden, können Sie `php runway [command]` vom Root Ihres Projekts ausführen. +1. Wenn Sie Runway als Paket über Composer installiert haben, können Sie `vendor/bin/runway [command]` vom Root Ihres Projekts ausführen. + +### Befehlsliste + +Sie können eine Liste aller verfügbaren Befehle anzeigen, indem Sie den `php runway`-Befehl ausführen. + +```bash +php runway +``` -1. Wenn Sie das Skeleton-Projekt verwenden, können Sie `php runway [command]` vom Stammverzeichnis Ihres Projekts ausführen. -1. Wenn Sie Runway als über Composer installiertes Paket verwenden, können Sie `vendor/bin/runway [command]` vom Stammverzeichnis Ihres Projekts ausführen. +### Befehlshilfe -Für jeden Befehl können Sie die `--help`-Flagge übergeben, um weitere Informationen zur Verwendung des Befehls zu erhalten. +Für jeden Befehl können Sie die `--help`-Flagge übergeben, um mehr Informationen darüber zu erhalten, wie man den Befehl verwendet. ```bash php runway routes --help @@ -33,7 +60,7 @@ Hier sind einige Beispiele: ### Einen Controller generieren -Basierend auf der Konfiguration in Ihrer `.runway.json`-Datei wird der Standardort einen Controller für Sie im `app/controllers/`-Verzeichnis generieren. +Basierend auf der Konfiguration in `runway.app_root` wird der Speicherort einen Controller für Sie im `app/controllers/`-Verzeichnis generieren. ```bash php runway make:controller MyController @@ -41,13 +68,13 @@ php runway make:controller MyController ### Ein Active Record-Modell generieren -Basierend auf der Konfiguration in Ihrer `.runway.json`-Datei wird der Standardort einen Controller für Sie im `app/records/`-Verzeichnis generieren. +Stellen Sie zuerst sicher, dass Sie das [Active Record](/awesome-plugins/active-record)-Plugin installiert haben. Basierend auf der Konfiguration in `runway.app_root` wird der Speicherort einen Record für Sie im `app/records/`-Verzeichnis generieren. ```bash php runway make:record users ``` -Falls Sie beispielsweise die `users`-Tabelle mit dem folgenden Schema haben: `id`, `name`, `email`, `created_at`, `updated_at`, wird eine Datei ähnlich der folgenden in der Datei `app/records/UserRecord.php` erstellt: +Wenn Sie beispielsweise die `users`-Tabelle mit dem folgenden Schema haben: `id`, `name`, `email`, `created_at`, `updated_at`, wird eine Datei ähnlich der folgenden in der Datei `app/records/UserRecord.php` erstellt: ```php $config JSON-Konfiguration aus .runway-config.json + * @param array $config Konfiguration aus app/config/config.php */ public function __construct(array $config) { - parent::__construct('make:example', 'Erstellt ein Beispiel für die Dokumentation', $config); + parent::__construct('make:example', 'Erstelle ein Beispiel für die Dokumentation', $config); $this->argument('', 'Der Name des lustigen GIFs'); } @@ -144,50 +171,116 @@ class ExampleCommand extends AbstractBaseCommand $io->info('Erstelle Beispiel...'); - // Etwas hier tun + // Hier etwas tun $io->ok('Beispiel erstellt!'); } } ``` -Siehe die [adhocore/php-cli-Dokumentation](https://github.com/adhocore/php-cli) für weitere Informationen darüber, wie Sie eigene benutzerdefinierte Befehle in Ihre Flight-Anwendung einbauen! +Lesen Sie die [adhocore/php-cli-Dokumentation](https://github.com/adhocore/php-cli), um mehr darüber zu erfahren, wie Sie eigene benutzerdefinierte Befehle in Ihre Flight-Anwendung einbauen! + +## Konfigurationsverwaltung -### Konfiguration +Da die Konfiguration ab `v1.2.0` zu `app/config/config.php` verschoben wurde, gibt es einige Hilfsbefehle zur Verwaltung der Konfiguration. -Wenn Sie die Konfiguration für Runway anpassen müssen, können Sie eine `.runway-config.json`-Datei im Stammverzeichnis Ihres Projekts erstellen. Nachfolgend sind einige zusätzliche Konfigurationen aufgeführt, die Sie setzen können: +### Alte Konfiguration migrieren -```js +Wenn Sie eine alte `.runway-config.json`-Datei haben, können Sie sie einfach mit dem folgenden Befehl zu `app/config/config.php` migrieren: + +```bash +php runway config:migrate +``` + +### Konfigurationswert setzen + +Sie können einen Konfigurationswert mit dem `config:set`-Befehl setzen. Dies ist nützlich, wenn Sie einen Konfigurationswert aktualisieren möchten, ohne die Datei zu öffnen. + +```bash +php runway config:set app_root "app/" +``` + +### Konfigurationswert abrufen + +Sie können einen Konfigurationswert mit dem `config:get`-Befehl abrufen. + +```bash +php runway config:get app_root +``` + +## Alle Runway-Konfigurationen + +Wenn Sie die Konfiguration für Runway anpassen müssen, können Sie diese Werte in `app/config/config.php` setzen. Nachfolgend sind einige zusätzliche Konfigurationen, die Sie setzen können: + +```php + [ + // Hier befindet sich Ihr Anwendungsverzeichnis + 'app_root' => 'app/', + + // Dies ist das Verzeichnis, in dem sich Ihre Root-Index-Datei befindet + 'index_root' => 'public/', + + // Dies sind die Pfade zu den Roots anderer Projekte + 'root_paths' => [ + '/home/user/different-project', + '/var/www/another-project' + ], + + // Basis-Pfade müssen wahrscheinlich nicht konfiguriert werden, aber es ist hier, falls Sie es möchten + 'base_paths' => [ + '/includes/libs/vendor', // wenn Sie einen wirklich einzigartigen Pfad für Ihr Vendor-Verzeichnis haben oder so + ], + + // Finale Pfade sind Orte innerhalb eines Projekts, um nach Befehlsdateien zu suchen + 'final_paths' => [ + 'src/diff-path/commands', + 'app/module/admin/commands', + ], + + // Wenn Sie einfach den vollständigen Pfad hinzufügen möchten, tun Sie es ruhig (absolut oder relativ zum Projekt-Root) + 'paths' => [ + '/home/user/different-project/src/diff-path/commands', + '/var/www/another-project/app/module/admin/commands', + 'app/my-unique-commands' + ] + ] +]; +``` + +### Zugriff auf Konfiguration + +Wenn Sie die Konfigurationswerte effektiv abrufen müssen, können Sie sie über die `__construct`-Methode oder die `app()`-Methode abrufen. Es ist auch wichtig zu beachten, dass, wenn Sie eine `app/config/services.php`-Datei haben, diese Dienste ebenfalls für Ihren Befehl verfügbar sind. + +```php +public function execute() { + $io = $this->app()->io(); + + // Zugriff auf Konfiguration + $app_root = $this->config['runway']['app_root']; + + // Zugriff auf Dienste wie vielleicht eine Datenbankverbindung + $database = $this->config['database'] + + // ... +} +``` + +## AI-Hilfs-Wrapper + +Runway hat einige Hilfs-Wrapper, die es einfacher machen, für KI Befehle zu generieren. Sie können `addOption` und `addArgument` auf eine Weise verwenden, die ähnlich wie Symfony Console wirkt. Dies ist hilfreich, wenn Sie KI-Tools verwenden, um Ihre Befehle zu generieren. - // Hier befindet sich das Verzeichnis Ihrer Anwendung - "app_root": "app/", - - // Dies ist das Verzeichnis, in dem sich Ihre root index-Datei befindet - "index_root": "public/", - - // Dies sind die Pfade zu den Roots anderer Projekte - "root_paths": [ - "/home/user/different-project", - "/var/www/another-project" - ], - - // Base-Pfade müssen wahrscheinlich nicht konfiguriert werden, aber es ist hier, falls Sie es wollen - "base_paths": { - "/includes/libs/vendor", // falls Sie einen wirklich einzigartigen Pfad für Ihr Vendor-Verzeichnis oder Ähnliches haben - }, - - // Final-Pfade sind Orte innerhalb eines Projekts, um nach den Befehlsdateien zu suchen - "final_paths": { - "src/diff-path/commands", - "app/module/admin/commands", - }, - - // Wenn Sie einfach den vollständigen Pfad hinzufügen möchten, tun Sie es ruhig (absolut oder relativ zum Projekt-Root) - "paths": [ - "/home/user/different-project/src/diff-path/commands", - "/var/www/another-project/app/module/admin/commands", - "app/my-unique-commands" - ] +```php +public function __construct(array $config) +{ + parent::__construct('make:example', 'Erstelle ein Beispiel für die Dokumentation', $config); + + // Der Name-Argument ist nullable und standardmäßig vollständig optional + $this->addOption('name', 'Der Name des Beispiels', null); } ``` \ No newline at end of file diff --git a/content/v3/en/awesome-plugins/runway.md b/content/v3/en/awesome-plugins/runway.md index 9f643dda..f796cd5d 100644 --- a/content/v3/en/awesome-plugins/runway.md +++ b/content/v3/en/awesome-plugins/runway.md @@ -14,7 +14,24 @@ composer require flightphp/runway ## Basic Configuration -The first time you run Runway, it will run you through a setup process and create a `.runway.json` configuration file in the root of your project. This file will contain some necessary configurations for Runway to work properly. +The first time you run Runway, it will try and find a `runway` configuration in `app/config/config.php` via the `'runway'` key. + +```php + [ + 'app_root' => 'app/', + 'public_root' => 'public/', + ], +]; +``` + +> **NOTE** - As of **v1.2.0**, `.runway-config.json` is deprecated. Please migrate your configuration to `app/config/config.php`. You can do this easily with the `php runway config:migrate` command. + +### Project Root Detection + +Runway is smart enough to detect the root of your project, even if you run it from a subdirectory. It looks for indicators like `composer.json`, `.git`, or `app/config/config.php` to determine where the project root is. This means you can run Runway commands from anywhere in your project! ## Usage @@ -23,6 +40,16 @@ Runway has a number of commands that you can use to manage your Flight applicati 1. If you are using the skeleton project, you can run `php runway [command]` from the root of your project. 1. If you are using Runway as a package installed via composer, you can run `vendor/bin/runway [command]` from the root of your project. +### Command List + +You can view a list of all available commands by running the `php runway` command. + +```bash +php runway +``` + +### Command Help + For any command, you can pass in the `--help` flag to get more information on how to use the command. ```bash @@ -33,7 +60,7 @@ Here are a few examples: ### Generate a Controller -Based on the configuration in your `.runway.json` file, the default location will generate a controller for you in the `app/controllers/` directory. +Based on the configuration in `runway.app_root`, the location will generate a controller for you in the `app/controllers/` directory. ```bash php runway make:controller MyController @@ -41,7 +68,7 @@ php runway make:controller MyController ### Generate an Active Record Model -Based on the configuration in your `.runway.json` file, the default location will generate a controller for you in the `app/records/` directory. +First make sure you've installed the [Active Record](/awesome-plugins/active-record) plugin. Based on the configuration in `runway.app_root`, the location will generate a record for you in the `app/records/` directory. ```bash php runway make:record users @@ -107,7 +134,7 @@ php runway routes --post # etc. ``` -## Customizing Runway +## Adding Custom Commands to Runway If you are either creating a package for Flight, or want to add your own custom commands into your project, you can do so by creating a `src/commands/`, `flight/commands/`, `app/commands/`, or `commands/` directory for your project/package. If you need further customization, see the section below on Configuration. @@ -125,7 +152,7 @@ class ExampleCommand extends AbstractBaseCommand /** * Construct * - * @param array $config JSON config from .runway-config.json + * @param array $config Config from app/config/config.php */ public function __construct(array $config) { @@ -153,41 +180,107 @@ class ExampleCommand extends AbstractBaseCommand See the [adhocore/php-cli Documentation](https://github.com/adhocore/php-cli) for more information on how to build your own custom commands into your Flight application! -### Configuration +## Configuration Management -If you need to customize the configuration for Runway, you can create a `.runway-config.json` file in the root of your project. Below are some additional configurations that you can set: +Since configuration has moved to `app/config/config.php` as of `v1.2.0`, there are a few helper commands to manage configuration. -```js -{ +### Migrate Old Config + +If you have an old `.runway-config.json` file, you can easily migrate it to `app/config/config.php` with the following command: + +```bash +php runway config:migrate +``` + +### Set Configuration Value + +You can set a configuration value using the `config:set` command. This is useful if you want to update a configuration value without opening the file. + +```bash +php runway config:set app_root "app/" +``` + +### Get Configuration Value + +You can get a configuration value using the `config:get` command. + +```bash +php runway config:get app_root +``` + +## All Runway Configurations + +If you need to customize the configuration for Runway, you can set these values in `app/config/config.php`. Below are some additional configurations that you can set: + +```php + [ + // This is where your application directory is located + 'app_root' => 'app/', + + // This is the directory where your root index file is located + 'index_root' => 'public/', + + // These are the paths to the roots of other projects + 'root_paths' => [ + '/home/user/different-project', + '/var/www/another-project' + ], + + // Base paths most likely don't need to be configured, but it's here if you want it + 'base_paths' => [ + '/includes/libs/vendor', // if you have a really unique path for your vendor directory or something + ], + + // Final paths are locations within a project to search for the command files + 'final_paths' => [ + 'src/diff-path/commands', + 'app/module/admin/commands', + ], + + // If you want to just add the full path, go right ahead (absolute or relative to project root) + 'paths' => [ + '/home/user/different-project/src/diff-path/commands', + '/var/www/another-project/app/module/admin/commands', + 'app/my-unique-commands' + ] + ] +]; +``` + +### Accessing Configuration + +If you need to access the configuration values effectively, you can access them through the `__construct` method or the `app()` method. It is also important to note that if you have a `app/config/services.php` file, those services will also be available to your command. - // This is where your application directory is located - "app_root": "app/", - - // This is the directory where your root index file is located - "index_root": "public/", - - // These are the paths to the roots of other projects - "root_paths": [ - "/home/user/different-project", - "/var/www/another-project" - ], - - // Base paths most likely don't need to be configured, but it's here if you want it - "base_paths": { - "/includes/libs/vendor", // if you have a really unique path for your vendor directory or something - }, - - // Final paths are locations within a project to search for the command files - "final_paths": { - "src/diff-path/commands", - "app/module/admin/commands", - }, - - // If you want to just add the full path, go right ahead (absolute or relative to project root) - "paths": [ - "/home/user/different-project/src/diff-path/commands", - "/var/www/another-project/app/module/admin/commands", - "app/my-unique-commands" - ] +```php +public function execute() +{ + $io = $this->app()->io(); + + // Access configuration + $app_root = $this->config['runway']['app_root']; + + // Access services like maybe a database connection + $database = $this->config['database'] + + // ... } ``` + +## AI Helper Wrappers + +Runway has some helper wrappers that make it easier for AI to generate commands. You can use `addOption` and `addArgument` in a way that feels similar to Symfony Console. This is helpful if you are using AI tools to generate your commands. + +```php +public function __construct(array $config) +{ + parent::__construct('make:example', 'Create an example for the documentation', $config); + + // The mode argument is nullable and defaults to completely optional + $this->addOption('name', 'The name of the example', null); +} +``` \ No newline at end of file diff --git a/content/v3/es/awesome-plugins/runway.md b/content/v3/es/awesome-plugins/runway.md index 311c0f7b..966cc419 100644 --- a/content/v3/es/awesome-plugins/runway.md +++ b/content/v3/es/awesome-plugins/runway.md @@ -14,7 +14,24 @@ composer require flightphp/runway ## Configuración Básica -La primera vez que ejecutes Runway, te guiará a través de un proceso de configuración y creará un archivo de configuración `.runway.json` en la raíz de tu proyecto. Este archivo contendrá algunas configuraciones necesarias para que Runway funcione correctamente. +La primera vez que ejecutes Runway, intentará encontrar una configuración `runway` en `app/config/config.php` a través de la clave `'runway'`. + +```php + [ + 'app_root' => 'app/', + 'public_root' => 'public/', + ], +]; +``` + +> **NOTA** - A partir de **v1.2.0**, `.runway-config.json` está obsoleto. Por favor, migra tu configuración a `app/config/config.php`. Puedes hacerlo fácilmente con el comando `php runway config:migrate`. + +### Detección de la Raíz del Proyecto + +Runway es lo suficientemente inteligente como para detectar la raíz de tu proyecto, incluso si lo ejecutas desde un subdirectorio. Busca indicadores como `composer.json`, `.git` o `app/config/config.php` para determinar dónde está la raíz del proyecto. Esto significa que puedes ejecutar comandos de Runway desde cualquier lugar en tu proyecto! ## Uso @@ -23,6 +40,16 @@ Runway tiene una serie de comandos que puedes usar para gestionar tu aplicación 1. Si estás usando el proyecto esqueleto, puedes ejecutar `php runway [command]` desde la raíz de tu proyecto. 1. Si estás usando Runway como un paquete instalado vía composer, puedes ejecutar `vendor/bin/runway [command]` desde la raíz de tu proyecto. +### Lista de Comandos + +Puedes ver una lista de todos los comandos disponibles ejecutando el comando `php runway`. + +```bash +php runway +``` + +### Ayuda de Comandos + Para cualquier comando, puedes pasar la bandera `--help` para obtener más información sobre cómo usar el comando. ```bash @@ -33,7 +60,7 @@ Aquí hay algunos ejemplos: ### Generar un Controlador -Basado en la configuración en tu archivo `.runway.json`, la ubicación predeterminada generará un controlador para ti en el directorio `app/controllers/`. +Basado en la configuración en `runway.app_root`, la ubicación generará un controlador para ti en el directorio `app/controllers/`. ```bash php runway make:controller MyController @@ -41,7 +68,7 @@ php runway make:controller MyController ### Generar un Modelo Active Record -Basado en la configuración en tu archivo `.runway.json`, la ubicación predeterminada generará un controlador para ti en el directorio `app/records/`. +Primero asegúrate de haber instalado el plugin [Active Record](/awesome-plugins/active-record). Basado en la configuración en `runway.app_root`, la ubicación generará un registro para ti en el directorio `app/records/`. ```bash php runway make:record users @@ -107,9 +134,9 @@ php runway routes --post # etc. ``` -## Personalizando Runway +## Agregar Comandos Personalizados a Runway -Si estás creando un paquete para Flight, o quieres agregar tus propios comandos personalizados a tu proyecto, puedes hacerlo creando un directorio `src/commands/`, `flight/commands/`, `app/commands/`, o `commands/` para tu proyecto/paquete. Si necesitas una personalización adicional, consulta la sección a continuación sobre Configuración. +Si estás creando un paquete para Flight o quieres agregar tus propios comandos personalizados a tu proyecto, puedes hacerlo creando un directorio `src/commands/`, `flight/commands/`, `app/commands/` o `commands/` para tu proyecto/paquete. Si necesitas una personalización adicional, consulta la sección a continuación sobre Configuración. Para crear un comando, simplemente extiende la clase `AbstractBaseCommand` e implementa, como mínimo, un método `__construct` y un método `execute`. @@ -125,12 +152,12 @@ class ExampleCommand extends AbstractBaseCommand /** * Constructor * - * @param array $config Configuración JSON de .runway-config.json + * @param array $config Configuración de app/config/config.php */ public function __construct(array $config) { parent::__construct('make:example', 'Crear un ejemplo para la documentación', $config); - $this->argument('', 'El nombre del gif divertido'); + $this->argument('', 'El nombre del gif gracioso'); } /** @@ -153,41 +180,107 @@ class ExampleCommand extends AbstractBaseCommand Consulta la [Documentación de adhocore/php-cli](https://github.com/adhocore/php-cli) para obtener más información sobre cómo construir tus propios comandos personalizados en tu aplicación Flight! -### Configuración +## Gestión de Configuración + +Dado que la configuración se ha movido a `app/config/config.php` a partir de `v1.2.0`, hay algunos comandos de ayuda para gestionar la configuración. -Si necesitas personalizar la configuración para Runway, puedes crear un archivo `.runway-config.json` en la raíz de tu proyecto. A continuación se muestran algunas configuraciones adicionales que puedes establecer: +### Migrar Configuración Antigua -```js +Si tienes un archivo antiguo `.runway-config.json`, puedes migrarlo fácilmente a `app/config/config.php` con el siguiente comando: + +```bash +php runway config:migrate +``` + +### Establecer Valor de Configuración + +Puedes establecer un valor de configuración usando el comando `config:set`. Esto es útil si quieres actualizar un valor de configuración sin abrir el archivo. + +```bash +php runway config:set app_root "app/" +``` + +### Obtener Valor de Configuración + +Puedes obtener un valor de configuración usando el comando `config:get`. + +```bash +php runway config:get app_root +``` + +## Todas las Configuraciones de Runway + +Si necesitas personalizar la configuración para Runway, puedes establecer estos valores en `app/config/config.php`. A continuación se muestran algunas configuraciones adicionales que puedes establecer: + +```php + [ + // Aquí es donde se encuentra el directorio de tu aplicación + 'app_root' => 'app/', + + // Este es el directorio donde se encuentra tu archivo índice raíz + 'index_root' => 'public/', + + // Estos son los caminos a las raíces de otros proyectos + 'root_paths' => [ + '/home/user/different-project', + '/var/www/another-project' + ], + + // Los caminos base probablemente no necesiten configurarse, pero está aquí si lo quieres + 'base_paths' => [ + '/includes/libs/vendor', // si tienes un camino realmente único para tu directorio vendor o algo + ], + + // Los caminos finales son ubicaciones dentro de un proyecto para buscar los archivos de comandos + 'final_paths' => [ + 'src/diff-path/commands', + 'app/module/admin/commands', + ], + + // Si quieres agregar el camino completo, adelante (absoluto o relativo a la raíz del proyecto) + 'paths' => [ + '/home/user/different-project/src/diff-path/commands', + '/var/www/another-project/app/module/admin/commands', + 'app/my-unique-commands' + ] + ] +]; +``` + +### Acceso a la Configuración + +Si necesitas acceder a los valores de configuración de manera efectiva, puedes acceder a ellos a través del método `__construct` o el método `app()`. También es importante notar que si tienes un archivo `app/config/services.php`, esos servicios también estarán disponibles para tu comando. + +```php +public function execute() { + $io = $this->app()->io(); + + // Acceder a la configuración + $app_root = $this->config['runway']['app_root']; + + // Acceder a servicios como quizás una conexión a la base de datos + $database = $this->config['database'] + + // ... +} +``` + +## Envoltorios de Ayudante de IA + +Runway tiene algunos envoltorios de ayudante que facilitan que la IA genere comandos. Puedes usar `addOption` y `addArgument` de una manera que se sienta similar a Symfony Console. Esto es útil si estás usando herramientas de IA para generar tus comandos. - // Aquí es donde se encuentra el directorio de tu aplicación - "app_root": "app/", - - // Este es el directorio donde se encuentra tu archivo index raíz - "index_root": "public/", - - // Estas son las rutas a las raíces de otros proyectos - "root_paths": [ - "/home/user/different-project", - "/var/www/another-project" - ], - - // Las rutas base probablemente no necesiten configurarse, pero está aquí si lo quieres - "base_paths": { - "/includes/libs/vendor", // si tienes una ruta realmente única para tu directorio vendor o algo - }, - - // Las rutas finales son ubicaciones dentro de un proyecto para buscar los archivos de comandos - "final_paths": { - "src/diff-path/commands", - "app/module/admin/commands", - }, - - // Si quieres agregar la ruta completa, adelante (absoluta o relativa a la raíz del proyecto) - "paths": [ - "/home/user/different-project/src/diff-path/commands", - "/var/www/another-project/app/module/admin/commands", - "app/my-unique-commands" - ] +```php +public function __construct(array $config) +{ + parent::__construct('make:example', 'Crear un ejemplo para la documentación', $config); + + // El argumento mode es nullable y por defecto completamente opcional + $this->addOption('name', 'El nombre del ejemplo', null); } ``` \ No newline at end of file diff --git a/content/v3/fr/awesome-plugins/runway.md b/content/v3/fr/awesome-plugins/runway.md index c6df2ca2..51a1218a 100644 --- a/content/v3/fr/awesome-plugins/runway.md +++ b/content/v3/fr/awesome-plugins/runway.md @@ -14,16 +14,43 @@ composer require flightphp/runway ## Configuration de Base -La première fois que vous exécutez Runway, il vous guidera à travers un processus de configuration et créera un fichier de configuration `.runway.json` à la racine de votre projet. Ce fichier contiendra certaines configurations nécessaires pour que Runway fonctionne correctement. +La première fois que vous exécutez Runway, il essaiera de trouver une configuration `runway` dans `app/config/config.php` via la clé `'runway'`. + +```php + [ + 'app_root' => 'app/', + 'public_root' => 'public/', + ], +]; +``` + +> **NOTE** - À partir de **v1.2.0**, `.runway-config.json` est déprécié. Veuillez migrer votre configuration vers `app/config/config.php`. Vous pouvez le faire facilement avec la commande `php runway config:migrate`. + +### Détection de la Racine du Projet + +Runway est suffisamment intelligent pour détecter la racine de votre projet, même si vous l'exécutez depuis un sous-répertoire. Il recherche des indicateurs comme `composer.json`, `.git`, ou `app/config/config.php` pour déterminer où se trouve la racine du projet. Cela signifie que vous pouvez exécuter les commandes Runway depuis n'importe où dans votre projet ! ## Utilisation Runway dispose d'un certain nombre de commandes que vous pouvez utiliser pour gérer votre application Flight. Il existe deux façons faciles d'utiliser Runway. -1. Si vous utilisez le projet squelette, vous pouvez exécuter `php runway [commande]` depuis la racine de votre projet. -1. Si vous utilisez Runway en tant que package installé via composer, vous pouvez exécuter `vendor/bin/runway [commande]` depuis la racine de votre projet. +1. Si vous utilisez le projet squelette, vous pouvez exécuter `php runway [command]` depuis la racine de votre projet. +1. Si vous utilisez Runway comme un package installé via composer, vous pouvez exécuter `vendor/bin/runway [command]` depuis la racine de votre projet. + +### Liste des Commandes + +Vous pouvez voir une liste de toutes les commandes disponibles en exécutant la commande `php runway`. + +```bash +php runway +``` + +### Aide sur les Commandes -Pour toute commande, vous pouvez passer l'option `--help` pour obtenir plus d'informations sur la façon d'utiliser la commande. +Pour n'importe quelle commande, vous pouvez passer l'option `--help` pour obtenir plus d'informations sur la façon d'utiliser la commande. ```bash php runway routes --help @@ -33,7 +60,7 @@ Voici quelques exemples : ### Générer un Contrôleur -En se basant sur la configuration dans votre fichier `.runway.json`, l'emplacement par défaut générera un contrôleur pour vous dans le répertoire `app/controllers/`. +Basé sur la configuration dans `runway.app_root`, l'emplacement générera un contrôleur pour vous dans le répertoire `app/controllers/`. ```bash php runway make:controller MyController @@ -41,13 +68,13 @@ php runway make:controller MyController ### Générer un Modèle Active Record -En se basant sur la configuration dans votre fichier `.runway.json`, l'emplacement par défaut générera un modèle pour vous dans le répertoire `app/records/`. +Assurez-vous d'abord d'avoir installé le plugin [Active Record](/awesome-plugins/active-record). Basé sur la configuration dans `runway.app_root`, l'emplacement générera un enregistrement pour vous dans le répertoire `app/records/`. ```bash php runway make:record users ``` -Si, par exemple, vous avez la table `users` avec le schéma suivant : `id`, `name`, `email`, `created_at`, `updated_at`, un fichier similaire à celui-ci sera créé dans le fichier `app/records/UserRecord.php` : +Par exemple, si vous avez la table `users` avec le schéma suivant : `id`, `name`, `email`, `created_at`, `updated_at`, un fichier similaire à celui-ci sera créé dans le fichier `app/records/UserRecord.php` : ```php $config Configuration JSON de .runway-config.json + * @param array $config Configuration de app/config/config.php */ public function __construct(array $config) { @@ -153,41 +180,107 @@ class ExampleCommand extends AbstractBaseCommand Consultez la [Documentation adhocore/php-cli](https://github.com/adhocore/php-cli) pour plus d'informations sur la façon de construire vos propres commandes personnalisées dans votre application Flight ! -### Configuration +## Gestion de la Configuration + +Puisque la configuration a été déplacée vers `app/config/config.php` à partir de `v1.2.0`, il existe quelques commandes d'aide pour gérer la configuration. -Si vous devez personnaliser la configuration pour Runway, vous pouvez créer un fichier `.runway-config.json` à la racine de votre projet. Voici quelques configurations supplémentaires que vous pouvez définir : +### Migrer l'Ancienne Configuration -```js +Si vous avez un ancien fichier `.runway-config.json`, vous pouvez facilement le migrer vers `app/config/config.php` avec la commande suivante : + +```bash +php runway config:migrate +``` + +### Définir une Valeur de Configuration + +Vous pouvez définir une valeur de configuration en utilisant la commande `config:set`. Cela est utile si vous souhaitez mettre à jour une valeur de configuration sans ouvrir le fichier. + +```bash +php runway config:set app_root "app/" +``` + +### Obtenir une Valeur de Configuration + +Vous pouvez obtenir une valeur de configuration en utilisant la commande `config:get`. + +```bash +php runway config:get app_root +``` + +## Toutes les Configurations Runway + +Si vous devez personnaliser la configuration pour Runway, vous pouvez définir ces valeurs dans `app/config/config.php`. Voici quelques configurations supplémentaires que vous pouvez définir : + +```php + [ + // C'est là que se trouve votre répertoire d'application + 'app_root' => 'app/', + + // C'est le répertoire où se trouve votre fichier index racine + 'index_root' => 'public/', + + // Ce sont les chemins vers les racines d'autres projets + 'root_paths' => [ + '/home/user/different-project', + '/var/www/another-project' + ], + + // Les chemins de base n'ont probablement pas besoin d'être configurés, mais ils sont là si vous en voulez + 'base_paths' => [ + '/includes/libs/vendor', // si vous avez un chemin vraiment unique pour votre répertoire vendor ou autre + ], + + // Les chemins finaux sont des emplacements dans un projet pour rechercher les fichiers de commandes + 'final_paths' => [ + 'src/diff-path/commands', + 'app/module/admin/commands', + ], + + // Si vous voulez simplement ajouter le chemin complet, allez-y (absolu ou relatif à la racine du projet) + 'paths' => [ + '/home/user/different-project/src/diff-path/commands', + '/var/www/another-project/app/module/admin/commands', + 'app/my-unique-commands' + ] + ] +]; +``` + +### Accéder à la Configuration + +Si vous devez accéder efficacement aux valeurs de configuration, vous pouvez les accéder via la méthode `__construct` ou la méthode `app()`. Il est également important de noter que si vous avez un fichier `app/config/services.php`, ces services seront également disponibles pour votre commande. + +```php +public function execute() { + $io = $this->app()->io(); + + // Accéder à la configuration + $app_root = $this->config['runway']['app_root']; + + // Accéder aux services comme peut-être une connexion à la base de données + $database = $this->config['database'] + + // ... +} +``` + +## Wrappers d'Aide IA + +Runway dispose de quelques wrappers d'aide qui facilitent la génération de commandes par l'IA. Vous pouvez utiliser `addOption` et `addArgument` d'une manière qui ressemble à Symfony Console. Cela est utile si vous utilisez des outils IA pour générer vos commandes. - // C'est l'endroit où se trouve votre répertoire d'application - "app_root": "app/", - - // C'est le répertoire où se trouve votre fichier index racine - "index_root": "public/", - - // Ce sont les chemins vers les racines d'autres projets - "root_paths": [ - "/home/user/different-project", - "/var/www/another-project" - ], - - // Les chemins de base n'ont probablement pas besoin d'être configurés, mais c'est là si vous en voulez - "base_paths": { - "/includes/libs/vendor", // si vous avez un chemin vraiment unique pour votre répertoire vendor ou autre - }, - - // Les chemins finaux sont des emplacements dans un projet pour rechercher les fichiers de commande - "final_paths": { - "src/diff-path/commands", - "app/module/admin/commands", - }, - - // Si vous voulez simplement ajouter le chemin complet, allez-y (absolu ou relatif à la racine du projet) - "paths": [ - "/home/user/different-project/src/diff-path/commands", - "/var/www/another-project/app/module/admin/commands", - "app/my-unique-commands" - ] +```php +public function __construct(array $config) +{ + parent::__construct('make:example', 'Créer un exemple pour la documentation', $config); + + // L'argument mode est nullable et par défaut complètement optionnel + $this->addOption('name', 'Le nom de l\'exemple', null); } ``` \ No newline at end of file diff --git a/content/v3/id/awesome-plugins/runway.md b/content/v3/id/awesome-plugins/runway.md index bd6c86ca..ed850f71 100644 --- a/content/v3/id/awesome-plugins/runway.md +++ b/content/v3/id/awesome-plugins/runway.md @@ -14,7 +14,24 @@ composer require flightphp/runway ## Konfigurasi Dasar -Pada pertama kali Anda menjalankan Runway, itu akan menjalankan Anda melalui proses pengaturan dan membuat file konfigurasi `.runway.json` di root proyek Anda. File ini akan berisi beberapa konfigurasi yang diperlukan agar Runway bekerja dengan benar. +Pada pertama kali Anda menjalankan Runway, itu akan mencoba mencari konfigurasi `runway` di `app/config/config.php` melalui kunci `'runway'`. + +```php + [ + 'app_root' => 'app/', + 'public_root' => 'public/', + ], +]; +``` + +> **CATATAN** - Mulai dari **v1.2.0**, `.runway-config.json` sudah usang. Silakan migrasi konfigurasi Anda ke `app/config/config.php`. Anda dapat melakukannya dengan mudah menggunakan perintah `php runway config:migrate`. + +### Deteksi Root Proyek + +Runway cukup pintar untuk mendeteksi root proyek Anda, bahkan jika Anda menjalankannya dari subdirektori. Ini mencari indikator seperti `composer.json`, `.git`, atau `app/config/config.php` untuk menentukan di mana root proyek berada. Ini berarti Anda dapat menjalankan perintah Runway dari mana saja di proyek Anda! ## Penggunaan @@ -23,7 +40,17 @@ Runway memiliki sejumlah perintah yang dapat Anda gunakan untuk mengelola aplika 1. Jika Anda menggunakan proyek skeleton, Anda dapat menjalankan `php runway [command]` dari root proyek Anda. 1. Jika Anda menggunakan Runway sebagai paket yang diinstal melalui composer, Anda dapat menjalankan `vendor/bin/runway [command]` dari root proyek Anda. -Untuk perintah apa pun, Anda dapat memberikan flag `--help` untuk mendapatkan informasi lebih lanjut tentang cara menggunakan perintah tersebut. +### Daftar Perintah + +Anda dapat melihat daftar semua perintah yang tersedia dengan menjalankan perintah `php runway`. + +```bash +php runway +``` + +### Bantuan Perintah + +Untuk perintah apa pun, Anda dapat meneruskan flag `--help` untuk mendapatkan informasi lebih lanjut tentang cara menggunakan perintah tersebut. ```bash php runway routes --help @@ -33,7 +60,7 @@ Berikut adalah beberapa contoh: ### Menghasilkan Controller -Berdasarkan konfigurasi di file `.runway.json` Anda, lokasi default akan menghasilkan controller untuk Anda di direktori `app/controllers/`. +Berdasarkan konfigurasi di `runway.app_root`, lokasi akan menghasilkan controller untuk Anda di direktori `app/controllers/`. ```bash php runway make:controller MyController @@ -41,7 +68,7 @@ php runway make:controller MyController ### Menghasilkan Model Active Record -Berdasarkan konfigurasi di file `.runway.json` Anda, lokasi default akan menghasilkan controller untuk Anda di direktori `app/records/`. +Pertama pastikan Anda telah menginstal plugin [Active Record](/awesome-plugins/active-record). Berdasarkan konfigurasi di `runway.app_root`, lokasi akan menghasilkan record untuk Anda di direktori `app/records/`. ```bash php runway make:record users @@ -65,20 +92,20 @@ namespace app\records; * @property string $email * @property string $created_at * @property string $updated_at - * // you could also add relationships here once you define them in the $relations array - * @property CompanyRecord $company Example of a relationship + * // Anda juga bisa menambahkan relasi di sini setelah mendefinisikannya di array $relations + * @property CompanyRecord $company Contoh relasi */ class UserRecord extends \flight\ActiveRecord { /** - * @var array $relations Set the relationships for the model + * @var array $relations Atur relasi untuk model * https://docs.flightphp.com/awesome-plugins/active-record#relationships */ protected array $relations = []; /** - * Constructor - * @param mixed $databaseConnection The connection to the database + * Konstruktor + * @param mixed $databaseConnection Koneksi ke database */ public function __construct($databaseConnection) { @@ -95,23 +122,23 @@ Ini akan menampilkan semua rute yang saat ini terdaftar dengan Flight. php runway routes ``` -Jika Anda ingin hanya melihat rute tertentu, Anda dapat memberikan flag untuk memfilter rute. +Jika Anda ingin hanya melihat rute tertentu, Anda dapat meneruskan flag untuk memfilter rute. ```bash -# Display only GET routes +# Tampilkan hanya rute GET php runway routes --get -# Display only POST routes +# Tampilkan hanya rute POST php runway routes --post -# etc. +# dst. ``` -## Menyesuaikan Runway +## Menambahkan Perintah Kustom ke Runway -Jika Anda membuat paket untuk Flight, atau ingin menambahkan perintah kustom Anda sendiri ke dalam proyek Anda, Anda dapat melakukannya dengan membuat direktori `src/commands/`, `flight/commands/`, `app/commands/`, atau `commands/` untuk proyek/paket Anda. Jika Anda membutuhkan penyesuaian lebih lanjut, lihat bagian di bawah tentang Konfigurasi. +Jika Anda sedang membuat paket untuk Flight, atau ingin menambahkan perintah kustom sendiri ke proyek Anda, Anda dapat melakukannya dengan membuat direktori `src/commands/`, `flight/commands/`, `app/commands/`, atau `commands/` untuk proyek/paket Anda. Jika Anda memerlukan kustomisasi lebih lanjut, lihat bagian di bawah tentang Konfigurasi. -Untuk membuat perintah, Anda cukup memperluas kelas `AbstractBaseCommand`, dan menerapkan setidaknya metode `__construct` dan metode `execute`. +Untuk membuat perintah, Anda cukup memperluas kelas `AbstractBaseCommand`, dan mengimplementasikan setidaknya metode `__construct` dan metode `execute`. ```php $config JSON config from .runway-config.json + * @param array $config Konfigurasi dari app/config/config.php */ public function __construct(array $config) { - parent::__construct('make:example', 'Create an example for the documentation', $config); - $this->argument('', 'The name of the funny gif'); + parent::__construct('make:example', 'Buat contoh untuk dokumentasi', $config); + $this->argument('', 'Nama dari gif lucu'); } /** - * Executes the function + * Menjalankan fungsi * * @return void */ @@ -142,52 +169,118 @@ class ExampleCommand extends AbstractBaseCommand { $io = $this->app()->io(); - $io->info('Creating example...'); + $io->info('Membuat contoh...'); - // Do something here + // Lakukan sesuatu di sini - $io->ok('Example created!'); + $io->ok('Contoh dibuat!'); } } ``` -Lihat [Dokumentasi adhocore/php-cli](https://github.com/adhocore/php-cli) untuk informasi lebih lanjut tentang cara membangun perintah kustom Anda sendiri ke dalam aplikasi Flight! +Lihat [Dokumentasi adhocore/php-cli](https://github.com/adhocore/php-cli) untuk informasi lebih lanjut tentang cara membangun perintah kustom sendiri ke aplikasi Flight Anda! + +## Manajemen Konfigurasi -### Konfigurasi +Karena konfigurasi telah dipindahkan ke `app/config/config.php` mulai dari `v1.2.0`, ada beberapa perintah bantu untuk mengelola konfigurasi. -Jika Anda perlu menyesuaikan konfigurasi untuk Runway, Anda dapat membuat file `.runway-config.json` di root proyek Anda. Berikut adalah beberapa konfigurasi tambahan yang dapat Anda atur: +### Migrasi Konfigurasi Lama -```js +Jika Anda memiliki file `.runway-config.json` lama, Anda dapat dengan mudah memigrasikannya ke `app/config/config.php` dengan perintah berikut: + +```bash +php runway config:migrate +``` + +### Mengatur Nilai Konfigurasi + +Anda dapat mengatur nilai konfigurasi menggunakan perintah `config:set`. Ini berguna jika Anda ingin memperbarui nilai konfigurasi tanpa membuka file. + +```bash +php runway config:set app_root "app/" +``` + +### Mendapatkan Nilai Konfigurasi + +Anda dapat mendapatkan nilai konfigurasi menggunakan perintah `config:get`. + +```bash +php runway config:get app_root +``` + +## Semua Konfigurasi Runway + +Jika Anda perlu menyesuaikan konfigurasi untuk Runway, Anda dapat mengatur nilai-nilai ini di `app/config/config.php`. Berikut adalah beberapa konfigurasi tambahan yang dapat Anda atur: + +```php + [ + // Ini adalah lokasi direktori aplikasi Anda + 'app_root' => 'app/', + + // Ini adalah direktori di mana file indeks root Anda berada + 'index_root' => 'public/', + + // Ini adalah path ke root proyek lain + 'root_paths' => [ + '/home/user/different-project', + '/var/www/another-project' + ], + + // Path dasar kemungkinan besar tidak perlu dikonfigurasi, tapi ini ada jika Anda menginginkannya + 'base_paths' => [ + '/includes/libs/vendor', // jika Anda memiliki path yang sangat unik untuk direktori vendor atau semacamnya + ], + + // Path akhir adalah lokasi dalam proyek untuk mencari file perintah + 'final_paths' => [ + 'src/diff-path/commands', + 'app/module/admin/commands', + ], + + // Jika Anda ingin menambahkan path lengkap, silakan (absolut atau relatif terhadap root proyek) + 'paths' => [ + '/home/user/different-project/src/diff-path/commands', + '/var/www/another-project/app/module/admin/commands', + 'app/my-unique-commands' + ] + ] +]; +``` + +### Mengakses Konfigurasi + +Jika Anda perlu mengakses nilai konfigurasi secara efektif, Anda dapat mengaksesnya melalui metode `__construct` atau metode `app()`. Penting juga untuk dicatat bahwa jika Anda memiliki file `app/config/services.php`, layanan-layanan tersebut juga akan tersedia untuk perintah Anda. + +```php +public function execute() { + $io = $this->app()->io(); + + // Akses konfigurasi + $app_root = $this->config['runway']['app_root']; + + // Akses layanan seperti mungkin koneksi database + $database = $this->config['database'] + + // ... +} +``` + +## Wrapper Pembantu AI + +Runway memiliki beberapa wrapper pembantu yang memudahkan AI untuk menghasilkan perintah. Anda dapat menggunakan `addOption` dan `addArgument` dengan cara yang mirip dengan Symfony Console. Ini membantu jika Anda menggunakan alat AI untuk menghasilkan perintah Anda. - // This is where your application directory is located - "app_root": "app/", - - // This is the directory where your root index file is located - "index_root": "public/", - - // These are the paths to the roots of other projects - "root_paths": [ - "/home/user/different-project", - "/var/www/another-project" - ], - - // Base paths most likely don't need to be configured, but it's here if you want it - "base_paths": { - "/includes/libs/vendor", // if you have a really unique path for your vendor directory or something - }, - - // Final paths are locations within a project to search for the command files - "final_paths": { - "src/diff-path/commands", - "app/module/admin/commands", - }, - - // If you want to just add the full path, go right ahead (absolute or relative to project root) - "paths": [ - "/home/user/different-project/src/diff-path/commands", - "/var/www/another-project/app/module/admin/commands", - "app/my-unique-commands" - ] +```php +public function __construct(array $config) +{ + parent::__construct('make:example', 'Buat contoh untuk dokumentasi', $config); + + // Argumen mode bersifat nullable dan defaultnya sepenuhnya opsional + $this->addOption('name', 'Nama dari contoh', null); } ``` \ No newline at end of file diff --git a/content/v3/ja/awesome-plugins/runway.md b/content/v3/ja/awesome-plugins/runway.md index a54c0738..2862ad72 100644 --- a/content/v3/ja/awesome-plugins/runway.md +++ b/content/v3/ja/awesome-plugins/runway.md @@ -1,8 +1,8 @@ # Runway -Runway は、Flight アプリケーションを管理するのに役立つ CLI アプリケーションです。コントローラーを生成したり、すべてのルートを表示したり、その他さまざまな機能を提供します。これは優れた [adhocore/php-cli](https://github.com/adhocore/php-cli) ライブラリを基にしています。 +Runway は、Flight アプリケーションを管理するのに役立つ CLI アプリケーションです。コントローラーを生成したり、全ルートを表示したり、その他さまざまな機能を提供します。これは優れた [adhocore/php-cli](https://github.com/adhocore/php-cli) ライブラリに基づいています。 -コードを見るには [こちら](https://github.com/flightphp/runway) をクリックしてください。 +コードを表示するには、[ここ](https://github.com/flightphp/runway)をクリックしてください。 ## インストール @@ -14,26 +14,53 @@ composer require flightphp/runway ## 基本設定 -Runway を初めて実行すると、セットアッププロセスを実行し、プロジェクトのルートに `.runway.json` 設定ファイルを作成します。このファイルには、Runway が正常に動作するために必要な設定が含まれています。 +Runway を初めて実行すると、`app/config/config.php` 内の `'runway'` キーから `runway` 設定を探します。 + +```php + [ + 'app_root' => 'app/', + 'public_root' => 'public/', + ], +]; +``` + +> **注意** - **v1.2.0** 以降、`.runway-config.json` は非推奨です。設定を `app/config/config.php` に移行してください。`php runway config:migrate` コマンドで簡単に移行できます。 + +### プロジェクトルートの検出 + +Runway は、プロジェクトのルートを検出するのに十分賢いです。サブディレクトリから実行した場合でも、`composer.json`、`.git`、または `app/config/config.php` などの指標を探してプロジェクトルートを決定します。これにより、プロジェクト内のどこからでも Runway コマンドを実行できます! ## 使用方法 -Runway には、Flight アプリケーションを管理するためのさまざまなコマンドがあります。Runway を使用する簡単な方法は 2 つあります。 +Runway には、Flight アプリケーションを管理するためのいくつかのコマンドがあります。Runway を使用する簡単な方法は 2 つあります。 1. スケルトンプロジェクトを使用している場合、プロジェクトのルートから `php runway [command]` を実行できます。 -1. Composer 経由でインストールしたパッケージとして Runway を使用している場合、プロジェクトのルートから `vendor/bin/runway [command]` を実行できます。 +1. Composer を通じてインストールしたパッケージとして Runway を使用している場合、プロジェクトのルートから `vendor/bin/runway [command]` を実行できます。 + +### コマンドリスト + +`php runway` コマンドを実行すると、すべての利用可能なコマンドのリストを表示できます。 + +```bash +php runway +``` + +### コマンドヘルプ -任意のコマンドに対して、`--help` フラグを渡すことで、そのコマンドの使用方法についての詳細情報を取得できます。 +任意のコマンドに対して、`--help` フラグを渡すと、そのコマンドの使用方法についての詳細情報を取得できます。 ```bash php runway routes --help ``` -以下にいくつかの例を示します: +以下にいくつかの例を示します。 ### コントローラーの生成 -`.runway.json` ファイルの設定に基づいて、デフォルトの場所に `app/controllers/` ディレクトリでコントローラーを生成します。 +`runway.app_root` の設定に基づいて、指定された場所に `app/controllers/` ディレクトリ内のコントローラーを生成します。 ```bash php runway make:controller MyController @@ -41,13 +68,13 @@ php runway make:controller MyController ### Active Record モデルの生成 -`.runway.json` ファイルの設定に基づいて、デフォルトの場所に `app/records/` ディレクトリでコントローラーを生成します。 +まず、[Active Record](/awesome-plugins/active-record) プラグインをインストールしていることを確認してください。`runway.app_root` の設定に基づいて、`app/records/` ディレクトリにレコードを生成します。 ```bash php runway make:record users ``` -たとえば、`users` テーブルに以下のスキーマがある場合:`id`、`name`、`email`、`created_at`、`updated_at`、`app/records/UserRecord.php` ファイルに以下の類似したファイルが作成されます: +たとえば、`users` テーブルに `id`、`name`、`email`、`created_at`、`updated_at` のスキーマがある場合、`app/records/UserRecord.php` ファイルに以下のようないファイルが作成されます: ```php $config .runway-config.json からの JSON 設定 + * @param array $config app/config/config.php からの設定 */ public function __construct(array $config) { @@ -144,50 +171,116 @@ class ExampleCommand extends AbstractBaseCommand $io->info('例を作成中...'); - // ここで何かをします + // ここで何かを実行 $io->ok('例が作成されました!'); } } ``` -Flight アプリケーションに独自のカスタムコマンドを構築する方法についての詳細は、[adhocore/php-cli ドキュメント](https://github.com/adhocore/php-cli) を参照してください! +Flight アプリケーションに独自のカスタムコマンドを構築する方法の詳細については、[adhocore/php-cli ドキュメント](https://github.com/adhocore/php-cli)を参照してください! + +## 設定管理 -### 設定 +v1.2.0 以降、設定が `app/config/config.php` に移行されたため、設定を管理するためのヘルパーコマンドがいくつかあります。 -Runway の設定をカスタマイズする必要がある場合、プロジェクトのルートに `.runway-config.json` ファイルを作成できます。以下に設定できる追加の設定を示します: +### 古い設定の移行 -```js +古い `.runway-config.json` ファイルがある場合、以下のコマンドで簡単に `app/config/config.php` に移行できます: + +```bash +php runway config:migrate +``` + +### 設定値の設定 + +`config:set` コマンドを使用して設定値を設定できます。ファイルを開かずに設定値を更新したい場合に便利です。 + +```bash +php runway config:set app_root "app/" +``` + +### 設定値の取得 + +`config:get` コマンドを使用して設定値を取得できます。 + +```bash +php runway config:get app_root +``` + +## すべての Runway 設定 + +Runway の設定をカスタマイズする必要がある場合、`app/config/config.php` でこれらの値を設定できます。以下に設定できる追加の設定を示します: + +```php + [ + // アプリケーション ディレクトリの場所 + 'app_root' => 'app/', + + // ルートインデックスファイルの場所のディレクトリ + 'index_root' => 'public/', + + // 他のプロジェクトのルートの経路 + 'root_paths' => [ + '/home/user/different-project', + '/var/www/another-project' + ], + + // ベースパスは通常設定する必要はありませんが、必要に応じて使用できます + 'base_paths' => [ + '/includes/libs/vendor', // vendor ディレクトリに独自の経路がある場合など + ], + + // 最終パスは、プロジェクト内のコマンドファイルの検索場所 + 'final_paths' => [ + 'src/diff-path/commands', + 'app/module/admin/commands', + ], + + // 完全なパスを追加したい場合(プロジェクトルートからの絶対または相対パス) + 'paths' => [ + '/home/user/different-project/src/diff-path/commands', + '/var/www/another-project/app/module/admin/commands', + 'app/my-unique-commands' + ] + ] +]; +``` + +### 設定へのアクセス + +設定値を効果的にアクセスする必要がある場合、`__construct` メソッドまたは `app()` メソッド経由でアクセスできます。また、`app/config/services.php` ファイルがある場合、そのサービスもコマンドで利用可能です。 + +```php +public function execute() { + $io = $this->app()->io(); + + // 設定にアクセス + $app_root = $this->config['runway']['app_root']; + + // データベース接続などのサービスにアクセス + $database = $this->config['database'] + + // ... +} +``` + +## AI ヘルパー ラッパー + +Runway には、AI がコマンドを生成しやすくするためのヘルパー ラッパーがいくつかあります。Symfony Console に似た方法で `addOption` と `addArgument` を使用できます。AI ツールを使用してコマンドを生成する場合に役立ちます。 - // アプリケーション ディレクトリが配置されている場所 - "app_root": "app/", - - // ルート index ファイルが配置されているディレクトリ - "index_root": "public/", - - // 他のプロジェクトのルートへのパス - "root_paths": [ - "/home/user/different-project", - "/var/www/another-project" - ], - - // ベース パスは通常設定する必要はありませんが、必要に応じて使用できます - "base_paths": { - "/includes/libs/vendor", // vendor ディレクトリなどのユニークなパスがある場合 - }, - - // 最終パスは、コマンド ファイルを検索するプロジェクト内の場所 - "final_paths": { - "src/diff-path/commands", - "app/module/admin/commands", - }, - - // フルパスを追加したい場合、問題ありません(プロジェクト ルートからの絶対パスまたは相対パス) - "paths": [ - "/home/user/different-project/src/diff-path/commands", - "/var/www/another-project/app/module/admin/commands", - "app/my-unique-commands" - ] +```php +public function __construct(array $config) +{ + parent::__construct('make:example', 'ドキュメント用の例を作成', $config); + + // name オプションは null 可能で、完全にオプションです + $this->addOption('name', '例の名前', null); } ``` \ No newline at end of file diff --git a/content/v3/ko/awesome-plugins/runway.md b/content/v3/ko/awesome-plugins/runway.md index 8319aa93..25bb2794 100644 --- a/content/v3/ko/awesome-plugins/runway.md +++ b/content/v3/ko/awesome-plugins/runway.md @@ -2,52 +2,79 @@ Runway는 Flight 애플리케이션을 관리하는 데 도움을 주는 CLI 애플리케이션입니다. 컨트롤러를 생성하고, 모든 경로를 표시하며, 그 외 더 많은 기능을 제공합니다. 이는 우수한 [adhocore/php-cli](https://github.com/adhocore/php-cli) 라이브러리를 기반으로 합니다. -코드 보기 [여기](https://github.com/flightphp/runway) 클릭. +코드 보기 위해 [여기](https://github.com/flightphp/runway)를 클릭하세요. -## Installation +## 설치 -composer를 사용하여 설치하세요. +Composer를 사용하여 설치하세요. ```bash composer require flightphp/runway ``` -## Basic Configuration +## 기본 구성 -Runway를 처음 실행할 때, 설정 프로세스를 안내하고 프로젝트 루트에 `.runway.json` 설정 파일을 생성합니다. 이 파일은 Runway가 제대로 작동하기 위한 필요한 설정을 포함합니다. +Runway를 처음 실행할 때, `app/config/config.php`의 `'runway'` 키를 통해 `runway` 구성을 찾으려고 시도합니다. -## Usage +```php + [ + 'app_root' => 'app/', + 'public_root' => 'public/', + ], +]; +``` + +> **참고** - **v1.2.0**부터 `.runway-config.json`은 더 이상 사용되지 않습니다. 구성을 `app/config/config.php`로 이전하세요. `php runway config:migrate` 명령으로 쉽게 할 수 있습니다. + +### 프로젝트 루트 감지 + +Runway는 하위 디렉토리에서 실행하더라도 프로젝트 루트를 충분히 스마트하게 감지합니다. `composer.json`, `.git`, 또는 `app/config/config.php`와 같은 지표를 찾아 프로젝트 루트가 어디인지 결정합니다. 따라서 프로젝트의 어디서든 Runway 명령을 실행할 수 있습니다! + +## 사용법 + +Runway는 Flight 애플리케이션을 관리하는 데 사용할 수 있는 여러 명령을 가지고 있습니다. Runway를 사용하는 두 가지 쉬운 방법이 있습니다. + +1. 스켈레톤 프로젝트를 사용 중이라면 프로젝트 루트에서 `php runway [command]`를 실행할 수 있습니다. +1. Composer를 통해 설치된 패키지로 Runway를 사용 중이라면 프로젝트 루트에서 `vendor/bin/runway [command]`를 실행할 수 있습니다. + +### 명령 목록 + +`php runway` 명령을 실행하여 사용 가능한 모든 명령 목록을 볼 수 있습니다. -Runway에는 Flight 애플리케이션을 관리하는 데 사용할 수 있는 여러 명령어가 있습니다. Runway를 사용하는 두 가지 쉬운 방법이 있습니다. +```bash +php runway +``` -1. 스켈레톤 프로젝트를 사용 중이라면, 프로젝트 루트에서 `php runway [command]`를 실행할 수 있습니다. -1. composer를 통해 설치된 패키지로 Runway를 사용 중이라면, 프로젝트 루트에서 `vendor/bin/runway [command]`를 실행할 수 있습니다. +### 명령 도움말 -모든 명령어에 대해 `--help` 플래그를 전달하여 명령어 사용 방법에 대한 더 많은 정보를 얻을 수 있습니다. +모든 명령에 대해 `--help` 플래그를 전달하여 명령 사용 방법에 대한 자세한 정보를 얻을 수 있습니다. ```bash php runway routes --help ``` -다음은 몇 가지 예시입니다: +다음은 몇 가지 예입니다: -### Generate a Controller +### 컨트롤러 생성 -`.runway.json` 파일의 설정에 따라, 기본 위치에 `app/controllers/` 디렉토리에서 컨트롤러를 생성합니다. +`runway.app_root`의 구성에 기반하여 `app/controllers/` 디렉토리에 컨트롤러를 생성합니다. ```bash php runway make:controller MyController ``` -### Generate an Active Record Model +### Active Record 모델 생성 -`.runway.json` 파일의 설정에 따라, 기본 위치에 `app/records/` 디렉토리에서 컨트롤러를 생성합니다. +먼저 [Active Record](/awesome-plugins/active-record) 플러그인이 설치되었는지 확인하세요. `runway.app_root`의 구성에 기반하여 `app/records/` 디렉토리에 레코드를 생성합니다. ```bash php runway make:record users ``` -예를 들어 `users` 테이블에 다음 스키마가 있는 경우: `id`, `name`, `email`, `created_at`, `updated_at`, `app/records/UserRecord.php` 파일에 다음과 유사한 파일이 생성됩니다: +예를 들어 `users` 테이블이 `id`, `name`, `email`, `created_at`, `updated_at` 스키마를 가진 경우, `app/records/UserRecord.php` 파일에 다음과 유사한 파일이 생성됩니다: ```php $config .runway-config.json에서 가져온 JSON 설정 + * @param array $config app/config/config.php의 구성 */ public function __construct(array $config) { - parent::__construct('make:example', '문서에 대한 예시 생성', $config); + parent::__construct('make:example', '문서화를 위한 예제 생성', $config); $this->argument('', '재미있는 GIF의 이름'); } @@ -142,52 +169,118 @@ class ExampleCommand extends AbstractBaseCommand { $io = $this->app()->io(); - $io->info('예시 생성 중...'); + $io->info('예제 생성 중...'); - // 여기에 작업 수행 + // 여기에 무언가 수행 - $io->ok('예시 생성 완료!'); + $io->ok('예제 생성됨!'); } } ``` -Flight 애플리케이션에 사용자 지정 명령어를 빌드하는 방법에 대한 자세한 정보는 [adhocore/php-cli Documentation](https://github.com/adhocore/php-cli)을 참조하세요! +Flight 애플리케이션에 사용자 지정 명령을 구축하는 방법에 대한 자세한 정보는 [adhocore/php-cli 문서](https://github.com/adhocore/php-cli)를 참조하세요! + +## 구성 관리 -### Configuration +`v1.2.0`부터 구성이 `app/config/config.php`로 이동되었으므로 구성 관리를 위한 몇 가지 도우미 명령이 있습니다. -Runway 설정을 커스터마이징해야 한다면, 프로젝트 루트에 `.runway-config.json` 파일을 생성할 수 있습니다. 아래는 설정할 수 있는 추가 설정입니다: +### 이전 구성 이전 -```js +이전 `.runway-config.json` 파일이 있다면 다음 명령으로 `app/config/config.php`로 쉽게 이전할 수 있습니다: + +```bash +php runway config:migrate +``` + +### 구성 값 설정 + +`config:set` 명령을 사용하여 구성 값을 설정할 수 있습니다. 파일을 열지 않고 구성 값을 업데이트하려는 경우 유용합니다. + +```bash +php runway config:set app_root "app/" +``` + +### 구성 값 가져오기 + +`config:get` 명령을 사용하여 구성 값을 가져올 수 있습니다. + +```bash +php runway config:get app_root +``` + +## 모든 Runway 구성 + +Runway 구성을 사용자 지정해야 한다면 `app/config/config.php`에 이러한 값을 설정할 수 있습니다. 아래는 설정할 수 있는 추가 구성입니다: + +```php + [ + // 애플리케이션 디렉토리가 위치한 곳 + 'app_root' => 'app/', + + // 루트 인덱스 파일이 위치한 디렉토리 + 'index_root' => 'public/', + + // 다른 프로젝트의 루트 경로들 + 'root_paths' => [ + '/home/user/different-project', + '/var/www/another-project' + ], + + // 기본 경로는 구성할 필요가 거의 없지만, 필요하다면 여기에 있습니다 + 'base_paths' => [ + '/includes/libs/vendor', // 벤더 디렉토리 등에 정말 독특한 경로가 있는 경우 + ], + + // 최종 경로는 프로젝트 내 명령 파일을 검색할 위치 + 'final_paths' => [ + 'src/diff-path/commands', + 'app/module/admin/commands', + ], + + // 전체 경로를 추가하려면 (프로젝트 루트에 대한 절대 또는 상대 경로) + 'paths' => [ + '/home/user/different-project/src/diff-path/commands', + '/var/www/another-project/app/module/admin/commands', + 'app/my-unique-commands' + ] + ] +]; +``` + +### 구성 접근 + +구성 값을 효과적으로 접근해야 한다면 `__construct` 메서드나 `app()` 메서드를 통해 접근할 수 있습니다. 또한 `app/config/services.php` 파일이 있는 경우 해당 서비스도 명령에 사용할 수 있습니다. + +```php +public function execute() { + $io = $this->app()->io(); + + // 구성 접근 + $app_root = $this->config['runway']['app_root']; + + // 데이터베이스 연결 같은 서비스 접근 + $database = $this->config['database'] + + // ... +} +``` + +## AI 도우미 래퍼 + +Runway에는 AI가 명령을 생성하기 쉽게 하는 몇 가지 도우미 래퍼가 있습니다. Symfony Console과 유사하게 `addOption`과 `addArgument`를 사용할 수 있습니다. AI 도구를 사용하여 명령을 생성할 때 유용합니다. - // 애플리케이션 디렉토리가 위치한 곳 - "app_root": "app/", - - // 루트 인덱스 파일이 위치한 디렉토리 - "index_root": "public/", - - // 다른 프로젝트의 루트 경로 - "root_paths": [ - "/home/user/different-project", - "/var/www/another-project" - ], - - // 기본 경로는 대부분 설정할 필요가 없지만, 필요 시 여기에 있음 - "base_paths": { - "/includes/libs/vendor", // vendor 디렉토리에 특이한 경로가 있는 경우 등 - }, - - // 최종 경로는 프로젝트 내 명령어 파일을 검색할 위치 - "final_paths": { - "src/diff-path/commands", - "app/module/admin/commands", - }, - - // 전체 경로를 추가하려면 그대로 진행 (프로젝트 루트에 대한 절대 또는 상대 경로) - "paths": [ - "/home/user/different-project/src/diff-path/commands", - "/var/www/another-project/app/module/admin/commands", - "app/my-unique-commands" - ] +```php +public function __construct(array $config) +{ + parent::__construct('make:example', '문서화를 위한 예제 생성', $config); + + // name 옵션은 null이고 완전히 선택적입니다 + $this->addOption('name', '예제의 이름', null); } ``` \ No newline at end of file diff --git a/content/v3/lv/awesome-plugins/runway.md b/content/v3/lv/awesome-plugins/runway.md index 5fc12ef6..550ab583 100644 --- a/content/v3/lv/awesome-plugins/runway.md +++ b/content/v3/lv/awesome-plugins/runway.md @@ -1,12 +1,12 @@ # Runway -Runway ir CLI lietojumprogramma, kas palīdz pārvaldīt jūsu Flight lietojumprogrammas. Tā var ģenerēt kontrolierus, parādīt visas maršrutus un vairāk. Tā balstās uz izcilo [adhocore/php-cli](https://github.com/adhocore/php-cli) bibliotēku. +Runway ir CLI lietojumprogramma, kas palīdz pārvaldīt jūsu Flight lietojumprogrammas. Tā var ģenerēt kontrolierus, parādīt visas maršrutus un vairāk. Tā ir balstīta uz izcilo [adhocore/php-cli](https://github.com/adhocore/php-cli) bibliotēku. Noklikšķiniet [šeit](https://github.com/flightphp/runway), lai skatītu kodu. -## Uzstādīšana +## Instalācija -Uzstādiet ar composer. +Instalējiet ar composer. ```bash composer require flightphp/runway @@ -14,16 +14,43 @@ composer require flightphp/runway ## Pamata konfigurācija -Pirmo reizi palaižot Runway, tā vadīs jūs cauri uzstādīšanas procesam un izveidos `.runway.json` konfigurācijas failu jūsu projekta saknes direktorijā. Šis fails saturēs dažas nepieciešamas konfigurācijas, lai Runway darbotos pareizi. +Pirmo reizi palaižot Runway, tā mēģinās atrast `runway` konfigurāciju `app/config/config.php` caur `'runway'` atslēgu. + +```php + [ + 'app_root' => 'app/', + 'public_root' => 'public/', + ], +]; +``` + +> **PIEZĪME** - Sākot ar **v1.2.0**, `.runway-config.json` ir novecojis. Lūdzu, migrējiet savu konfigurāciju uz `app/config/config.php`. Jūs varat to izdarīt viegli ar komandu `php runway config:migrate`. + +### Projekta saknes noteikšana + +Runway ir pietiekami gudra, lai noteiktu jūsu projekta sakni, pat ja jūs to palaižat no apakšdirektorijas. Tā meklē indikatorus, piemēram, `composer.json`, `.git` vai `app/config/config.php`, lai noteiktu, kur ir projekta sakne. Tas nozīmē, ka jūs varat palaidīt Runway komandas no jebkuras vietas jūsu projektā! ## Lietošana Runway ir vairākas komandas, kuras jūs varat izmantot, lai pārvaldītu jūsu Flight lietojumprogrammu. Ir divi viegli veidi, kā izmantot Runway. 1. Ja jūs izmantojat skeletu projektu, jūs varat palaidīt `php runway [command]` no jūsu projekta saknes. -1. Ja jūs izmantojat Runway kā paketi, kas uzstādīta caur composer, jūs varat palaidīt `vendor/bin/runway [command]` no jūsu projekta saknes. +1. Ja jūs izmantojat Runway kā paketi, kas instalēta caur composer, jūs varat palaidīt `vendor/bin/runway [command]` no jūsu projekta saknes. + +### Komandu saraksts + +Jūs varat skatīt visu pieejamo komandu sarakstu, palaižot komandu `php runway`. + +```bash +php runway +``` + +### Komandu palīdzība -Jebkurai komandai jūs varat pievienot `--help` karodziņu, lai iegūtu vairāk informācijas par to, kā izmantot komandu. +Jebkurai komandai jūs varat pievienot karodziņu `--help`, lai iegūtu vairāk informācijas par to, kā izmantot komandu. ```bash php runway routes --help @@ -33,7 +60,7 @@ php runway routes --help ### Ģenerēt kontrolieri -Pamatojoties uz konfigurāciju jūsu `.runway.json` failā, noklusējuma atrašanās vieta ģenerēs kontrolieri jums `app/controllers/` direktorijā. +Pamatojoties uz konfigurāciju `runway.app_root`, atrašanās vieta ģenerēs kontrolieri jums `app/controllers/` direktorijā. ```bash php runway make:controller MyController @@ -41,7 +68,7 @@ php runway make:controller MyController ### Ģenerēt Active Record modeli -Pamatojoties uz konfigurāciju jūsu `.runway.json` failā, noklusējuma atrašanās vieta ģenerēs kontrolieri jums `app/records/` direktorijā. +Vispirms pārliecinieties, ka esat instalējis [Active Record](/awesome-plugins/active-record) spraudni. Pamatojoties uz konfigurāciju `runway.app_root`, atrašanās vieta ģenerēs ierakstu jums `app/records/` direktorijā. ```bash php runway make:record users @@ -65,8 +92,8 @@ namespace app\records; * @property string $email * @property string $created_at * @property string $updated_at - * // jūs varat arī pievienot attiecības šeit, kad definēsiet tās $relations masīvā - * @property CompanyRecord $company Attiecības piemērs + * // jūs varētu arī pievienot attiecības šeit, kad definēsiet tās $relations masīvā + * @property CompanyRecord $company Attiecību piemērs */ class UserRecord extends \flight\ActiveRecord { @@ -89,13 +116,13 @@ class UserRecord extends \flight\ActiveRecord ### Parādīt visus maršrutus -Tas parādīs visus maršrutus, kas pašlaik reģistrēti ar Flight. +Tas parādīs visus maršrutus, kas pašlaik ir reģistrēti ar Flight. ```bash php runway routes ``` -Ja vēlaties skatīt tikai specifiskus maršrutus, jūs varat pievienot karodziņu, lai filtrētu maršrutus. +Ja jūs vēlaties skatīt tikai specifiskus maršrutus, jūs varat pievienot karodziņu, lai filtrētu maršrutus. ```bash # Parādīt tikai GET maršrutus @@ -107,11 +134,11 @@ php runway routes --post # utt. ``` -## Pielāgošana Runway +## Pievienot pielāgotas komandas Runway -Ja jūs vai nu izveidojat paketi Flight, vai vēlaties pievienot savas pielāgotas komandas savam projektam, jūs varat to izdarīt, izveidojot `src/commands/`, `flight/commands/`, `app/commands/` vai `commands/` direktoriju savam projektam/paketei. Ja nepieciešama tālākā pielāgošana, skatiet sadaļu zemāk par Konfigurāciju. +Ja jūs vai nu izveidojat paketi Flight, vai vēlaties pievienot savas pielāgotas komandas savam projektam, jūs varat to izdarīt, izveidojot direktoriju `src/commands/`, `flight/commands/`, `app/commands/` vai `commands/` savam projektam/paketam. Ja jums vajadzīga turpmāka pielāgošana, skatiet sadaļu zemāk par Konfigurāciju. -Lai izveidotu komandu, jūs vienkārši pagarināt `AbstractBaseCommand` klasi un implementēt vismaz `__construct` metodi un `execute` metodi. +Lai izveidotu komandu, jūs vienkārši paplašināt `AbstractBaseCommand` klasi un implementēt vismaz `__construct` metodi un `execute` metodi. ```php $config JSON konfigurācija no .runway-config.json + * @param array $config Konfigurācija no app/config/config.php */ public function __construct(array $config) { parent::__construct('make:example', 'Izveidot piemēru dokumentācijai', $config); - $this->argument('', 'Smieklīgā gif nosaukums'); + $this->argument('', 'Jautrā gif nosaukums'); } /** @@ -153,41 +180,107 @@ class ExampleCommand extends AbstractBaseCommand Skatiet [adhocore/php-cli Dokumentāciju](https://github.com/adhocore/php-cli), lai iegūtu vairāk informācijas par to, kā izveidot savas pielāgotas komandas savai Flight lietojumprogrammai! -### Konfigurācija +## Konfigurācijas pārvaldība + +Tā kā konfigurācija ir pārcelta uz `app/config/config.php` sākot ar `v1.2.0`, ir dažas palīglomas, lai pārvaldītu konfigurāciju. -Ja nepieciešams pielāgot konfigurāciju Runway, jūs varat izveidot `.runway-config.json` failu jūsu projekta saknes direktorijā. Zemāk ir dažas papildu konfigurācijas, kuras jūs varat iestatīt: +### Migrēt veco konfigurāciju -```js +Ja jums ir vecs `.runway-config.json` fails, jūs varat viegli to migrēt uz `app/config/config.php` ar šādu komandu: + +```bash +php runway config:migrate +``` + +### Iestatīt konfigurācijas vērtību + +Jūs varat iestatīt konfigurācijas vērtību, izmantojot `config:set` komandu. Tas ir noderīgi, ja vēlaties atjaunināt konfigurācijas vērtību, neizmantojot failu. + +```bash +php runway config:set app_root "app/" +``` + +### Iegūt konfigurācijas vērtību + +Jūs varat iegūt konfigurācijas vērtību, izmantojot `config:get` komandu. + +```bash +php runway config:get app_root +``` + +## Visas Runway konfigurācijas + +Ja jums vajadzīga pielāgošana Runway konfigurācijai, jūs varat iestatīt šīs vērtības `app/config/config.php`. Zemāk ir dažas papildu konfigurācijas, kuras jūs varat iestatīt: + +```php + [ + // Šī ir vieta, kur atrodas jūsu lietojumprogrammas direktorija + 'app_root' => 'app/', + + // Šī ir direktorija, kur atrodas jūsu saknes indeksa fails + 'index_root' => 'public/', + + // Šīs ir ceļi uz citu projektu saknēm + 'root_paths' => [ + '/home/user/different-project', + '/var/www/another-project' + ], + + // Bāzes ceļi, visticamāk, nav jākonfigurē, bet tas ir šeit, ja vēlaties + 'base_paths' => [ + '/includes/libs/vendor', // ja jums ir patiesi unikāls ceļš uz jūsu vendor direktoriju vai kaut ko + ], + + // Galīgie ceļi ir atrašanās vietas projektā, kur meklēt komandu failus + 'final_paths' => [ + 'src/diff-path/commands', + 'app/module/admin/commands', + ], + + // Ja vēlaties pievienot pilnu ceļu, dariet to (absolūts vai relatīvs pret projektu sakni) + 'paths' => [ + '/home/user/different-project/src/diff-path/commands', + '/var/www/another-project/app/module/admin/commands', + 'app/my-unique-commands' + ] + ] +]; +``` + +### Piekļuve konfigurācijai + +Ja jums vajadzīga efektīva piekļuve konfigurācijas vērtībām, jūs varat piekļūt tām caur `__construct` metodi vai `app()` metodi. Ir arī svarīgi atzīmēt, ka, ja jums ir `app/config/services.php` fails, šie servisi būs pieejami jūsu komandai. + +```php +public function execute() { + $io = $this->app()->io(); + + // Piekļūt konfigurācijai + $app_root = $this->config['runway']['app_root']; + + // Piekļūt servisiem, piemēram, datubāzes savienojumam + $database = $this->config['database'] + + // ... +} +``` + +## AI palīglopu apvalki + +Runway ir daži palīglopu apvalki, kas padara vieglāku AI komandu ģenerēšanu. Jūs varat izmantot `addOption` un `addArgument` veidā, kas šķiet līdzīgs Symfony Console. Tas ir noderīgi, ja izmantojat AI rīkus, lai ģenerētu jūsu komandas. - // Šī ir vieta, kur atrodas jūsu lietojumprogrammas direktorija - "app_root": "app/", - - // Šī ir direktorija, kur atrodas jūsu saknes indeksa fails - "index_root": "public/", - - // Šie ir ceļi uz citu projektu saknēm - "root_paths": [ - "/home/user/different-project", - "/var/www/another-project" - ], - - // Bāzes ceļi visticamāk nav jākonfigurē, bet tas ir šeit, ja vēlaties - "base_paths": { - "/includes/libs/vendor", // ja jums ir patiesi unikāls ceļš uz jūsu vendor direktoriju vai kaut ko - }, - - // Galīgie ceļi ir vietas projektā, kur meklēt komandu failus - "final_paths": { - "src/diff-path/commands", - "app/module/admin/commands", - }, - - // Ja vēlaties pievienot pilnu ceļu, dariet to (absolūts vai relatīvs pret projektu sakni) - "paths": [ - "/home/user/different-project/src/diff-path/commands", - "/var/www/another-project/app/module/admin/commands", - "app/my-unique-commands" - ] +```php +public function __construct(array $config) +{ + parent::__construct('make:example', 'Izveidot piemēru dokumentācijai', $config); + + // The mode argument is nullable and defaults to completely optional + $this->addOption('name', 'The name of the example', null); } ``` \ No newline at end of file diff --git a/content/v3/pt/awesome-plugins/runway.md b/content/v3/pt/awesome-plugins/runway.md index 73cf108e..92da2dd9 100644 --- a/content/v3/pt/awesome-plugins/runway.md +++ b/content/v3/pt/awesome-plugins/runway.md @@ -14,14 +14,41 @@ composer require flightphp/runway ## Configuração Básica -Na primeira vez que você executar o Runway, ele o guiará por um processo de configuração e criará um arquivo de configuração `.runway.json` na raiz do seu projeto. Este arquivo conterá algumas configurações necessárias para o Runway funcionar corretamente. +Na primeira vez que você executar o Runway, ele tentará encontrar uma configuração `runway` em `app/config/config.php` via a chave `'runway'`. + +```php + [ + 'app_root' => 'app/', + 'public_root' => 'public/', + ], +]; +``` + +> **NOTA** - A partir de **v1.2.0**, `.runway-config.json` está depreciado. Por favor, migre sua configuração para `app/config/config.php`. Você pode fazer isso facilmente com o comando `php runway config:migrate`. + +### Detecção da Raiz do Projeto + +Runway é inteligente o suficiente para detectar a raiz do seu projeto, mesmo se você o executar a partir de um subdiretório. Ele procura indicadores como `composer.json`, `.git` ou `app/config/config.php` para determinar onde está a raiz do projeto. Isso significa que você pode executar comandos do Runway de qualquer lugar no seu projeto! ## Uso -O Runway possui vários comandos que você pode usar para gerenciar sua aplicação Flight. Existem duas maneiras fáceis de usar o Runway. +Runway tem uma série de comandos que você pode usar para gerenciar sua aplicação Flight. Existem duas maneiras fáceis de usar o Runway. + +1. Se você estiver usando o projeto esqueleto, você pode executar `php runway [command]` a partir da raiz do seu projeto. +1. Se você estiver usando Runway como um pacote instalado via composer, você pode executar `vendor/bin/runway [command]` a partir da raiz do seu projeto. + +### Lista de Comandos + +Você pode visualizar uma lista de todos os comandos disponíveis executando o comando `php runway`. + +```bash +php runway +``` -1. Se você estiver usando o projeto skeleton, você pode executar `php runway [command]` a partir da raiz do seu projeto. -1. Se você estiver usando o Runway como um pacote instalado via composer, você pode executar `vendor/bin/runway [command]` a partir da raiz do seu projeto. +### Ajuda do Comando Para qualquer comando, você pode passar a flag `--help` para obter mais informações sobre como usar o comando. @@ -33,7 +60,7 @@ Aqui estão alguns exemplos: ### Gerar um Controlador -Com base na configuração no seu arquivo `.runway.json`, o local padrão gerará um controlador para você no diretório `app/controllers/`. +Com base na configuração em `runway.app_root`, o local gerará um controlador para você no diretório `app/controllers/`. ```bash php runway make:controller MyController @@ -41,7 +68,7 @@ php runway make:controller MyController ### Gerar um Modelo Active Record -Com base na configuração no seu arquivo `.runway.json`, o local padrão gerará um controlador para você no diretório `app/records/`. +Primeiro, certifique-se de que você instalou o plugin [Active Record](/awesome-plugins/active-record). Com base na configuração em `runway.app_root`, o local gerará um registro para você no diretório `app/records/`. ```bash php runway make:record users @@ -89,13 +116,13 @@ class UserRecord extends \flight\ActiveRecord ### Exibir Todas as Rotas -Isso exibirá todas as rotas que estão atualmente registradas no Flight. +Isso exibirá todas as rotas que estão atualmente registradas com o Flight. ```bash php runway routes ``` -Se você quiser visualizar apenas rotas específicas, pode passar uma flag para filtrar as rotas. +Se você quiser visualizar apenas rotas específicas, você pode passar uma flag para filtrar as rotas. ```bash # Exibir apenas rotas GET @@ -107,9 +134,9 @@ php runway routes --post # etc. ``` -## Personalizando o Runway +## Adicionando Comandos Personalizados ao Runway -Se você estiver criando um pacote para o Flight, ou quiser adicionar seus próprios comandos personalizados ao seu projeto, você pode fazer isso criando um diretório `src/commands/`, `flight/commands/`, `app/commands/`, ou `commands/` para o seu projeto/pacote. Se precisar de mais personalização, veja a seção abaixo sobre Configuração. +Se você estiver criando um pacote para o Flight ou quiser adicionar seus próprios comandos personalizados ao seu projeto, você pode fazer isso criando um diretório `src/commands/`, `flight/commands/`, `app/commands/` ou `commands/` para o seu projeto/pacote. Se precisar de mais personalização, veja a seção abaixo sobre Configuração. Para criar um comando, você simplesmente estende a classe `AbstractBaseCommand` e implementa, no mínimo, um método `__construct` e um método `execute`. @@ -125,11 +152,11 @@ class ExampleCommand extends AbstractBaseCommand /** * Construtor * - * @param array $config Configuração JSON de .runway-config.json + * @param array $config Config de app/config/config.php */ public function __construct(array $config) { - parent::__construct('make:example', 'Criar um exemplo para a documentação', $config); + parent::__construct('make:example', 'Cria um exemplo para a documentação', $config); $this->argument('', 'O nome do gif engraçado'); } @@ -153,41 +180,107 @@ class ExampleCommand extends AbstractBaseCommand Consulte a [Documentação do adhocore/php-cli](https://github.com/adhocore/php-cli) para mais informações sobre como construir seus próprios comandos personalizados para sua aplicação Flight! -### Configuração +## Gerenciamento de Configuração + +Como a configuração foi movida para `app/config/config.php` a partir da `v1.2.0`, há alguns comandos auxiliares para gerenciar a configuração. -Se você precisar personalizar a configuração para o Runway, pode criar um arquivo `.runway-config.json` na raiz do seu projeto. Abaixo estão algumas configurações adicionais que você pode definir: +### Migrar Configuração Antiga -```js +Se você tiver um arquivo `.runway-config.json` antigo, você pode migrá-lo facilmente para `app/config/config.php` com o seguinte comando: + +```bash +php runway config:migrate +``` + +### Definir Valor de Configuração + +Você pode definir um valor de configuração usando o comando `config:set`. Isso é útil se você quiser atualizar um valor de configuração sem abrir o arquivo. + +```bash +php runway config:set app_root "app/" +``` + +### Obter Valor de Configuração + +Você pode obter um valor de configuração usando o comando `config:get`. + +```bash +php runway config:get app_root +``` + +## Todas as Configurações do Runway + +Se você precisar personalizar a configuração para o Runway, você pode definir esses valores em `app/config/config.php`. Abaixo estão algumas configurações adicionais que você pode definir: + +```php + [ + // Este é o local onde o diretório da sua aplicação está localizado + 'app_root' => 'app/', + + // Este é o diretório onde o seu arquivo index raiz está localizado + 'index_root' => 'public/', + + // Estes são os caminhos para as raízes de outros projetos + 'root_paths' => [ + '/home/user/different-project', + '/var/www/another-project' + ], + + // Caminhos base provavelmente não precisam ser configurados, mas está aqui se você quiser + 'base_paths' => [ + '/includes/libs/vendor', // se você tiver um caminho realmente único para o seu diretório vendor ou algo assim + ], + + // Caminhos finais são locais dentro de um projeto para procurar os arquivos de comando + 'final_paths' => [ + 'src/diff-path/commands', + 'app/module/admin/commands', + ], + + // Se você quiser apenas adicionar o caminho completo, vá em frente (absoluto ou relativo à raiz do projeto) + 'paths' => [ + '/home/user/different-project/src/diff-path/commands', + '/var/www/another-project/app/module/admin/commands', + 'app/my-unique-commands' + ] + ] +]; +``` + +### Acessando a Configuração + +Se você precisar acessar os valores de configuração de forma eficaz, você pode acessá-los através do método `__construct` ou do método `app()`. Também é importante notar que, se você tiver um arquivo `app/config/services.php`, esses serviços também estarão disponíveis para o seu comando. + +```php +public function execute() { + $io = $this->app()->io(); + + // Acessar configuração + $app_root = $this->config['runway']['app_root']; + + // Acessar serviços como talvez uma conexão com o banco de dados + $database = $this->config['database'] + + // ... +} +``` + +## Wrappers de Auxílio de IA + +Runway tem alguns wrappers de auxílio que facilitam para a IA gerar comandos. Você pode usar `addOption` e `addArgument` de uma maneira que se sinta semelhante ao Symfony Console. Isso é útil se você estiver usando ferramentas de IA para gerar seus comandos. - // Este é o local onde o diretório da sua aplicação está localizado - "app_root": "app/", - - // Este é o diretório onde o arquivo index raiz está localizado - "index_root": "public/", - - // Estes são os caminhos para as raízes de outros projetos - "root_paths": [ - "/home/user/different-project", - "/var/www/another-project" - ], - - // Caminhos base provavelmente não precisam ser configurados, mas está aqui se você quiser - "base_paths": { - "/includes/libs/vendor", // se você tiver um caminho realmente único para o diretório vendor ou algo assim - }, - - // Caminhos finais são locais dentro de um projeto para procurar os arquivos de comando - "final_paths": { - "src/diff-path/commands", - "app/module/admin/commands", - }, - - // Se você quiser apenas adicionar o caminho completo, vá em frente (absoluto ou relativo à raiz do projeto) - "paths": [ - "/home/user/different-project/src/diff-path/commands", - "/var/www/another-project/app/module/admin/commands", - "app/my-unique-commands" - ] +```php +public function __construct(array $config) +{ + parent::__construct('make:example', 'Cria um exemplo para a documentação', $config); + + // O argumento mode é anulável e padrão para completamente opcional + $this->addOption('name', 'O nome do exemplo', null); } ``` \ No newline at end of file diff --git a/content/v3/ru/awesome-plugins/runway.md b/content/v3/ru/awesome-plugins/runway.md index dafbb0d3..8b468b1c 100644 --- a/content/v3/ru/awesome-plugins/runway.md +++ b/content/v3/ru/awesome-plugins/runway.md @@ -14,7 +14,24 @@ composer require flightphp/runway ## Базовая конфигурация -В первый раз, когда вы запустите Runway, он проведёт вас через процесс настройки и создаст файл конфигурации `.runway.json` в корне вашего проекта. Этот файл будет содержать некоторые необходимые конфигурации для правильной работы Runway. +В первый раз при запуске Runway попытается найти конфигурацию `runway` в `app/config/config.php` через ключ `'runway'`. + +```php + [ + 'app_root' => 'app/', + 'public_root' => 'public/', + ], +]; +``` + +> **ПРИМЕЧАНИЕ** - Начиная с **v1.2.0**, `.runway-config.json` устарел. Пожалуйста, мигрируйте вашу конфигурацию в `app/config/config.php`. Вы можете сделать это легко с помощью команды `php runway config:migrate`. + +### Обнаружение корня проекта + +Runway достаточно умён, чтобы обнаружить корень вашего проекта, даже если вы запускаете его из поддиректории. Он ищет индикаторы, такие как `composer.json`, `.git` или `app/config/config.php`, чтобы определить, где находится корень проекта. Это значит, что вы можете запускать команды Runway откуда угодно в вашем проекте! ## Использование @@ -23,6 +40,16 @@ Runway имеет ряд команд, которые вы можете испо 1. Если вы используете скелетный проект, вы можете запустить `php runway [command]` из корня вашего проекта. 1. Если вы используете Runway как пакет, установленный через composer, вы можете запустить `vendor/bin/runway [command]` из корня вашего проекта. +### Список команд + +Вы можете просмотреть список всех доступных команд, запустив команду `php runway`. + +```bash +php runway +``` + +### Справка по командам + Для любой команды вы можете передать флаг `--help`, чтобы получить больше информации о том, как использовать команду. ```bash @@ -33,7 +60,7 @@ php runway routes --help ### Генерация контроллера -На основе конфигурации в вашем файле `.runway.json` по умолчанию будет сгенерирован контроллер в директории `app/controllers/`. +На основе конфигурации в `runway.app_root` будет сгенерирован контроллер в директории `app/controllers/`. ```bash php runway make:controller MyController @@ -41,13 +68,13 @@ php runway make:controller MyController ### Генерация модели Active Record -На основе конфигурации в вашем файле `.runway.json` по умолчанию будет сгенерирована модель в директории `app/records/`. +Сначала убедитесь, что вы установили плагин [Active Record](/awesome-plugins/active-record). На основе конфигурации в `runway.app_root` будет сгенерирована запись для вас в директории `app/records/`. ```bash php runway make:record users ``` -Например, если у вас есть таблица `users` со следующей схемой: `id`, `name`, `email`, `created_at`, `updated_at`, то в файле `app/records/UserRecord.php` будет создан файл, похожий на следующий: +Если, например, у вас есть таблица `users` со следующей схемой: `id`, `name`, `email`, `created_at`, `updated_at`, будет создан файл, похожий на следующий, в файле `app/records/UserRecord.php`: ```php $config JSON-конфигурация из .runway-config.json + * @param array $config Config from app/config/config.php */ public function __construct(array $config) { - parent::__construct('make:example', 'Создать пример для документации', $config); - $this->argument('', 'Имя забавного GIF'); + parent::__construct('make:example', 'Create an example for the documentation', $config); + $this->argument('', 'The name of the funny gif'); } /** - * Выполняет функцию + * Executes the function * * @return void */ @@ -142,52 +169,118 @@ class ExampleCommand extends AbstractBaseCommand { $io = $this->app()->io(); - $io->info('Создание примера...'); + $io->info('Creating example...'); - // Сделайте что-то здесь + // Do something here - $io->ok('Пример создан!'); + $io->ok('Example created!'); } } ``` -См. [Документацию adhocore/php-cli](https://github.com/adhocore/php-cli) для получения дополнительной информации о том, как создавать свои собственные пользовательские команды для вашего приложения Flight! +См. [Документацию adhocore/php-cli](https://github.com/adhocore/php-cli) для получения дополнительной информации о том, как создавать свои собственные пользовательские команды в вашем приложении Flight! + +## Управление конфигурацией -### Конфигурация +Поскольку конфигурация переместилась в `app/config/config.php` начиная с `v1.2.0`, есть несколько вспомогательных команд для управления конфигурацией. -Если вам нужно настроить конфигурацию для Runway, вы можете создать файл `.runway-config.json` в корне вашего проекта. Ниже приведены некоторые дополнительные конфигурации, которые вы можете установить: +### Миграция старой конфигурации -```js +Если у вас есть старый файл `.runway-config.json`, вы можете легко мигрировать его в `app/config/config.php` с помощью следующей команды: + +```bash +php runway config:migrate +``` + +### Установка значения конфигурации + +Вы можете установить значение конфигурации с помощью команды `config:set`. Это полезно, если вы хотите обновить значение конфигурации без открытия файла. + +```bash +php runway config:set app_root "app/" +``` + +### Получение значения конфигурации + +Вы можете получить значение конфигурации с помощью команды `config:get`. + +```bash +php runway config:get app_root +``` + +## Все конфигурации Runway + +Если вам нужно настроить конфигурацию для Runway, вы можете установить эти значения в `app/config/config.php`. Ниже приведены некоторые дополнительные конфигурации, которые вы можете установить: + +```php + [ + // This is where your application directory is located + 'app_root' => 'app/', + + // This is the directory where your root index file is located + 'index_root' => 'public/', + + // These are the paths to the roots of other projects + 'root_paths' => [ + '/home/user/different-project', + '/var/www/another-project' + ], + + // Base paths most likely don't need to be configured, but it's here if you want it + 'base_paths' => [ + '/includes/libs/vendor', // if you have a really unique path for your vendor directory or something + ], + + // Final paths are locations within a project to search for the command files + 'final_paths' => [ + 'src/diff-path/commands', + 'app/module/admin/commands', + ], + + // If you want to just add the full path, go right ahead (absolute or relative to project root) + 'paths' => [ + '/home/user/different-project/src/diff-path/commands', + '/var/www/another-project/app/module/admin/commands', + 'app/my-unique-commands' + ] + ] +]; +``` + +### Доступ к конфигурации + +Если вам нужно эффективно получить доступ к значениям конфигурации, вы можете получить к ним доступ через метод `__construct` или метод `app()`. Также важно отметить, что если у вас есть файл `app/config/services.php`, эти сервисы также будут доступны для вашей команды. + +```php +public function execute() { + $io = $this->app()->io(); + + // Access configuration + $app_root = $this->config['runway']['app_root']; + + // Access services like maybe a database connection + $database = $this->config['database'] + + // ... +} +``` + +## Обёртки для помощника ИИ + +Runway имеет некоторые обёртки-помощники, которые облегчают генерацию команд ИИ. Вы можете использовать `addOption` и `addArgument` таким образом, который похож на Symfony Console. Это полезно, если вы используете инструменты ИИ для генерации ваших команд. - // Здесь находится директория вашего приложения - "app_root": "app/", - - // Это директория, где находится ваш корневой индексный файл - "index_root": "public/", - - // Это пути к корням других проектов - "root_paths": [ - "/home/user/different-project", - "/var/www/another-project" - ], - - // Базовые пути, скорее всего, не нужно настраивать, но они здесь, если вы хотите - "base_paths": { - "/includes/libs/vendor", // если у вас есть действительно уникальный путь для директории vendor или чего-то подобного - }, - - // Финальные пути — это расположения внутри проекта для поиска файлов команд - "final_paths": { - "src/diff-path/commands", - "app/module/admin/commands", - }, - - // Если вы хотите просто добавить полный путь, вперед (абсолютный или относительный к корню проекта) - "paths": [ - "/home/user/different-project/src/diff-path/commands", - "/var/www/another-project/app/module/admin/commands", - "app/my-unique-commands" - ] +```php +public function __construct(array $config) +{ + parent::__construct('make:example', 'Create an example for the documentation', $config); + + // The mode argument is nullable and defaults to completely optional + $this->addOption('name', 'The name of the example', null); } ``` \ No newline at end of file diff --git a/content/v3/uk/awesome-plugins/runway.md b/content/v3/uk/awesome-plugins/runway.md index bb9dfd96..7a2e847b 100644 --- a/content/v3/uk/awesome-plugins/runway.md +++ b/content/v3/uk/awesome-plugins/runway.md @@ -1,6 +1,6 @@ # Runway -Runway — це CLI-додаток, який допомагає керувати вашими додатками Flight. Він може генерувати контролери, відображати всі маршрути та інше. Він базується на чудовій бібліотеці [adhocore/php-cli](https://github.com/adhocore/php-cli). +Runway — це CLI-застосунок, який допомагає керувати вашими Flight-застосунками. Він може генерувати контролери, відображати всі маршрути та багато іншого. Він базується на чудовій бібліотеці [adhocore/php-cli](https://github.com/adhocore/php-cli). Натисніть [тут](https://github.com/flightphp/runway), щоб переглянути код. @@ -12,17 +12,44 @@ Runway — це CLI-додаток, який допомагає керувати composer require flightphp/runway ``` -## Базова конфігурація +## Базова Конфігурація -Вперше запускаючи Runway, він проведе вас через процес налаштування та створить файл конфігурації `.runway.json` у корені вашого проекту. Цей файл міститиме деякі необхідні конфігурації для правильної роботи Runway. +Вперше запустивши Runway, він спробує знайти конфігурацію `runway` у `app/config/config.php` через ключ `'runway'`. + +```php + [ + 'app_root' => 'app/', + 'public_root' => 'public/', + ], +]; +``` + +> **ПРИМІТКА** - Починаючи з **v1.2.0**, `.runway-config.json` є застарілим. Будь ласка, мігруйте вашу конфігурацію до `app/config/config.php`. Ви можете зробити це легко за допомогою команди `php runway config:migrate`. + +### Виявлення Кореня Проекту + +Runway достатньо розумний, щоб виявити корінь вашого проекту, навіть якщо ви запускаєте його з підкаталогу. Він шукає індикатори, такі як `composer.json`, `.git` або `app/config/config.php`, щоб визначити, де знаходиться корінь проекту. Це означає, що ви можете запускати команди Runway з будь-якого місця у вашому проекті! ## Використання -Runway має низку команд, які ви можете використовувати для керування вашим додатком Flight. Є два простих способи використовувати Runway. +Runway має низку команд, які ви можете використовувати для керування вашим Flight-застосунком. Є два простих способи використовувати Runway. 1. Якщо ви використовуєте скелетний проект, ви можете запустити `php runway [command]` з кореня вашого проекту. 1. Якщо ви використовуєте Runway як пакет, встановлений через composer, ви можете запустити `vendor/bin/runway [command]` з кореня вашого проекту. +### Список Команд + +Ви можете переглянути список усіх доступних команд, запустивши команду `php runway`. + +```bash +php runway +``` + +### Довідка по Командах + Для будь-якої команди ви можете передати прапорець `--help`, щоб отримати більше інформації про те, як використовувати команду. ```bash @@ -31,23 +58,23 @@ php runway routes --help Ось кілька прикладів: -### Генерація контролера +### Генерація Контролера -На основі конфігурації у вашому файлі `.runway.json`, за замовчуванням буде згенеровано контролер у директорії `app/controllers/`. +На основі конфігурації в `runway.app_root`, локація згенерує для вас контролер у директорії `app/controllers/`. ```bash php runway make:controller MyController ``` -### Генерація моделі Active Record +### Генерація Моделі Active Record -На основі конфігурації у вашому файлі `.runway.json`, за замовчуванням буде згенеровано контролер у директорії `app/records/`. +Спочатку переконайтеся, що ви встановили плагін [Active Record](/awesome-plugins/active-record). На основі конфігурації в `runway.app_root`, локація згенерує для вас запис у директорії `app/records/`. ```bash php runway make:record users ``` -Наприклад, якщо у вас є таблиця `users` з такою схемою: `id`, `name`, `email`, `created_at`, `updated_at`, буде створено файл, подібний до наступного, у файлі `app/records/UserRecord.php`: +Наприклад, якщо у вас є таблиця `users` з такою схемою: `id`, `name`, `email`, `created_at`, `updated_at`, файл, подібний до наступного, буде створено у файлі `app/records/UserRecord.php`: ```php $config JSON config from .runway-config.json + * @param array $config Config from app/config/config.php */ public function __construct(array $config) { @@ -151,43 +178,109 @@ class ExampleCommand extends AbstractBaseCommand } ``` -Дивіться [Документацію adhocore/php-cli](https://github.com/adhocore/php-cli) для отримання додаткової інформації про те, як створювати власні власні команди для вашого додатка Flight! +Дивіться [Документацію adhocore/php-cli](https://github.com/adhocore/php-cli) для отримання додаткової інформації про те, як створювати власні власні команди для вашого Flight-застосунку! + +## Керування Конфігурацією -### Конфігурація +Оскільки конфігурація переміщена до `app/config/config.php` починаючи з `v1.2.0`, є кілька допоміжних команд для керування конфігурацією. -Якщо вам потрібно налаштувати конфігурацію для Runway, ви можете створити файл `.runway-config.json` у корені вашого проекту. Нижче наведено деякі додаткові конфігурації, які ви можете встановити: +### Міграція Старої Конфігурації -```js +Якщо у вас є старий файл `.runway-config.json`, ви можете легко мігрувати його до `app/config/config.php` за допомогою наступної команди: + +```bash +php runway config:migrate +``` + +### Встановлення Значення Конфігурації + +Ви можете встановити значення конфігурації за допомогою команди `config:set`. Це корисно, якщо ви хочете оновити значення конфігурації без відкриття файлу. + +```bash +php runway config:set app_root "app/" +``` + +### Отримання Значення Конфігурації + +Ви можете отримати значення конфігурації за допомогою команди `config:get`. + +```bash +php runway config:get app_root +``` + +## Усі Конфігурації Runway + +Якщо вам потрібно кастомізувати конфігурацію для Runway, ви можете встановити ці значення в `app/config/config.php`. Нижче наведено деякі додаткові конфігурації, які ви можете встановити: + +```php + [ + // This is where your application directory is located + 'app_root' => 'app/', + + // This is the directory where your root index file is located + 'index_root' => 'public/', + + // These are the paths to the roots of other projects + 'root_paths' => [ + '/home/user/different-project', + '/var/www/another-project' + ], + + // Base paths most likely don't need to be configured, but it's here if you want it + 'base_paths' => [ + '/includes/libs/vendor', // if you have a really unique path for your vendor directory or something + ], + + // Final paths are locations within a project to search for the command files + 'final_paths' => [ + 'src/diff-path/commands', + 'app/module/admin/commands', + ], + + // If you want to just add the full path, go right ahead (absolute or relative to project root) + 'paths' => [ + '/home/user/different-project/src/diff-path/commands', + '/var/www/another-project/app/module/admin/commands', + 'app/my-unique-commands' + ] + ] +]; +``` + +### Доступ до Конфігурації + +Якщо вам потрібно ефективно доступатися до значень конфігурації, ви можете доступатися до них через метод `__construct` або метод `app()`. Також важливо зазначити, що якщо у вас є файл `app/config/services.php`, ці сервіси також будуть доступні для вашої команди. + +```php +public function execute() { + $io = $this->app()->io(); + + // Access configuration + $app_root = $this->config['runway']['app_root']; + + // Access services like maybe a database connection + $database = $this->config['database'] + + // ... +} +``` + +## Обгортки Допоміжника ШІ + +Runway має деякі обгортки помічників, які полегшують для ШІ генерацію команд. Ви можете використовувати `addOption` та `addArgument` таким чином, що нагадує Symfony Console. Це корисно, якщо ви використовуєте інструменти ШІ для генерації ваших команд. - // This is where your application directory is located - "app_root": "app/", - - // This is the directory where your root index file is located - "index_root": "public/", - - // These are the paths to the roots of other projects - "root_paths": [ - "/home/user/different-project", - "/var/www/another-project" - ], - - // Base paths most likely don't need to be configured, but it's here if you want it - "base_paths": { - "/includes/libs/vendor", // if you have a really unique path for your vendor directory or something - }, - - // Final paths are locations within a project to search for the command files - "final_paths": { - "src/diff-path/commands", - "app/module/admin/commands", - }, - - // If you want to just add the full path, go right ahead (absolute or relative to project root) - "paths": [ - "/home/user/different-project/src/diff-path/commands", - "/var/www/another-project/app/module/admin/commands", - "app/my-unique-commands" - ] +```php +public function __construct(array $config) +{ + parent::__construct('make:example', 'Create an example for the documentation', $config); + + // The mode argument is nullable and defaults to completely optional + $this->addOption('name', 'The name of the example', null); } ``` \ No newline at end of file diff --git a/content/v3/zh/awesome-plugins/runway.md b/content/v3/zh/awesome-plugins/runway.md index 72d1e375..f9ab9233 100644 --- a/content/v3/zh/awesome-plugins/runway.md +++ b/content/v3/zh/awesome-plugins/runway.md @@ -14,16 +14,43 @@ composer require flightphp/runway ## 基本配置 -首次运行 Runway 时,它会引导您完成设置过程,并在项目根目录创建一个 `.runway.json` 配置文件。此文件将包含 Runway 正常工作的必要配置。 +第一次运行 Runway 时,它会尝试在 `app/config/config.php` 中通过 `'runway'` 键查找 `runway` 配置。 + +```php + [ + 'app_root' => 'app/', + 'public_root' => 'public/', + ], +]; +``` + +> **注意** - 从 **v1.2.0** 开始,`.runway-config.json` 已弃用。请将您的配置迁移到 `app/config/config.php`。您可以使用 `php runway config:migrate` 命令轻松完成此操作。 + +### 项目根目录检测 + +Runway 足够智能,即使从子目录运行它,也能检测到项目根目录。它会查找像 `composer.json`、`.git` 或 `app/config/config.php` 这样的指示符来确定项目根目录在哪里。这意味着您可以在项目中的任何地方运行 Runway 命令! ## 使用 -Runway 具有多个命令,可用于管理您的 Flight 应用程序。有两种简单的方式使用 Runway。 +Runway 有许多命令可用于管理您的 Flight 应用程序。有两种简单的方式使用 Runway。 + +1. 如果您使用的是骨架项目,您可以从项目根目录运行 `php runway [command]`。 +1. 如果您通过 Composer 安装 Runway 作为包,您可以从项目根目录运行 `vendor/bin/runway [command]`。 + +### 命令列表 + +您可以通过运行 `php runway` 命令查看所有可用命令的列表。 + +```bash +php runway +``` -1. 如果您使用的是骨架项目,可以从项目根目录运行 `php runway [command]`。 -1. 如果您通过 Composer 安装 Runway 作为包,可以从项目根目录运行 `vendor/bin/runway [command]`。 +### 命令帮助 -对于任何命令,您可以传入 `--help` 标志以获取有关如何使用该命令的更多信息。 +对于任何命令,您可以传入 `--help` 标志来获取有关如何使用该命令的更多信息。 ```bash php runway routes --help @@ -33,7 +60,7 @@ php runway routes --help ### 生成控制器 -基于您的 `.runway.json` 文件中的配置,默认位置将在 `app/controllers/` 目录中为您生成控制器。 +基于 `runway.app_root` 中的配置,位置将在 `app/controllers/` 目录中为您生成控制器。 ```bash php runway make:controller MyController @@ -41,13 +68,13 @@ php runway make:controller MyController ### 生成 Active Record 模型 -基于您的 `.runway.json` 文件中的配置,默认位置将在 `app/records/` 目录中为您生成模型。 +首先确保您已安装 [Active Record](/awesome-plugins/active-record) 插件。基于 `runway.app_root` 中的配置,位置将在 `app/records/` 目录中为您生成记录。 ```bash php runway make:record users ``` -例如,如果您有 `users` 表,具有以下架构:`id`、`name`、`email`、`created_at`、`updated_at`,则将在 `app/records/UserRecord.php` 文件中创建类似以下的文件: +例如,如果您有名为 `users` 的表,架构如下:`id`、`name`、`email`、`created_at`、`updated_at`,则将在 `app/records/UserRecord.php` 文件中创建一个类似以下的文件: ```php $config JSON config from .runway-config.json + * @param array $config Config from app/config/config.php */ public function __construct(array $config) { @@ -151,43 +178,109 @@ class ExampleCommand extends AbstractBaseCommand } ``` -有关如何将自定义命令构建到 Flight 应用程序中的更多信息,请参阅 [adhocore/php-cli 文档](https://github.com/adhocore/php-cli)! +请参阅 [adhocore/php-cli 文档](https://github.com/adhocore/php-cli),了解如何为您的 Flight 应用程序构建自己的自定义命令的更多信息! + +## 配置管理 -### 配置 +由于从 `v1.2.0` 开始配置已移动到 `app/config/config.php`,因此有一些辅助命令来管理配置。 -如果需要自定义 Runway 的配置,可以在项目根目录创建一个 `.runway-config.json` 文件。以下是一些可以设置的附加配置: +### 迁移旧配置 -```js +如果您有旧的 `.runway-config.json` 文件,您可以使用以下命令轻松将其迁移到 `app/config/config.php`: + +```bash +php runway config:migrate +``` + +### 设置配置值 + +您可以使用 `config:set` 命令设置配置值。这在您想更新配置值而不打开文件时很有用。 + +```bash +php runway config:set app_root "app/" +``` + +### 获取配置值 + +您可以使用 `config:get` 命令获取配置值。 + +```bash +php runway config:get app_root +``` + +## 所有 Runway 配置 + +如果您需要自定义 Runway 的配置,您可以在 `app/config/config.php` 中设置这些值。以下是一些您可以设置的额外配置: + +```php + [ + // This is where your application directory is located + 'app_root' => 'app/', + + // This is the directory where your root index file is located + 'index_root' => 'public/', + + // These are the paths to the roots of other projects + 'root_paths' => [ + '/home/user/different-project', + '/var/www/another-project' + ], + + // Base paths most likely don't need to be configured, but it's here if you want it + 'base_paths' => [ + '/includes/libs/vendor', // if you have a really unique path for your vendor directory or something + ], + + // Final paths are locations within a project to search for the command files + 'final_paths' => [ + 'src/diff-path/commands', + 'app/module/admin/commands', + ], + + // If you want to just add the full path, go right ahead (absolute or relative to project root) + 'paths' => [ + '/home/user/different-project/src/diff-path/commands', + '/var/www/another-project/app/module/admin/commands', + 'app/my-unique-commands' + ] + ] +]; +``` + +### 访问配置 + +如果您需要有效地访问配置值,您可以通过 `__construct` 方法或 `app()` 方法访问它们。同样重要的是要注意,如果您有 `app/config/services.php` 文件,那些服务也将可用作您的命令。 + +```php +public function execute() { + $io = $this->app()->io(); + + // Access configuration + $app_root = $this->config['runway']['app_root']; + + // Access services like maybe a database connection + $database = $this->config['database'] + + // ... +} +``` + +## AI 助手包装器 + +Runway 有一些辅助包装器,使 AI 更容易生成命令。您可以使用 `addOption` 和 `addArgument`,方式类似于 Symfony Console。这在您使用 AI 工具生成命令时很有帮助。 - // This is where your application directory is located - "app_root": "app/", - - // This is the directory where your root index file is located - "index_root": "public/", - - // These are the paths to the roots of other projects - "root_paths": [ - "/home/user/different-project", - "/var/www/another-project" - ], - - // Base paths most likely don't need to be configured, but it's here if you want it - "base_paths": { - "/includes/libs/vendor", // if you have a really unique path for your vendor directory or something - }, - - // Final paths are locations within a project to search for the command files - "final_paths": { - "src/diff-path/commands", - "app/module/admin/commands", - }, - - // If you want to just add the full path, go right ahead (absolute or relative to project root) - "paths": [ - "/home/user/different-project/src/diff-path/commands", - "/var/www/another-project/app/module/admin/commands", - "app/my-unique-commands" - ] +```php +public function __construct(array $config) +{ + parent::__construct('make:example', 'Create an example for the documentation', $config); + + // The mode argument is nullable and defaults to completely optional + $this->addOption('name', 'The name of the example', null); } ``` \ No newline at end of file From f83d872f855174c0defe4f5fd7664397e70841e9 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Thu, 1 Jan 2026 11:49:34 -0700 Subject: [PATCH 28/36] added Translate Command to be more cool and official --- .gemini/GEMINI.md | 42 +++++++ app/commands/TranslateCommand.php | 193 ++++++++++++++++++++++++++++++ 2 files changed, 235 insertions(+) create mode 100644 .gemini/GEMINI.md create mode 100644 app/commands/TranslateCommand.php diff --git a/.gemini/GEMINI.md b/.gemini/GEMINI.md new file mode 100644 index 00000000..15760858 --- /dev/null +++ b/.gemini/GEMINI.md @@ -0,0 +1,42 @@ +# Copilot AI Coding Assistant Instructions for FlightPHP Docs + +Welcome to the FlightPHP Documentation Site! This project is the official documentation hub for the Flight PHP Framework. Please follow these guidelines when using AI coding assistants (like GitHub Copilot) to contribute to this repository. + +## Project Structure + +- **app/**: Contains the application logic for fetching, rendering, and displaying documentation content. This is a standard Flight PHP app, with customizations for documentation needs. +- **content/**: Holds all documentation content, organized by framework version (e.g., `v3/`). + - **content/v3/en/**: The *only* directory for direct documentation edits. All other language folders are generated via translation scripts and should not be manually edited. + - **content/v3/{lang}/**: Translated content for other languages. These are auto-generated and overwritten by scripts. +- **translate_content.php**: Script for translating English docs to other languages using an LLM API. Do not edit non-English docs directly. +- **public/**: Contains static assets and the main entry point (`index.php`). + +## Contribution Guidelines + +- **Add or update documentation only in `content/v3/en/`**. All other language folders are generated and will be overwritten. +- **When adding documentation, include practical, beginner-friendly examples**. Focus on helping new PHP developers understand the framework, but keep content useful for mid-level and senior devs too. +- **The tone should be casual, friendly, and fun**—like a good friend helping you learn. Avoid being overly silly or unprofessional. +- **This site is not a PHP tutorial**. Focus on Flight PHP concepts: framework basics, usage, scaling, best practices, and advanced features. +- **Do not edit translated files directly**. Use the translation script to update non-English docs. +- **Keep code and documentation clear and concise**. Favor real-world, copy-paste-ready examples. +- **If you add new features to the app logic, document them for future contributors.** +- **Check for existing examples before adding new ones** to avoid duplication. + +## AI Assistant Usage + +- When using AI assistants: + - Ensure all changes to documentation are made in English under `content/v3/en/`. + - For code changes, follow the existing structure and conventions in `app/`. + - Suggest practical, beginner-friendly examples for new docs. + - Maintain the project's friendly, approachable tone. + - Do not generate or suggest edits to translated files. + - If unsure about a translation or content structure, check the translation script or ask a maintainer. + +## Other Notes + +- The project uses standard Flight PHP conventions for routing and rendering. +- Static assets (CSS, JS, images) are in `public/`. +- The site is designed to be easy to run locally via php dev-server with `composer start` +- All contributions should be MIT licensed. + +Thank you for helping make FlightPHP docs awesome! diff --git a/app/commands/TranslateCommand.php b/app/commands/TranslateCommand.php new file mode 100644 index 00000000..e0130435 --- /dev/null +++ b/app/commands/TranslateCommand.php @@ -0,0 +1,193 @@ +option('--from-date', 'Skip files older than this date (YYYY-MM-DD)', null, 0) + ->option('--skip-files', 'Comma separated list of filenames to skip', null, '') + ->option('--dry-run', 'Run without making API calls or saving files', null, false); + } + + public function execute() { + $io = $this->app()->io(); + $chatgpt_key = $this->config['chatgpt_key'] ?? ''; + + if (empty($chatgpt_key)) { + // fallback to env if not in config + $chatgpt_key = getenv('CHATGPT_KEY'); + } + + if (empty($chatgpt_key) && !$this->dryRun) { + $io->error('You need to set the chatgpt_key in config or CHATGPT_KEY environment variable to run this script', true); + return; + } + + $fromDate = $this->fromDate; + if ($fromDate) { + $fromDate = strtotime($fromDate . ' 00:00:00'); + } + + $dryRun = $this->dryRun; + + $io->info("Translating content from " . date('Y-m-d', $fromDate ?: 0), true); + if ($dryRun) { + $io->warn('** DRY RUN MODE ** - No files will be modified.', true); + } + + $skipFilesInput = $this->skipFiles ?? ''; + $filenames_to_skip = array_filter(array_map('trim', explode(',', $skipFilesInput))); + + $languages = [ + 'es', + 'fr', + 'lv', + 'pt', + 'de', + 'ru', + 'zh', + 'ja', + 'ko', + 'uk', + 'id' + ]; + + $projectRoot = dirname(__DIR__, 2); + $top_level_files = glob($projectRoot . '/content/v3/en/*.md'); + $files = array_merge($top_level_files, glob($projectRoot . '/content/v3/en/**/*.md')); + + foreach ($files as $file) { + $io->bold("Processing " . basename($file), true); + + if (filemtime($file) < $fromDate) { + $io->comment(" Skipping file because it's older than the from-date", true); + continue; + } + + if (in_array(basename($file), $filenames_to_skip)) { + $io->comment(" Skipping file because it's in the skip list", true); + continue; + } + + foreach ($languages as $languageAbbreviation) { + $full_response = ''; + $messages = [ + [ + "role" => "system", + "content" => "You are a gifted translator focusing on the tech space. Today you are translating documentation for a PHP Framework called Flight (so please never translate the word 'Flight' as it's the name of the framework). You are going to receive content that is a markdown file. When you receive the content you'll translate it from english to the two letter language code that is specified. When you generate a response, you are going to ONLY send back the translated markdown content, no other replies or 'here is your translated markdown' type statements back, only the translated markdown content in markdown format. If you get a follow up response, you need to continue to markdown translation from the very character you left off at and complete the translation until the full page is done. THIS NEXT ITEM IS VERY IMPORTANT! Make sure that when you are translating any code in the markdown file that you ONLY translate the comments of the code and not the classes/methods/variables/links/urls/etc. This next part is also incredibly important or it will break the entire page!!!! Please don't translate any URLs or you will break my app and I will lose my job if this is not done correctly!!!!" + ], + [ + "role" => "user", + "content" => "Translate the following text from English to the two letter language code of {$languageAbbreviation}:\n\n" . file_get_contents($file) + ] + ]; + + if ($dryRun) { + $io->comment(" [DRY RUN] Would translate to {$languageAbbreviation}...", true); + continue; + } + + do { + $ch = curl_init('https://api.x.ai/v1/chat/completions'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_POST, true); + + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ + "model" => "grok-4-fast-non-reasoning", + "messages" => $messages + ])); + + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Authorization: Bearer ' . $chatgpt_key, + 'Content-Type: application/json' + ]); + + $response = curl_exec($ch); + curl_close($ch); + + $responseArr = json_decode($response, true); + + $content = $responseArr['choices'][0]['message']['content'] ?? ''; + + if (empty($content)) { + $io->error(" Skipping file because it received an empty response"); + break; + } + + $full_response .= $content; + + $messages[] = [ + 'role' => 'assistant', + 'content' => $content + ]; + } while (($responseArr['usage']['completion_tokens'] ?? 0) === 4096); + + // save the translated content to the appropriate file + $translatedFilePath = str_replace('/en/', '/' . $languageAbbreviation . '/', $file); + $directory = dirname($translatedFilePath); + + if (!is_dir($directory)) { + mkdir($directory, 0775, true); + } + + if (!$full_response) { + $io->error(" Skipping file because it's received an empty response", true); + continue; + } + + file_put_contents($translatedFilePath, $full_response); + $io->green(" Updated: " . $translatedFilePath, true); + } + } + + // Cleanup orphaned files + if (!$dryRun) { + $this->cleanupOrphanedFiles($files, $languages, $projectRoot, $io); + } else { + $io->comment("[DRY RUN] Skipping orphaned file cleanup check.", true); + } + } + + protected function cleanupOrphanedFiles(array $files, array $languages, string $projectRoot, $io) { + $enFiles = []; + foreach ($files as $file) { + $enFiles[] = ltrim(str_replace(realpath($projectRoot . '/content/v3/en/'), '', realpath($file)), '/\\'); + } + + foreach ($languages as $languageAbbreviation) { + $langDir = $projectRoot . "/content/v3/{$languageAbbreviation}/"; + if (!is_dir($langDir)) continue; + + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($langDir, RecursiveDirectoryIterator::SKIP_DOTS) + ); + + foreach ($iterator as $translatedFile) { + if ($translatedFile->getExtension() !== 'md') continue; + + $relativePath = ltrim(str_replace(realpath($langDir), '', $translatedFile->getRealPath()), '/\\'); + + if (!in_array($relativePath, $enFiles)) { + $io->error("Deleting orphaned file: {$translatedFile->getRealPath()}", true); + unlink($translatedFile->getRealPath()); + + $dir = dirname($translatedFile->getRealPath()); + while ($dir !== $langDir && is_dir($dir) && count(glob("$dir/*")) === 0) { + rmdir($dir); + $dir = dirname($dir); + } + } + } + } + } +} From 317d84ca23f7c69896fe47714dcec7f9e49bd9dd Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Thu, 1 Jan 2026 16:43:55 -0700 Subject: [PATCH 29/36] made translation multi threaded and added jwt docs --- app/commands/TranslateCommand.php | 220 ++++++-- .../v3/de/awesome-plugins/awesome_plugins.md | 52 +- content/v3/de/awesome-plugins/jwt.md | 532 ++++++++++++++++++ .../v3/en/awesome-plugins/awesome_plugins.md | 6 + content/v3/en/awesome-plugins/jwt.md | 532 ++++++++++++++++++ .../v3/es/awesome-plugins/awesome_plugins.md | 54 +- content/v3/es/awesome-plugins/jwt.md | 532 ++++++++++++++++++ .../v3/fr/awesome-plugins/awesome_plugins.md | 54 +- content/v3/fr/awesome-plugins/jwt.md | 532 ++++++++++++++++++ .../v3/id/awesome-plugins/awesome_plugins.md | 30 +- content/v3/id/awesome-plugins/jwt.md | 532 ++++++++++++++++++ .../v3/ja/awesome-plugins/awesome_plugins.md | 66 ++- content/v3/ja/awesome-plugins/jwt.md | 532 ++++++++++++++++++ .../v3/ko/awesome-plugins/awesome_plugins.md | 44 +- content/v3/ko/awesome-plugins/jwt.md | 532 ++++++++++++++++++ .../v3/lv/awesome-plugins/awesome_plugins.md | 54 +- content/v3/lv/awesome-plugins/jwt.md | 532 ++++++++++++++++++ .../v3/pt/awesome-plugins/awesome_plugins.md | 28 +- content/v3/pt/awesome-plugins/jwt.md | 532 ++++++++++++++++++ .../v3/ru/awesome-plugins/awesome_plugins.md | 66 ++- content/v3/ru/awesome-plugins/jwt.md | 532 ++++++++++++++++++ .../v3/uk/awesome-plugins/awesome_plugins.md | 70 +-- content/v3/uk/awesome-plugins/jwt.md | 532 ++++++++++++++++++ .../v3/zh/awesome-plugins/awesome_plugins.md | 58 +- content/v3/zh/awesome-plugins/jwt.md | 532 ++++++++++++++++++ 25 files changed, 6870 insertions(+), 316 deletions(-) create mode 100644 content/v3/de/awesome-plugins/jwt.md create mode 100644 content/v3/en/awesome-plugins/jwt.md create mode 100644 content/v3/es/awesome-plugins/jwt.md create mode 100644 content/v3/fr/awesome-plugins/jwt.md create mode 100644 content/v3/id/awesome-plugins/jwt.md create mode 100644 content/v3/ja/awesome-plugins/jwt.md create mode 100644 content/v3/ko/awesome-plugins/jwt.md create mode 100644 content/v3/lv/awesome-plugins/jwt.md create mode 100644 content/v3/pt/awesome-plugins/jwt.md create mode 100644 content/v3/ru/awesome-plugins/jwt.md create mode 100644 content/v3/uk/awesome-plugins/jwt.md create mode 100644 content/v3/zh/awesome-plugins/jwt.md diff --git a/app/commands/TranslateCommand.php b/app/commands/TranslateCommand.php index e0130435..3492b6ff 100644 --- a/app/commands/TranslateCommand.php +++ b/app/commands/TranslateCommand.php @@ -10,13 +10,15 @@ * @property-read string $fromDate * @property-read string $skipFiles * @property-read bool $dryRun + * @property-read int $threads */ class TranslateCommand extends AbstractBaseCommand { public function __construct(array $config = []) { parent::__construct('app:translate', 'Translate markdown documentation files to other languages.', $config); $this->option('--from-date', 'Skip files older than this date (YYYY-MM-DD)', null, 0) ->option('--skip-files', 'Comma separated list of filenames to skip', null, '') - ->option('--dry-run', 'Run without making API calls or saving files', null, false); + ->option('--dry-run', 'Run without making API calls or saving files', null, false) + ->option('--threads', 'Number of concurrent translation requests', null, 5); } public function execute() { @@ -66,96 +68,192 @@ public function execute() { $top_level_files = glob($projectRoot . '/content/v3/en/*.md'); $files = array_merge($top_level_files, glob($projectRoot . '/content/v3/en/**/*.md')); + // Build queue of translation jobs + $translationJobs = []; foreach ($files as $file) { - $io->bold("Processing " . basename($file), true); - - if (filemtime($file) < $fromDate) { - $io->comment(" Skipping file because it's older than the from-date", true); + if ($fromDate && filemtime($file) < $fromDate) { + $io->comment("Skipping " . basename($file) . " because it's older than the from-date", true); continue; } if (in_array(basename($file), $filenames_to_skip)) { - $io->comment(" Skipping file because it's in the skip list", true); + $io->comment("Skipping " . basename($file) . " because it's in the skip list", true); continue; } foreach ($languages as $languageAbbreviation) { - $full_response = ''; - $messages = [ - [ - "role" => "system", - "content" => "You are a gifted translator focusing on the tech space. Today you are translating documentation for a PHP Framework called Flight (so please never translate the word 'Flight' as it's the name of the framework). You are going to receive content that is a markdown file. When you receive the content you'll translate it from english to the two letter language code that is specified. When you generate a response, you are going to ONLY send back the translated markdown content, no other replies or 'here is your translated markdown' type statements back, only the translated markdown content in markdown format. If you get a follow up response, you need to continue to markdown translation from the very character you left off at and complete the translation until the full page is done. THIS NEXT ITEM IS VERY IMPORTANT! Make sure that when you are translating any code in the markdown file that you ONLY translate the comments of the code and not the classes/methods/variables/links/urls/etc. This next part is also incredibly important or it will break the entire page!!!! Please don't translate any URLs or you will break my app and I will lose my job if this is not done correctly!!!!" - ], - [ - "role" => "user", - "content" => "Translate the following text from English to the two letter language code of {$languageAbbreviation}:\n\n" . file_get_contents($file) - ] + $translationJobs[] = [ + 'file' => $file, + 'language' => $languageAbbreviation, + 'translatedFilePath' => str_replace('/en/', '/' . $languageAbbreviation . '/', $file) ]; + } + } - if ($dryRun) { - $io->comment(" [DRY RUN] Would translate to {$languageAbbreviation}...", true); - continue; - } + if (empty($translationJobs)) { + $io->info('No files to translate.', true); + return; + } - do { - $ch = curl_init('https://api.x.ai/v1/chat/completions'); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_POST, true); + $io->info("Total translation jobs: " . count($translationJobs), true); - curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ - "model" => "grok-4-fast-non-reasoning", - "messages" => $messages - ])); + if ($dryRun) { + foreach ($translationJobs as $job) { + $io->comment(" [DRY RUN] Would translate " . basename($job['file']) . " to {$job['language']}", true); + } + return; + } + + // Process jobs in batches based on thread count + $maxThreads = (int)$this->threads; + $totalJobs = count($translationJobs); + $processedJobs = 0; - curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Authorization: Bearer ' . $chatgpt_key, - 'Content-Type: application/json' - ]); + while ($processedJobs < $totalJobs) { + $batch = array_slice($translationJobs, $processedJobs, $maxThreads); + $this->processBatch($batch, $chatgpt_key, $io); + $processedJobs += count($batch); + $io->info("Progress: {$processedJobs}/{$totalJobs} translations completed", true); + } - $response = curl_exec($ch); - curl_close($ch); + // Cleanup orphaned files + if (!$dryRun) { + $this->cleanupOrphanedFiles($files, $languages, $projectRoot, $io); + } else { + $io->comment("[DRY RUN] Skipping orphaned file cleanup check.", true); + } + } - $responseArr = json_decode($response, true); + /** + * Process a batch of translation jobs concurrently using curl_multi + */ + protected function processBatch(array $batch, string $apiKey, $io) { + $mh = curl_multi_init(); + $handles = []; + $jobData = []; + + // Initialize all curl handles for the batch + foreach ($batch as $index => $job) { + $fileContent = file_get_contents($job['file']); + $messages = [ + [ + "role" => "system", + "content" => "You are a gifted translator focusing on the tech space. Today you are translating documentation for a PHP Framework called Flight (so please never translate the word 'Flight' as it's the name of the framework). You are going to receive content that is a markdown file. When you receive the content you'll translate it from english to the two letter language code that is specified. When you generate a response, you are going to ONLY send back the translated markdown content, no other replies or 'here is your translated markdown' type statements back, only the translated markdown content in markdown format. If you get a follow up response, you need to continue to markdown translation from the very character you left off at and complete the translation until the full page is done. THIS NEXT ITEM IS VERY IMPORTANT! Make sure that when you are translating any code in the markdown file that you ONLY translate the comments of the code and not the classes/methods/variables/links/urls/etc. This next part is also incredibly important or it will break the entire page!!!! Please don't translate any URLs or you will break my app and I will lose my job if this is not done correctly!!!!" + ], + [ + "role" => "user", + "content" => "Translate the following text from English to the two letter language code of {$job['language']}:\n\n{$fileContent}" + ] + ]; + + $ch = $this->createCurlHandle($apiKey, $messages); + curl_multi_add_handle($mh, $ch); + + $handles[(int)$ch] = $ch; + $jobData[(int)$ch] = [ + 'job' => $job, + 'messages' => $messages, + 'full_response' => '', + 'needs_continuation' => false + ]; + } - $content = $responseArr['choices'][0]['message']['content'] ?? ''; + // Execute all handles + $active = null; + do { + $status = curl_multi_exec($mh, $active); + if ($active) { + curl_multi_select($mh); + } + } while ($active && $status == CURLM_OK); - if (empty($content)) { - $io->error(" Skipping file because it received an empty response"); - break; - } + // Collect results and check for continuation needs + foreach ($handles as $handleId => $ch) { + $response = curl_multi_getcontent($ch); + $responseArr = json_decode($response, true); - $full_response .= $content; + $content = $responseArr['choices'][0]['message']['content'] ?? ''; - $messages[] = [ - 'role' => 'assistant', - 'content' => $content - ]; - } while (($responseArr['usage']['completion_tokens'] ?? 0) === 4096); + if (!empty($content)) { + $jobData[$handleId]['full_response'] .= $content; + $jobData[$handleId]['messages'][] = [ + 'role' => 'assistant', + 'content' => $content + ]; - // save the translated content to the appropriate file - $translatedFilePath = str_replace('/en/', '/' . $languageAbbreviation . '/', $file); + // Check if we need continuation (response was truncated) + if (($responseArr['usage']['completion_tokens'] ?? 0) === 4096) { + $jobData[$handleId]['needs_continuation'] = true; + } + } else { + $io->error("Empty response for " . basename($jobData[$handleId]['job']['file']) . " ({$jobData[$handleId]['job']['language']})", true); + } + + curl_multi_remove_handle($mh, $ch); + curl_close($ch); + } + + curl_multi_close($mh); + + // Handle continuation requests for jobs that need them + foreach ($jobData as $data) { + while ($data['needs_continuation']) { + $io->comment(" Continuing translation for " . basename($data['job']['file']) . " ({$data['job']['language']})...", true); + + $ch = $this->createCurlHandle($apiKey, $data['messages']); + $response = curl_exec($ch); + curl_close($ch); + + $responseArr = json_decode($response, true); + $content = $responseArr['choices'][0]['message']['content'] ?? ''; + + if (empty($content)) { + $io->error("Empty continuation response for " . basename($data['job']['file']), true); + break; + } + + $data['full_response'] .= $content; + $data['messages'][] = [ + 'role' => 'assistant', + 'content' => $content + ]; + + // Check if we still need continuation + $data['needs_continuation'] = ($responseArr['usage']['completion_tokens'] ?? 0) === 4096; + } + + // Save the translated content + if (!empty($data['full_response'])) { + $translatedFilePath = $data['job']['translatedFilePath']; $directory = dirname($translatedFilePath); if (!is_dir($directory)) { mkdir($directory, 0775, true); } - if (!$full_response) { - $io->error(" Skipping file because it's received an empty response", true); - continue; - } - - file_put_contents($translatedFilePath, $full_response); - $io->green(" Updated: " . $translatedFilePath, true); + file_put_contents($translatedFilePath, $data['full_response']); + $io->green(" Translated: " . basename($data['job']['file']) . " -> {$data['job']['language']}", true); } } + } - // Cleanup orphaned files - if (!$dryRun) { - $this->cleanupOrphanedFiles($files, $languages, $projectRoot, $io); - } else { - $io->comment("[DRY RUN] Skipping orphaned file cleanup check.", true); - } + /** + * Create a configured curl handle for the API request + */ + protected function createCurlHandle(string $apiKey, array $messages) { + $ch = curl_init('https://api.x.ai/v1/chat/completions'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ + "model" => "grok-4-fast-non-reasoning", + "messages" => $messages + ])); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Authorization: Bearer ' . $apiKey, + 'Content-Type: application/json' + ]); + + return $ch; } protected function cleanupOrphanedFiles(array $files, array $languages, string $projectRoot, $io) { diff --git a/content/v3/de/awesome-plugins/awesome_plugins.md b/content/v3/de/awesome-plugins/awesome_plugins.md index 993587b4..20b0aadd 100644 --- a/content/v3/de/awesome-plugins/awesome_plugins.md +++ b/content/v3/de/awesome-plugins/awesome_plugins.md @@ -1,12 +1,12 @@ -# Awesome Plugins +# Tolle 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, und andere sind Micro/Lite-Bibliotheken, um Ihnen den Einstieg zu erleichtern. +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 und andere sind Micro/Lite-Bibliotheken, um Ihnen den Einstieg zu erleichtern. ## API-Dokumentation API-Dokumentation ist entscheidend für jede API. Sie hilft Entwicklern zu verstehen, wie sie mit Ihrer API interagieren können und was sie als Rückgabe erwarten können. Es gibt ein paar Tools, die Ihnen helfen, API-Dokumentation für Ihre Flight-Projekte zu generieren. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Blogbeitrag von Daniel Schreiber darüber, wie man die OpenAPI-Spezifikation mit FlightPHP verwendet, um Ihre API mit einem API-First-Ansatz aufzubauen. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Blog-Beitrag von Daniel Schreiber darüber, wie man die OpenAPI-Spezifikation mit FlightPHP verwendet, um Ihre API mit einem API-First-Ansatz aufzubauen. - [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ist ein großartiges Tool, um API-Dokumentation für Ihre Flight-Projekte zu generieren. Es ist sehr einfach zu bedienen und kann an Ihre Bedürfnisse angepasst werden. Dies ist die PHP-Bibliothek, die Ihnen hilft, die Swagger-Dokumentation zu generieren. ## Application Performance Monitoring (APM) @@ -16,21 +16,27 @@ Application Performance Monitoring (APM) ist entscheidend für jede Anwendung. E ## Async -Flight ist bereits ein schnelles Framework, aber es mit einem Turbolader auszustatten macht alles noch spaßiger (und herausfordernder)! +Flight ist bereits ein schnelles Framework, aber es mit einem Turbo-Motor auszustatten macht alles noch spaßiger (und herausfordernder)! - [flightphp/async](/awesome-plugins/async) - Offizielle Flight Async-Bibliothek. Diese Bibliothek ist eine einfache Möglichkeit, asynchrone Verarbeitung zu Ihrer Anwendung hinzuzufügen. Sie verwendet Swoole/Openswoole im Hintergrund, um eine einfache und effektive Möglichkeit zu bieten, Aufgaben asynchron auszuführen. -## Authorization/Permissions +## Autorisierung/Berechtigungen -Autorisierung und Berechtigungen sind entscheidend für jede Anwendung, die Steuerelemente für den Zugriff auf bestimmte Inhalte erfordert. +Autorisierung und Berechtigungen sind entscheidend für jede Anwendung, die Steuerelemente benötigt, um festzulegen, wer auf was zugreifen kann. -- offiziell [flightphp/permissions](/awesome-plugins/permissions) - Offizielle Flight Permissions-Bibliothek. Diese Bibliothek ist eine einfache Möglichkeit, Benutzer- und Anwendungsebene-Berechtigungen zu Ihrer Anwendung hinzuzufügen. +- offiziell [flightphp/permissions](/awesome-plugins/permissions) - Offizielle Flight Permissions-Bibliothek. Diese Bibliothek ist eine einfache Möglichkeit, Benutzer- und Anwendungsebenen-Berechtigungen zu Ihrer Anwendung hinzuzufügen. + +## Authentifizierung + +Authentifizierung ist essenziell für Anwendungen, die die Benutzeridentität überprüfen und API-Endpunkte sichern müssen. + +- [firebase/php-jwt](/awesome-plugins/jwt) - JSON Web Token (JWT)-Bibliothek für PHP. Eine einfache und sichere Möglichkeit, tokenbasierte Authentifizierung in Ihren Flight-Anwendungen zu implementieren. Perfekt für stateless API-Authentifizierung, Schutz von Routen mit Middleware und Implementierung von OAuth-ähnlichen Autorisierungsflüssen. ## Caching Caching ist eine großartige Möglichkeit, Ihre Anwendung zu beschleunigen. Es gibt eine Reihe von Caching-Bibliotheken, die mit Flight verwendet werden können. -- offiziell [flightphp/cache](/awesome-plugins/php-file-cache) - Leichte, einfache und eigenständige PHP-in-File-Caching-Klasse +- offiziell [flightphp/cache](/awesome-plugins/php-file-cache) - Leichte, einfache und eigenständige PHP-In-Datei-Caching-Klasse ## CLI @@ -40,7 +46,7 @@ CLI-Anwendungen sind eine großartige Möglichkeit, mit Ihrer Anwendung zu inter ## Cookies -Cookies sind eine großartige Möglichkeit, kleine Datenmengen auf der Client-Seite zu speichern. Sie können verwendet werden, um Benutzerpräferenzen, Anwendungseinstellungen und mehr zu speichern. +Cookies sind eine großartige Möglichkeit, kleine Datenmengen auf der Client-Seite zu speichern. Sie können verwendet werden, um Benutzereinstellungen, Anwendungseinstellungen und mehr zu speichern. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie ist eine PHP-Bibliothek, die eine einfache und effektive Möglichkeit bietet, Cookies zu verwalten. @@ -48,50 +54,50 @@ Cookies sind eine großartige Möglichkeit, kleine Datenmengen auf der Client-Se Debugging ist entscheidend, wenn Sie in Ihrer lokalen Umgebung entwickeln. Es gibt ein paar Plugins, die Ihr Debugging-Erlebnis verbessern können. -- [tracy/tracy](/awesome-plugins/tracy) - Dies ist ein vollständiges Fehlerbehandlungstool, das mit Flight verwendet werden kann. Es verfügt über eine Reihe von Panels, die Ihnen helfen können, Ihre Anwendung zu debuggen. Es ist auch sehr einfach zu erweitern und eigene Panels hinzuzufügen. -- offiziell [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - In Verbindung mit dem [Tracy](/awesome-plugins/tracy) Fehlerbehandlungstool fügt dieses Plugin ein paar zusätzliche Panels hinzu, um das Debugging speziell für Flight-Projekte zu erleichtern. +- [tracy/tracy](/awesome-plugins/tracy) - Dies ist ein vollständiges Fehlerbehandlungs-Tool, das mit Flight verwendet werden kann. Es hat eine Reihe von Panels, die Ihnen helfen können, Ihre Anwendung zu debuggen. Es ist auch sehr einfach zu erweitern und eigene Panels hinzuzufügen. +- offiziell [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Wird mit dem [Tracy](/awesome-plugins/tracy) Fehlerbehandlungs-Tool verwendet, fügt dieses Plugin ein paar zusätzliche Panels hinzu, um das Debugging speziell für Flight-Projekte zu erleichtern. -## Databases +## Datenbanken Datenbanken sind der Kern der meisten Anwendungen. So speichern und rufen Sie Daten ab. Einige Datenbank-Bibliotheken sind einfach Wrapper, um Abfragen zu schreiben, und einige sind vollwertige ORMs. -- offiziell [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Offizieller Flight PDO-Wrapper, der zum Kern gehört. Dies ist ein einfacher Wrapper, der den Prozess des Schreibens und Ausführens von Abfragen vereinfacht. Es handelt sich nicht um ein ORM. +- offiziell [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Offizieller Flight PDO-Wrapper, der zum Kern gehört. Dies ist ein einfacher Wrapper, der hilft, den Prozess des Schreibens und Ausführens von Abfragen zu vereinfachen. Es handelt sich nicht um ein ORM. - offiziell [flightphp/active-record](/awesome-plugins/active-record) - Offizielles Flight ActiveRecord ORM/Mapper. Tolle kleine Bibliothek, um Daten einfach in Ihrer Datenbank abzurufen und zu speichern. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin, um alle Datenbankänderungen für Ihr Projekt zu verfolgen. -## Encryption +## Verschlüsselung -Verschlüsselung ist entscheidend für jede Anwendung, die sensible Daten speichert. Das Verschlüsseln und Entschlüsseln der Daten ist nicht allzu schwer, aber das ordnungsgemäße Speichern des Verschlüsselungsschlüssels [kann](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [sein](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [schwierig](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Das Wichtigste ist, Ihren Verschlüsselungsschlüssel niemals in einem öffentlichen Verzeichnis zu speichern oder ihn in Ihr Code-Repository zu committen. +Verschlüsselung ist entscheidend für jede Anwendung, die sensible Daten speichert. Das Verschlüsseln und Entschlüsseln der Daten ist nicht besonders schwierig, aber das ordnungsgemäße Speichern des Verschlüsselungsschlüssels [kann](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [sein](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [schwierig](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Das Wichtigste ist, Ihren Verschlüsselungsschlüssel nie in einem öffentlichen Verzeichnis zu speichern oder ihn in Ihr Code-Repository zu committen. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Dies ist eine Bibliothek, die verwendet werden kann, um Daten zu verschlüsseln und zu entschlüsseln. Der Einstieg ist ziemlich einfach, um mit dem Verschlüsseln und Entschlüsseln von Daten zu beginnen. ## Job Queue -Job-Warteschlangen sind wirklich hilfreich, um Aufgaben asynchron zu verarbeiten. Dies kann das Senden von E-Mails, das Verarbeiten von Bildern oder alles sein, was nicht in Echtzeit erledigt werden muss. +Job-Warteschlangen sind wirklich hilfreich, um Aufgaben asynchron zu verarbeiten. Das kann das Senden von E-Mails, die Verarbeitung von Bildern oder alles sein, was nicht in Echtzeit erledigt werden muss. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue ist eine Bibliothek, die verwendet werden kann, um Jobs asynchron zu verarbeiten. Sie kann mit beanstalkd, MySQL/MariaDB, SQLite und PostgreSQL verwendet werden. ## Session -Sitzungen sind für APIs nicht wirklich nützlich, aber beim Aufbau einer Web-Anwendung können Sitzungen entscheidend für die Aufrechterhaltung des Zustands und Login-Informationen sein. +Sessions sind für APIs nicht wirklich nützlich, aber beim Aufbau einer Web-Anwendung können Sessions entscheidend sein, um Zustände und Login-Informationen aufrechtzuerhalten. - offiziell [flightphp/session](/awesome-plugins/session) - Offizielle Flight Session-Bibliothek. Dies ist eine einfache Session-Bibliothek, die verwendet werden kann, um Session-Daten zu speichern und abzurufen. Sie verwendet die integrierte Session-Behandlung von PHP. - [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session-Manager (nicht-blockierend, Flash, Segment, Session-Verschlüsselung). Verwendet PHP open_ssl für optionale Verschlüsselung/Entschlüsselung von Session-Daten. ## Templating -Templating ist der Kern jeder Web-Anwendung mit einer Benutzeroberfläche. Es gibt eine Reihe von Templating-Engines, die mit Flight verwendet werden können. +Templating ist der Kern jeder Web-Anwendung mit einer UI. Es gibt eine Reihe von Templating-Engines, die mit Flight verwendet werden können. -- deprecated [flightphp/core View](/learn#views) - Dies ist eine sehr grundlegende Templating-Engine, die zum Kern gehört. Es wird nicht empfohlen, sie zu verwenden, wenn Ihr Projekt mehr als ein paar Seiten hat. -- [latte/latte](/awesome-plugins/latte) - Latte ist eine vollständige Templating-Engine, die sehr einfach zu bedienen ist und sich näher an der PHP-Syntax anfühlt als Twig oder Smarty. Sie ist auch sehr einfach zu erweitern und eigene Filter und Funktionen hinzuzufügen. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate ist eine leistungsstarke PHP-Template-Engine mit Asset-Kompilierung, Template-Vererbung und Variablenverarbeitung. Bietet automatische CSS/JS-Minifizierung, Caching, Base64-Codierung und optionale Integration mit dem Flight PHP-Framework. +- veraltet [flightphp/core View](/learn#views) - Dies ist eine sehr grundlegende Templating-Engine, die zum Kern gehört. Es wird nicht empfohlen, sie zu verwenden, wenn Sie mehr als ein paar Seiten in Ihrem Projekt haben. +- [latte/latte](/awesome-plugins/latte) - Latte ist eine vollständige Templating-Engine, die sehr einfach zu bedienen ist und näher an der PHP-Syntax liegt als Twig oder Smarty. Sie ist auch sehr einfach zu erweitern und eigene Filter und Funktionen hinzuzufügen. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate ist ein leistungsstarkes PHP-Template-Engine mit Asset-Kompilierung, Template-Vererbung und Variablenverarbeitung. Features automatisierte CSS/JS-Minifizierung, Caching, Base64-Codierung und optionale Integration mit dem Flight PHP-Framework. -## WordPress Integration +## WordPress-Integration Möchten Sie Flight in Ihrem WordPress-Projekt verwenden? Es gibt ein praktisches Plugin dafür! - [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Dieses WordPress-Plugin ermöglicht es Ihnen, Flight direkt neben WordPress auszuführen. Es ist perfekt, um benutzerdefinierte APIs, Microservices oder sogar vollständige Apps zu Ihrer WordPress-Site mit dem Flight-Framework hinzuzufügen. Super nützlich, wenn Sie das Beste aus beiden Welten wollen! -## Contributing +## Mitwirkung Haben Sie ein Plugin, das Sie teilen möchten? Reichen Sie einen Pull Request ein, um es zur Liste hinzuzufügen! \ No newline at end of file diff --git a/content/v3/de/awesome-plugins/jwt.md b/content/v3/de/awesome-plugins/jwt.md new file mode 100644 index 00000000..08e81939 --- /dev/null +++ b/content/v3/de/awesome-plugins/jwt.md @@ -0,0 +1,532 @@ +# Firebase JWT - JSON Web Token Authentifizierung für Flight + +JWT (JSON Web Tokens) sind eine kompakte, URL-sichere Methode, um Ansprüche zwischen Ihrer Anwendung und einem Client darzustellen. Sie eignen sich perfekt für stateless API-Authentifizierung – kein Bedarf an serverseitiger Sitzungsspeicherung! Diese Anleitung zeigt Ihnen, wie Sie [Firebase JWT](https://github.com/firebase/php-jwt) mit Flight für sichere, tokenbasierte Authentifizierung integrieren. + +Besuchen Sie das [Github-Repository](https://github.com/firebase/php-jwt) für die vollständige Dokumentation und Details. + +## Was ist JWT? + +Ein JSON Web Token ist eine Zeichenkette, die aus drei Teilen besteht: +1. **Header**: Metadaten über das Token (Algorithmus, Typ) +2. **Payload**: Ihre Daten (Benutzer-ID, Rollen, Ablauf usw.) +3. **Signature**: Kryptografische Signatur zur Überprüfung der Authentizität + +Beispiel-JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (sieht aus wie Kauderwelsch, ist aber strukturierte Daten!) + +### Warum JWT verwenden? + +- **Stateless**: Keine serverseitige Sitzungsspeicherung erforderlich – perfekt für Microservices und APIs +- **Skalierbar**: Funktioniert hervorragend mit Load Balancern, da keine Sitzungsaffinität erforderlich ist +- **Cross-Domain**: Kann über verschiedene Domains und Dienste hinweg verwendet werden +- **Mobile-freundlich**: Ideal für Mobile-Apps, wo Cookies möglicherweise nicht gut funktionieren +- **Standardisiert**: Branchenstandard-Ansatz (RFC 7519) + +## Installation + +Installieren Sie es über Composer: + +```bash +composer require firebase/php-jwt +``` + +## Grundlegende Verwendung + +Hier ist ein schnelles Beispiel für die Erstellung und Überprüfung eines JWT: + +```php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; + +// Ihr geheimer Schlüssel (HALTEN SIE DAS SICHER!) +$secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; + +// Erstellen eines Tokens +$payload = [ + 'user_id' => 123, + 'username' => 'johndoe', + 'role' => 'admin', + 'iat' => time(), // Issued at + 'exp' => time() + 3600 // Läuft in 1 Stunde ab +]; + +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +echo "Token: " . $jwt; + +// Überprüfen und Dekodieren eines Tokens +try { + $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + echo "User ID: " . $decoded->user_id; +} catch (Exception $e) { + echo "Ungültiges Token: " . $e->getMessage(); +} +``` + +## JWT-Middleware für Flight (Empfohlener Ansatz) + +Der gängigste und nützlichste Weg, JWT mit Flight zu verwenden, ist als **Middleware**, um Ihre API-Routen zu schützen. Hier ist ein vollständiges, produktionsreifes Beispiel: + +### Schritt 1: Erstellen einer JWT-Middleware-Klasse + +```php +// app/middleware/JwtMiddleware.php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; +use Firebase\JWT\ExpiredException; +use Firebase\JWT\SignatureInvalidException; +use flight\Engine; + +class JwtMiddleware { + + protected Engine $app; + protected string $secretKey; + + public function __construct(Engine $app) { + $this->app = $app; + // Speichern Sie Ihren geheimen Schlüssel in app/config/config.php, NICHT hartcodiert! + $this->secretKey = $app->get('config')['jwt_secret']; + } + + public function before(array $params) { + $authHeader = $this->app->request()->getHeader('Authorization'); + + // Überprüfen, ob der Authorization-Header vorhanden ist + if (empty($authHeader)) { + $this->app->jsonHalt(['error' => 'Kein Autorisierungstoken bereitgestellt'], 401); + } + + // Token aus dem "Bearer "-Format extrahieren + if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { + $this->app->jsonHalt(['error' => 'Ungültiges Autorisierungsformat. Verwenden Sie: Bearer '], 401); + } + + $jwt = $matches[1]; + + try { + // Das Token dekodieren und überprüfen + $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); + + // Benutzerdaten in der Anfrage für die Verwendung in Routen-Handlern speichern + $this->app->request()->data->user = $decoded; + + } catch (ExpiredException $e) { + $this->app->jsonHalt(['error' => 'Token ist abgelaufen'], 401); + } catch (SignatureInvalidException $e) { + $this->app->jsonHalt(['error' => 'Ungültige Token-Signatur'], 401); + } catch (Exception $e) { + $this->app->jsonHalt(['error' => 'Ungültiges Token: ' . $e->getMessage()], 401); + } + } +} +``` + +### Schritt 2: JWT-Geheimnis in Ihrer Konfiguration registrieren + +```php +// app/config/config.php +return [ + 'jwt_secret' => getenv('JWT_SECRET') ?: 'your-fallback-secret-for-development' +]; + +// app/config/bootstrap.php oder index.php +// Stellen Sie sicher, dass Sie diese Zeile hinzufügen, wenn Sie die Konfiguration der App zugänglich machen möchten +$app->set('config', $config); +``` + +> **Sicherheitshinweis**: Kodieren Sie Ihren geheimen Schlüssel niemals hart! Verwenden Sie Umgebungsvariablen in der Produktion. + +### Schritt 3: Ihre Routen mit Middleware schützen + +```php +// Eine einzelne Route schützen +Flight::route('GET /api/user/profile', function() { + $user = Flight::request()->data->user; // Von Middleware gesetzt + Flight::json([ + 'user_id' => $user->user_id, + 'username' => $user->username, + 'role' => $user->role + ]); +})->addMiddleware( JwtMiddleware::class); + +// Eine gesamte Gruppe von Routen schützen (häufiger!) +Flight::group('/api', function() { + Flight::route('GET /users', function() { /* ... */ }); + Flight::route('GET /posts', function() { /* ... */ }); + Flight::route('POST /posts', function() { /* ... */ }); + Flight::route('DELETE /posts/@id', function($id) { /* ... */ }); +}, [ JwtMiddleware::class ]); // Alle Routen in dieser Gruppe sind geschützt! +``` + +Für weitere Details zu Middleware siehe die [Middleware-Dokumentation](/learn/middleware). + +## Häufige Anwendungsfälle + +### 1. Login-Endpunkt (Token-Generierung) + +Erstellen Sie eine Route, die nach erfolgreicher Authentifizierung ein JWT generiert: + +```php +Flight::route('POST /api/login', function() { + $data = Flight::request()->data; + $username = $data->username ?? ''; + $password = $data->password ?? ''; + + // Anmeldeinformationen validieren (Beispiel – verwenden Sie Ihre eigene Logik!) + $user = validateUserCredentials($username, $password); + + if (!$user) { + Flight::jsonHalt(['error' => 'Ungültige Anmeldeinformationen'], 401); + } + + // JWT generieren + $secretKey = Flight::get('config')['jwt_secret']; + $payload = [ + 'user_id' => $user->id, + 'username' => $user->username, + 'role' => $user->role, + 'iat' => time(), + 'exp' => time() + (60 * 60) // 1 Stunde Ablauf + ]; + + $jwt = JWT::encode($payload, $secretKey, 'HS256'); + + Flight::json([ + 'success' => true, + 'token' => $jwt, + 'expires_in' => 3600 + ]); +}); + +function validateUserCredentials($username, $password) { + // Ihre Datenbankabfrage und Passwortüberprüfung hier + // Beispiel: + $db = Flight::db(); + $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); + + if ($user && password_verify($password, $user['password_hash'])) { + return (object) [ + 'id' => $user['id'], + 'username' => $user['username'], + 'role' => $user['role'] + ]; + } + return null; +} +``` + +### 2. Token-Refresh-Flow + +Implementieren Sie ein Refresh-Token-System für langfristige Sitzungen: + +```php +Flight::route('POST /api/login', function() { + // ... Anmeldeinformationen validieren ... + + $secretKey = Flight::get('config')['jwt_secret']; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + // Kurzlebiges Access-Token (15 Minuten) + $accessToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + // Langlebiges Refresh-Token (7 Tage) + $refreshToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'refresh', + 'iat' => time(), + 'exp' => time() + (7 * 24 * 60 * 60) + ], $refreshSecret, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'refresh_token' => $refreshToken, + 'expires_in' => 900 + ]); +}); + +Flight::route('POST /api/refresh', function() { + $refreshToken = Flight::request()->data->refresh_token ?? ''; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + try { + $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); + + // Überprüfen, ob es sich um ein Refresh-Token handelt + if ($decoded->type !== 'refresh') { + Flight::jsonHalt(['error' => 'Ungültiger Token-Typ'], 401); + } + + // Neues Access-Token generieren + $secretKey = Flight::get('config')['jwt_secret']; + $accessToken = JWT::encode([ + 'user_id' => $decoded->user_id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'expires_in' => 900 + ]); + + } catch (Exception $e) { + Flight::jsonHalt(['error' => 'Ungültiges Refresh-Token'], 401); + } +}); +``` + +### 3. Rollengestützte Zugriffssteuerung + +Erweitern Sie Ihre Middleware, um Benutzerrollen zu überprüfen: + +```php +class JwtRoleMiddleware { + + protected Engine $app; + protected array $allowedRoles; + + public function __construct(Engine $app, array $allowedRoles = []) { + $this->app = $app; + $this->allowedRoles = $allowedRoles; + } + + public function before(array $params) { + // Annahme: JwtMiddleware hat bereits ausgeführt und Benutzerdaten gesetzt + $user = $this->app->request()->data->user ?? null; + + if (!$user) { + $this->app->jsonHalt(['error' => 'Authentifizierung erforderlich'], 401); + } + + // Überprüfen, ob der Benutzer die erforderliche Rolle hat + if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { + $this->app->jsonHalt(['error' => 'Unzureichende Berechtigungen'], 403); + } + } +} + +// Verwendung: Nur-Admin-Route +Flight::route('DELETE /api/users/@id', function($id) { + // Benutzer löschen Logik +})->addMiddleware([ + JwtMiddleware::class, + new JwtRoleMiddleware(Flight::app(), ['admin']) +]); +``` + +### 4. Öffentliche API mit Rate Limiting pro Benutzer + +Verwenden Sie JWT, um Benutzer ohne Sitzungen zu verfolgen und zu rate-limitieren: + +```php +class RateLimitMiddleware { + + public function before(array $params) { + $user = Flight::request()->data->user ?? null; + $userId = $user ? $user->user_id : Flight::request()->ip; + + $cacheKey = "rate_limit:$userId"; + // Stellen Sie sicher, dass Sie einen Cache-Dienst in app/config/services.php einrichten + $requests = Flight::cache()->get($cacheKey, 0); + + if ($requests >= 100) { // 100 Anfragen pro Stunde + Flight::jsonHalt(['error' => 'Rate Limit überschritten'], 429); + } + + Flight::cache()->set($cacheKey, $requests + 1, 3600); + } +} +``` + +## Best Practices für Sicherheit + +### 1. Starke geheime Schlüssel verwenden + +```php +// Einen sicheren geheimen Schlüssel generieren (einmal ausführen, in .env-Datei speichern) +$secretKey = base64_encode(random_bytes(32)); +echo $secretKey; // Speichern Sie das in Ihrer .env-Datei! +``` + +### 2. Geheimnisse in Umgebungsvariablen speichern + +```php +// Geheimnisse niemals in die Versionskontrolle committen! +// Verwenden Sie eine .env-Datei und eine Bibliothek wie vlucas/phpdotenv + +// .env-Datei: +// JWT_SECRET=your-base64-encoded-secret-here +// JWT_REFRESH_SECRET=another-base64-encoded-secret-here + +// Sie können auch die app/config/config.php-Datei verwenden, um Ihre Geheimnisse zu speichern +// Stellen Sie nur sicher, dass die Konfigurationsdatei nicht in die Versionskontrolle committet wird +// return [ +// 'jwt_secret' => 'your-base64-encoded-secret-here', +// 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', +// ]; + +// In Ihrer App: +$secretKey = getenv('JWT_SECRET'); +``` + +### 3. Geeignete Ablaufzeiten festlegen + +```php +// Gute Praxis: Kurzlebige Access-Tokens +'exp' => time() + (15 * 60) // 15 Minuten + +// Für Refresh-Tokens: Längere Ablaufzeit +'exp' => time() + (7 * 24 * 60 * 60) // 7 Tage +``` + +### 4. HTTPS in der Produktion verwenden + +JWTs sollten **immer** über HTTPS übertragen werden. Senden Sie Tokens niemals über einfaches HTTP in der Produktion! + +### 5. Token-Ansprüche validieren + +Validieren Sie immer die Ansprüche, die Sie interessieren: + +```php +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + +// Überprüfung des Ablaufs wird automatisch von der Bibliothek gehandhabt +// Aber Sie können benutzerdefinierte Validierungen hinzufügen: +if ($decoded->iat > time()) { + throw new Exception('Token verwendet, bevor es ausgestellt wurde'); +} + +if (isset($decoded->nbf) && $decoded->nbf > time()) { + throw new Exception('Token noch nicht gültig'); +} +``` + +### 6. Token-Blacklisting für Logout in Betracht ziehen + +Für zusätzliche Sicherheit eine Blacklist ungültiger Tokens pflegen: + +```php +Flight::route('POST /api/logout', function() { + $authHeader = Flight::request()->getHeader('Authorization'); + preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches); + $jwt = $matches[1]; + + // Den Ablauf des Tokens extrahieren + $decoded = Flight::request()->data->user; + $ttl = $decoded->exp - time(); + + // In Cache/Redis bis zum Ablauf speichern + Flight::cache()->set("blacklist:$jwt", true, $ttl); + + Flight::json(['message' => 'Erfolgreich abgemeldet']); +}); + +// Zu Ihrer JwtMiddleware hinzufügen: +public function before(array $params) { + // ... JWT extrahieren ... + + // Blacklist überprüfen + if (Flight::cache()->get("blacklist:$jwt")) { + $this->app->jsonHalt(['error' => 'Token wurde widerrufen'], 401); + } + + // ... Token überprüfen ... +} +``` + +## Algorithmen und Schlüsseltypen + +Firebase JWT unterstützt mehrere Algorithmen: + +### Symmetrische Algorithmen (HMAC) +- **HS256** (Empfohlen für die meisten Apps): Verwendet einen einzelnen geheimen Schlüssel +- **HS384**, **HS512**: Stärkere Varianten + +```php +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Asymmetrische Algorithmen (RSA/ECDSA) +- **RS256**, **RS384**, **RS512**: Verwendet öffentliche/privaten Schlüsselpaare +- **ES256**, **ES384**, **ES512**: Elliptische-Kurven-Varianten + +```php +// Schlüssel generieren: openssl genrsa -out private.key 2048 +// openssl rsa -in private.key -pubout -out public.key + +$privateKey = file_get_contents('/path/to/private.key'); +$publicKey = file_get_contents('/path/to/public.key'); + +// Mit privatem Schlüssel kodieren +$jwt = JWT::encode($payload, $privateKey, 'RS256'); + +// Mit öffentlichem Schlüssel dekodieren +$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); +``` + +> **Wann RSA verwenden**: Verwenden Sie RSA, wenn Sie den öffentlichen Schlüssel für die Überprüfung verteilen müssen (z. B. Microservices, Drittanbieter-Integrationen). Für eine einzelne Anwendung ist HS256 einfacher und ausreichend. + +## Fehlerbehebung + +### "Abgelaufenes Token"-Fehler +Der `exp`-Anspruch Ihres Tokens liegt in der Vergangenheit. Stellen Sie ein neues Token aus oder implementieren Sie Token-Refresh. + +### "Signaturüberprüfung fehlgeschlagen" +- Sie verwenden einen anderen geheimen Schlüssel zum Dekodieren als zum Kodieren +- Das Token wurde manipuliert +- Uhrzeitskew zwischen Servern (fügen Sie einen Leeway-Puffer hinzu) + +```php +use Firebase\JWT\JWT; + +JWT::$leeway = 60; // 60 Sekunden Uhrzeitskew erlauben +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Token wird nicht in Anfragen gesendet +Stellen Sie sicher, dass Ihr Client den `Authorization`-Header sendet: + +```javascript +// JavaScript-Beispiel +fetch('/api/users', { + headers: { + 'Authorization': 'Bearer ' + token + } +}); +``` + +## Methoden + +Die Firebase JWT-Bibliothek stellt diese Kernmethoden bereit: + +- `JWT::encode(array $payload, string $key, string $alg)`: Erstellt ein JWT aus einem Payload +- `JWT::decode(string $jwt, Key $key)`: Dekodiert und überprüft ein JWT +- `JWT::urlsafeB64Encode(string $input)`: Base64 URL-sichere Kodierung +- `JWT::urlsafeB64Decode(string $input)`: Base64 URL-sichere Dekodierung +- `JWT::$leeway`: Statische Eigenschaft zum Festlegen der Zeit-Leeway für Validierung (in Sekunden) + +## Warum diese Bibliothek verwenden? + +- **Branchenstandard**: Firebase JWT ist die beliebteste und am weitesten vertrauenswürdige JWT-Bibliothek für PHP +- **Aktive Wartung**: Wird vom Google/Firebase-Team gepflegt +- **Sicherheitsfokussiert**: Regelmäßige Updates und Sicherheits-Patches +- **Einfache API**: Leicht zu verstehen und zu implementieren +- **Gut dokumentiert**: Umfangreiche Dokumentation und Community-Support +- **Flexibel**: Unterstützt mehrere Algorithmen und konfigurierbare Optionen + +## Siehe auch + +- [Firebase JWT Github-Repository](https://github.com/firebase/php-jwt) +- [JWT.io](https://jwt.io/) - JWTs debuggen und dekodieren +- [RFC 7519](https://tools.ietf.org/html/rfc7519) - Offizielle JWT-Spezifikation +- [Flight Middleware-Dokumentation](/learn/middleware) +- [Flight Session-Plugin](/awesome-plugins/session) - Für traditionelle sitzungsbasierte Authentifizierung + +## Lizenz + +Die Firebase JWT-Bibliothek ist unter der BSD 3-Clause License lizenziert. Siehe das [Github-Repository](https://github.com/firebase/php-jwt) für Details. \ No newline at end of file diff --git a/content/v3/en/awesome-plugins/awesome_plugins.md b/content/v3/en/awesome-plugins/awesome_plugins.md index a2ec1211..8756e026 100644 --- a/content/v3/en/awesome-plugins/awesome_plugins.md +++ b/content/v3/en/awesome-plugins/awesome_plugins.md @@ -26,6 +26,12 @@ Authorization and Permissions are crucial for any application that requires cont - official [flightphp/permissions](/awesome-plugins/permissions) - Official Flight Permissions library. This library is a simple way to add user and application level permissions to your application. +## Authentication + +Authentication is essential for applications that need to verify user identity and secure API endpoints. + +- [firebase/php-jwt](/awesome-plugins/jwt) - JSON Web Token (JWT) library for PHP. A simple and secure way to implement token-based authentication in your Flight applications. Perfect for stateless API authentication, protecting routes with middleware, and implementing OAuth-style authorization flows. + ## Caching Caching is a great way to speed up your application. There are a number of caching libraries that can be used with Flight. diff --git a/content/v3/en/awesome-plugins/jwt.md b/content/v3/en/awesome-plugins/jwt.md new file mode 100644 index 00000000..ae5ea89e --- /dev/null +++ b/content/v3/en/awesome-plugins/jwt.md @@ -0,0 +1,532 @@ +# Firebase JWT - JSON Web Token Authentication for Flight + +JWT (JSON Web Tokens) are a compact, URL-safe way to represent claims between your application and a client. They're perfect for stateless API authentication—no need for server-side session storage! This guide shows you how to integrate [Firebase JWT](https://github.com/firebase/php-jwt) with Flight for secure, token-based authentication. + +Visit the [Github repository](https://github.com/firebase/php-jwt) for full documentation and details. + +## What is JWT? + +A JSON Web Token is a string that contains three parts: +1. **Header**: Metadata about the token (algorithm, type) +2. **Payload**: Your data (user ID, roles, expiration, etc.) +3. **Signature**: Cryptographic signature to verify authenticity + +Example JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (looks like gibberish, but it's structured data!) + +### Why Use JWT? + +- **Stateless**: No server-side session storage needed—perfect for microservices and APIs +- **Scalable**: Works great with load balancers since there's no session affinity requirement +- **Cross-Domain**: Can be used across different domains and services +- **Mobile-Friendly**: Great for mobile apps where cookies may not work well +- **Standardized**: Industry-standard approach (RFC 7519) + +## Installation + +Install via Composer: + +```bash +composer require firebase/php-jwt +``` + +## Basic Usage + +Here's a quick example of creating and verifying a JWT: + +```php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; + +// Your secret key (KEEP THIS SECURE!) +$secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; + +// Create a token +$payload = [ + 'user_id' => 123, + 'username' => 'johndoe', + 'role' => 'admin', + 'iat' => time(), // Issued at + 'exp' => time() + 3600 // Expires in 1 hour +]; + +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +echo "Token: " . $jwt; + +// Verify and decode a token +try { + $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + echo "User ID: " . $decoded->user_id; +} catch (Exception $e) { + echo "Invalid token: " . $e->getMessage(); +} +``` + +## JWT Middleware for Flight (Recommended Approach) + +The most common and useful way to use JWT with Flight is as **middleware** to protect your API routes. Here's a complete, production-ready example: + +### Step 1: Create a JWT Middleware Class + +```php +// app/middleware/JwtMiddleware.php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; +use Firebase\JWT\ExpiredException; +use Firebase\JWT\SignatureInvalidException; +use flight\Engine; + +class JwtMiddleware { + + protected Engine $app; + protected string $secretKey; + + public function __construct(Engine $app) { + $this->app = $app; + // Store your secret key in app/config/config.php, NOT hardcoded! + $this->secretKey = $app->get('config')['jwt_secret']; + } + + public function before(array $params) { + $authHeader = $this->app->request()->getHeader('Authorization'); + + // Check if Authorization header exists + if (empty($authHeader)) { + $this->app->jsonHalt(['error' => 'No authorization token provided'], 401); + } + + // Extract token from "Bearer " format + if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { + $this->app->jsonHalt(['error' => 'Invalid authorization format. Use: Bearer '], 401); + } + + $jwt = $matches[1]; + + try { + // Decode and verify the token + $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); + + // Store user data in request for use in route handlers + $this->app->request()->data->user = $decoded; + + } catch (ExpiredException $e) { + $this->app->jsonHalt(['error' => 'Token has expired'], 401); + } catch (SignatureInvalidException $e) { + $this->app->jsonHalt(['error' => 'Invalid token signature'], 401); + } catch (Exception $e) { + $this->app->jsonHalt(['error' => 'Invalid token: ' . $e->getMessage()], 401); + } + } +} +``` + +### Step 2: Register JWT Secret in Your Config + +```php +// app/config/config.php +return [ + 'jwt_secret' => getenv('JWT_SECRET') ?: 'your-fallback-secret-for-development' +]; + +// app/config/bootstrap.php or index.php +// make sure to add this line if you want to expose the config to the app +$app->set('config', $config); +``` + +> **Security Note**: Never hardcode your secret key! Use environment variables in production. + +### Step 3: Protect Your Routes with Middleware + +```php +// Protect a single route +Flight::route('GET /api/user/profile', function() { + $user = Flight::request()->data->user; // Set by middleware + Flight::json([ + 'user_id' => $user->user_id, + 'username' => $user->username, + 'role' => $user->role + ]); +})->addMiddleware(JwtMiddleware::class); + +// Protect an entire group of routes (more common!) +Flight::group('/api', function() { + Flight::route('GET /users', function() { /* ... */ }); + Flight::route('GET /posts', function() { /* ... */ }); + Flight::route('POST /posts', function() { /* ... */ }); + Flight::route('DELETE /posts/@id', function($id) { /* ... */ }); +}, [ JwtMiddleware::class ]); // All routes in this group are protected! +``` + +For more details on middleware, see the [middleware documentation](/learn/middleware). + +## Common Use Cases + +### 1. Login Endpoint (Token Generation) + +Create a route that generates a JWT after successful authentication: + +```php +Flight::route('POST /api/login', function() { + $data = Flight::request()->data; + $username = $data->username ?? ''; + $password = $data->password ?? ''; + + // Validate credentials (example - use your own logic!) + $user = validateUserCredentials($username, $password); + + if (!$user) { + Flight::jsonHalt(['error' => 'Invalid credentials'], 401); + } + + // Generate JWT + $secretKey = Flight::get('config')['jwt_secret']; + $payload = [ + 'user_id' => $user->id, + 'username' => $user->username, + 'role' => $user->role, + 'iat' => time(), + 'exp' => time() + (60 * 60) // 1 hour expiration + ]; + + $jwt = JWT::encode($payload, $secretKey, 'HS256'); + + Flight::json([ + 'success' => true, + 'token' => $jwt, + 'expires_in' => 3600 + ]); +}); + +function validateUserCredentials($username, $password) { + // Your database lookup and password verification here + // Example: + $db = Flight::db(); + $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); + + if ($user && password_verify($password, $user['password_hash'])) { + return (object) [ + 'id' => $user['id'], + 'username' => $user['username'], + 'role' => $user['role'] + ]; + } + return null; +} +``` + +### 2. Token Refresh Flow + +Implement a refresh token system for long-lived sessions: + +```php +Flight::route('POST /api/login', function() { + // ... validate credentials ... + + $secretKey = Flight::get('config')['jwt_secret']; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + // Short-lived access token (15 minutes) + $accessToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + // Long-lived refresh token (7 days) + $refreshToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'refresh', + 'iat' => time(), + 'exp' => time() + (7 * 24 * 60 * 60) + ], $refreshSecret, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'refresh_token' => $refreshToken, + 'expires_in' => 900 + ]); +}); + +Flight::route('POST /api/refresh', function() { + $refreshToken = Flight::request()->data->refresh_token ?? ''; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + try { + $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); + + // Verify this is a refresh token + if ($decoded->type !== 'refresh') { + Flight::jsonHalt(['error' => 'Invalid token type'], 401); + } + + // Generate new access token + $secretKey = Flight::get('config')['jwt_secret']; + $accessToken = JWT::encode([ + 'user_id' => $decoded->user_id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'expires_in' => 900 + ]); + + } catch (Exception $e) { + Flight::jsonHalt(['error' => 'Invalid refresh token'], 401); + } +}); +``` + +### 3. Role-Based Access Control + +Extend your middleware to check user roles: + +```php +class JwtRoleMiddleware { + + protected Engine $app; + protected array $allowedRoles; + + public function __construct(Engine $app, array $allowedRoles = []) { + $this->app = $app; + $this->allowedRoles = $allowedRoles; + } + + public function before(array $params) { + // Assume JwtMiddleware already ran and set user data + $user = $this->app->request()->data->user ?? null; + + if (!$user) { + $this->app->jsonHalt(['error' => 'Authentication required'], 401); + } + + // Check if user has required role + if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { + $this->app->jsonHalt(['error' => 'Insufficient permissions'], 403); + } + } +} + +// Usage: Admin-only route +Flight::route('DELETE /api/users/@id', function($id) { + // Delete user logic +})->addMiddleware([ + JwtMiddleware::class, + new JwtRoleMiddleware(Flight::app(), ['admin']) +]); +``` + +### 4. Public API with Rate Limiting by User + +Use JWT to track and rate-limit users without sessions: + +```php +class RateLimitMiddleware { + + public function before(array $params) { + $user = Flight::request()->data->user ?? null; + $userId = $user ? $user->user_id : Flight::request()->ip; + + $cacheKey = "rate_limit:$userId"; + // Make sure you set up a cache service in app/config/services.php + $requests = Flight::cache()->get($cacheKey, 0); + + if ($requests >= 100) { // 100 requests per hour + Flight::jsonHalt(['error' => 'Rate limit exceeded'], 429); + } + + Flight::cache()->set($cacheKey, $requests + 1, 3600); + } +} +``` + +## Security Best Practices + +### 1. Use Strong Secret Keys + +```php +// Generate a secure secret key (run once, save to .env file) +$secretKey = base64_encode(random_bytes(32)); +echo $secretKey; // Store this in your .env file! +``` + +### 2. Store Secrets in Environment Variables + +```php +// Never commit secrets to version control! +// Use a .env file and library like vlucas/phpdotenv + +// .env file: +// JWT_SECRET=your-base64-encoded-secret-here +// JWT_REFRESH_SECRET=another-base64-encoded-secret-here + +// You can also use the app/config/config.php file to store your secrets +// just make sure that the config file is not committed to version control +// return [ +// 'jwt_secret' => 'your-base64-encoded-secret-here', +// 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', +// ]; + +// In your app: +$secretKey = getenv('JWT_SECRET'); +``` + +### 3. Set Appropriate Expiration Times + +```php +// Good practice: short-lived access tokens +'exp' => time() + (15 * 60) // 15 minutes + +// For refresh tokens: longer expiration +'exp' => time() + (7 * 24 * 60 * 60) // 7 days +``` + +### 4. Use HTTPS in Production + +JWTs should **always** be transmitted over HTTPS. Never send tokens over plain HTTP in production! + +### 5. Validate Token Claims + +Always validate the claims you care about: + +```php +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + +// Check expiration is handled automatically by the library +// But you can add custom validations: +if ($decoded->iat > time()) { + throw new Exception('Token used before it was issued'); +} + +if (isset($decoded->nbf) && $decoded->nbf > time()) { + throw new Exception('Token not yet valid'); +} +``` + +### 6. Consider Token Blacklisting for Logout + +For extra security, maintain a blacklist of invalidated tokens: + +```php +Flight::route('POST /api/logout', function() { + $authHeader = Flight::request()->getHeader('Authorization'); + preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches); + $jwt = $matches[1]; + + // Extract the token's expiration + $decoded = Flight::request()->data->user; + $ttl = $decoded->exp - time(); + + // Store in cache/redis until expiration + Flight::cache()->set("blacklist:$jwt", true, $ttl); + + Flight::json(['message' => 'Successfully logged out']); +}); + +// Add to your JwtMiddleware: +public function before(array $params) { + // ... extract JWT ... + + // Check blacklist + if (Flight::cache()->get("blacklist:$jwt")) { + $this->app->jsonHalt(['error' => 'Token has been revoked'], 401); + } + + // ... verify token ... +} +``` + +## Algorithms and Key Types + +Firebase JWT supports multiple algorithms: + +### Symmetric Algorithms (HMAC) +- **HS256** (Recommended for most apps): Uses a single secret key +- **HS384**, **HS512**: Stronger variants + +```php +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Asymmetric Algorithms (RSA/ECDSA) +- **RS256**, **RS384**, **RS512**: Uses public/private key pairs +- **ES256**, **ES384**, **ES512**: Elliptic curve variants + +```php +// Generate keys: openssl genrsa -out private.key 2048 +// openssl rsa -in private.key -pubout -out public.key + +$privateKey = file_get_contents('/path/to/private.key'); +$publicKey = file_get_contents('/path/to/public.key'); + +// Encode with private key +$jwt = JWT::encode($payload, $privateKey, 'RS256'); + +// Decode with public key +$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); +``` + +> **When to use RSA**: Use RSA when you need to distribute the public key for verification (e.g., microservices, third-party integrations). For a single application, HS256 is simpler and sufficient. + +## Troubleshooting + +### "Expired token" Error +Your token's `exp` claim is in the past. Issue a new token or implement token refresh. + +### "Signature verification failed" +- You're using a different secret key to decode than you used to encode +- The token has been tampered with +- Clock skew between servers (add a leeway buffer) + +```php +use Firebase\JWT\JWT; + +JWT::$leeway = 60; // Allow 60 seconds of clock skew +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Token Not Being Sent in Requests +Make sure your client is sending the `Authorization` header: + +```javascript +// JavaScript example +fetch('/api/users', { + headers: { + 'Authorization': 'Bearer ' + token + } +}); +``` + +## Methods + +The Firebase JWT library provides these core methods: + +- `JWT::encode(array $payload, string $key, string $alg)`: Creates a JWT from a payload +- `JWT::decode(string $jwt, Key $key)`: Decodes and verifies a JWT +- `JWT::urlsafeB64Encode(string $input)`: Base64 URL-safe encoding +- `JWT::urlsafeB64Decode(string $input)`: Base64 URL-safe decoding +- `JWT::$leeway`: Static property to set time leeway for validation (in seconds) + +## Why Use This Library? + +- **Industry Standard**: Firebase JWT is the most popular and widely trusted JWT library for PHP +- **Active Maintenance**: Maintained by Google/Firebase team +- **Security Focused**: Regular updates and security patches +- **Simple API**: Easy to understand and implement +- **Well Documented**: Extensive documentation and community support +- **Flexible**: Supports multiple algorithms and configurable options + +## See Also + +- [Firebase JWT Github Repository](https://github.com/firebase/php-jwt) +- [JWT.io](https://jwt.io/) - Debug and decode JWTs +- [RFC 7519](https://tools.ietf.org/html/rfc7519) - Official JWT specification +- [Flight Middleware Documentation](/learn/middleware) +- [Flight Session Plugin](/awesome-plugins/session) - For traditional session-based auth + +## License + +The Firebase JWT library is licensed under the BSD 3-Clause License. See the [Github repository](https://github.com/firebase/php-jwt) for details. diff --git a/content/v3/es/awesome-plugins/awesome_plugins.md b/content/v3/es/awesome-plugins/awesome_plugins.md index 415ab10f..e5c9030a 100644 --- a/content/v3/es/awesome-plugins/awesome_plugins.md +++ b/content/v3/es/awesome-plugins/awesome_plugins.md @@ -1,42 +1,48 @@ # Plugins Geniales -Flight es increíblemente extensible. Hay una serie de plugins que se pueden usar para agregar funcionalidad a tu aplicación Flight. Algunos son oficialmente soportados por el Equipo de Flight y otros son bibliotecas micro/lite para ayudarte a comenzar. +Flight es increíblemente extensible. Hay una serie de plugins que se pueden usar para agregar funcionalidad a tu aplicación Flight. Algunos son soportados oficialmente por el Equipo de Flight y otros son bibliotecas micro/lite para ayudarte a comenzar. ## Documentación de API -La documentación de API es crucial para cualquier API. Ayuda a los desarrolladores a entender cómo interactuar con tu API y qué esperar a cambio. Hay un par de herramientas disponibles para ayudarte a generar documentación de API para tus Proyectos de Flight. +La documentación de API es crucial para cualquier API. Ayuda a los desarrolladores a entender cómo interactuar con tu API y qué esperar a cambio. Hay un par de herramientas disponibles para ayudarte a generar documentación de API para tus Proyectos Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Publicación de blog escrita por Daniel Schreiber sobre cómo usar la Especificación OpenAPI con FlightPHP para construir tu API utilizando un enfoque API primero. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI es una gran herramienta para ayudarte a generar documentación de API para tus proyectos de Flight. Es muy fácil de usar y se puede personalizar para adaptarse a tus necesidades. Esta es la biblioteca PHP para ayudarte a generar la documentación Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Publicación de blog escrita por Daniel Schreiber sobre cómo usar la Especificación OpenAPI con FlightPHP para construir tu API utilizando un enfoque API first. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI es una gran herramienta para ayudarte a generar documentación de API para tus proyectos Flight. Es muy fácil de usar y se puede personalizar para adaptarse a tus necesidades. Esta es la biblioteca PHP para ayudarte a generar la documentación Swagger. ## Monitoreo de Rendimiento de Aplicaciones (APM) El Monitoreo de Rendimiento de Aplicaciones (APM) es crucial para cualquier aplicación. Te ayuda a entender cómo está funcionando tu aplicación y dónde están los cuellos de botella. Hay una serie de herramientas APM que se pueden usar con Flight. -- oficial [flightphp/apm](/awesome-plugins/apm) - Flight APM es una biblioteca APM simple que se puede usar para monitorear tus aplicaciones de Flight. Se puede usar para monitorear el rendimiento de tu aplicación y ayudarte a identificar cuellos de botella. +- oficial [flightphp/apm](/awesome-plugins/apm) - Flight APM es una biblioteca APM simple que se puede usar para monitorear tus aplicaciones Flight. Se puede usar para monitorear el rendimiento de tu aplicación y ayudarte a identificar cuellos de botella. ## Async Flight ya es un framework rápido, pero agregarle un motor turbo lo hace todo más divertido (¡y desafiante)! -- [flightphp/async](/awesome-plugins/async) - Biblioteca Async oficial de Flight. Esta biblioteca es una forma simple de agregar procesamiento asíncrono a tu aplicación. Usa Swoole/Openswoole bajo el capó para proporcionar una forma simple y efectiva de ejecutar tareas de manera asíncrona. +- [flightphp/async](/awesome-plugins/async) - Biblioteca oficial de Flight Async. Esta biblioteca es una forma simple de agregar procesamiento asíncrono a tu aplicación. Usa Swoole/Openswoole bajo el capó para proporcionar una forma simple y efectiva de ejecutar tareas de manera asíncrona. ## Autorización/Permisos -La Autorización y Permisos son cruciales para cualquier aplicación que requiera controles en su lugar para quién puede acceder a qué. +La autorización y los permisos son cruciales para cualquier aplicación que requiera controles en su lugar para quién puede acceder a qué. -- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca de Permisos oficial de Flight. Esta biblioteca es una forma simple de agregar permisos a nivel de usuario y aplicación a tu aplicación. +- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca oficial de Permisos de Flight. Esta biblioteca es una forma simple de agregar permisos a nivel de usuario y aplicación a tu aplicación. + +## Autenticación + +La autenticación es esencial para las aplicaciones que necesitan verificar la identidad del usuario y asegurar endpoints de API. + +- [firebase/php-jwt](/awesome-plugins/jwt) - Biblioteca de JSON Web Token (JWT) para PHP. Una forma simple y segura de implementar autenticación basada en tokens en tus aplicaciones Flight. Perfecta para autenticación de API sin estado, protección de rutas con middleware e implementación de flujos de autorización estilo OAuth. ## Caché El caché es una gran manera de acelerar tu aplicación. Hay una serie de bibliotecas de caché que se pueden usar con Flight. -- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Clase de caché en archivo PHP ligera, simple y independiente +- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Clase ligera, simple y standalone de caché en archivo PHP ## CLI Las aplicaciones CLI son una gran manera de interactuar con tu aplicación. Puedes usarlas para generar controladores, mostrar todas las rutas y más. -- oficial [flightphp/runway](/awesome-plugins/runway) - Runway es una aplicación CLI que te ayuda a gestionar tus aplicaciones de Flight. +- oficial [flightphp/runway](/awesome-plugins/runway) - Runway es una aplicación CLI que te ayuda a gestionar tus aplicaciones Flight. ## Cookies @@ -46,18 +52,18 @@ Las cookies son una gran manera de almacenar pequeños fragmentos de datos en el ## Depuración -La depuración es crucial cuando estás desarrollando en tu entorno local. Hay unos pocos plugins que pueden elevar tu experiencia de depuración. +La depuración es crucial cuando estás desarrollando en tu entorno local. Hay algunos plugins que pueden elevar tu experiencia de depuración. - [tracy/tracy](/awesome-plugins/tracy) - Este es un manejador de errores completo que se puede usar con Flight. Tiene una serie de paneles que pueden ayudarte a depurar tu aplicación. También es muy fácil de extender y agregar tus propios paneles. -- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado con el manejador de errores [Tracy](/awesome-plugins/tracy), este plugin agrega unos pocos paneles extra para ayudar con la depuración específicamente para proyectos de Flight. +- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado con el manejador de errores [Tracy](/awesome-plugins/tracy), este plugin agrega algunos paneles extra para ayudar con la depuración específicamente para proyectos Flight. ## Bases de Datos -Las bases de datos son el núcleo de la mayoría de las aplicaciones. Así es como almacenas y recuperas datos. Algunas bibliotecas de bases de datos son simplemente envolturas para escribir consultas y otras son ORMs completos. +Las bases de datos son el núcleo de la mayoría de las aplicaciones. Así es como almacenas y recuperas datos. Algunas bibliotecas de base de datos son simplemente envoltorios para escribir consultas y algunas son ORMs completos. -- oficial [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Envoltura PDO oficial de Flight que forma parte del núcleo. Esta es una envoltura simple para ayudar a simplificar el proceso de escribir consultas y ejecutarlas. No es un ORM. -- oficial [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord oficial de Flight. Gran biblioteca pequeña para recuperar y almacenar datos fácilmente en tu base de datos. -- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para rastrear todos los cambios de base de datos para tu proyecto. +- oficial [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Envoltorio oficial de PDO de Flight que forma parte del núcleo. Este es un envoltorio simple para ayudar a simplificar el proceso de escribir consultas y ejecutarlas. No es un ORM. +- oficial [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper oficial de ActiveRecord de Flight. Gran biblioteca pequeña para recuperar y almacenar datos fácilmente en tu base de datos. +- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para mantener un registro de todos los cambios de base de datos para tu proyecto. ## Encriptación @@ -65,9 +71,9 @@ La encriptación es crucial para cualquier aplicación que almacene datos sensib - [defuse/php-encryption](/awesome-plugins/php-encryption) - Esta es una biblioteca que se puede usar para encriptar y desencriptar datos. Ponerse en marcha es bastante simple para comenzar a encriptar y desencriptar datos. -## Cola de Tareas +## Cola de Trabajos -Las colas de tareas son realmente útiles para procesar tareas de manera asíncrona. Esto puede ser enviar correos electrónicos, procesar imágenes o cualquier cosa que no necesite hacerse en tiempo real. +Las colas de trabajos son realmente útiles para procesar tareas de manera asíncrona. Esto puede ser enviar correos electrónicos, procesar imágenes o cualquier cosa que no necesite hacerse en tiempo real. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue es una biblioteca que se puede usar para procesar trabajos de manera asíncrona. Se puede usar con beanstalkd, MySQL/MariaDB, SQLite y PostgreSQL. @@ -75,23 +81,23 @@ Las colas de tareas son realmente útiles para procesar tareas de manera asíncr Las sesiones no son realmente útiles para las API, pero para construir una aplicación web, las sesiones pueden ser cruciales para mantener el estado e información de inicio de sesión. -- oficial [flightphp/session](/awesome-plugins/session) - Biblioteca de Sesión oficial de Flight. Esta es una biblioteca de sesión simple que se puede usar para almacenar y recuperar datos de sesión. Usa el manejo de sesiones integrado de PHP. +- oficial [flightphp/session](/awesome-plugins/session) - Biblioteca oficial de Sesión de Flight. Esta es una biblioteca de sesión simple que se puede usar para almacenar y recuperar datos de sesión. Usa el manejo de sesiones integrado de PHP. - [Ghostff/Session](/awesome-plugins/ghost-session) - Gestor de Sesiones PHP (no bloqueante, flash, segmento, encriptación de sesión). Usa PHP open_ssl para encriptación/desencriptación opcional de datos de sesión. ## Plantillas -La plantillación es el núcleo de cualquier aplicación web con una UI. Hay una serie de motores de plantillas que se pueden usar con Flight. +La plantillas son el núcleo de cualquier aplicación web con una UI. Hay una serie de motores de plantillas que se pueden usar con Flight. - deprecado [flightphp/core View](/learn#views) - Este es un motor de plantillas muy básico que forma parte del núcleo. No se recomienda usarlo si tienes más de un par de páginas en tu proyecto. - [latte/latte](/awesome-plugins/latte) - Latte es un motor de plantillas completo que es muy fácil de usar y se siente más cercano a la sintaxis PHP que Twig o Smarty. También es muy fácil de extender y agregar tus propios filtros y funciones. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate es un potente motor de plantillas PHP con compilación de activos, herencia de plantillas y procesamiento de variables. Incluye minificación automática de CSS/JS, caché, codificación Base64 e integración opcional con el framework PHP Flight. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate es un potente motor de plantillas PHP con compilación de assets, herencia de plantillas y procesamiento de variables. Incluye minificación automática de CSS/JS, caché, codificación Base64 e integración opcional con el framework PHP Flight. ## Integración con WordPress -¿Quieres usar Flight en tu proyecto de WordPress? ¡Hay un plugin práctico para eso! +¿Quieres usar Flight en tu proyecto WordPress? ¡Hay un plugin práctico para eso! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Este plugin de WordPress te permite ejecutar Flight justo al lado de WordPress. Es perfecto para agregar APIs personalizadas, microservicios o incluso aplicaciones completas a tu sitio de WordPress usando el framework Flight. ¡Súper útil si quieres lo mejor de ambos mundos! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Este plugin de WordPress te permite ejecutar Flight junto a WordPress. Es perfecto para agregar APIs personalizadas, microservicios o incluso aplicaciones completas a tu sitio WordPress usando el framework Flight. ¡Súper útil si quieres lo mejor de ambos mundos! -## Contribución +## Contribuyendo ¿Tienes un plugin que te gustaría compartir? ¡Envía una solicitud de pull para agregarlo a la lista! \ No newline at end of file diff --git a/content/v3/es/awesome-plugins/jwt.md b/content/v3/es/awesome-plugins/jwt.md new file mode 100644 index 00000000..78b3dc65 --- /dev/null +++ b/content/v3/es/awesome-plugins/jwt.md @@ -0,0 +1,532 @@ +# Firebase JWT - Autenticación con JSON Web Token para Flight + +JWT (JSON Web Tokens) son una forma compacta y segura para URLs de representar reclamaciones entre tu aplicación y un cliente. ¡Son perfectos para la autenticación de API sin estado, sin necesidad de almacenamiento de sesiones en el servidor! Esta guía te muestra cómo integrar [Firebase JWT](https://github.com/firebase/php-jwt) con Flight para una autenticación segura basada en tokens. + +Visita el [repositorio de Github](https://github.com/firebase/php-jwt) para documentación completa y detalles. + +## ¿Qué es JWT? + +Un JSON Web Token es una cadena que contiene tres partes: +1. **Header**: Metadatos sobre el token (algoritmo, tipo) +2. **Payload**: Tus datos (ID de usuario, roles, expiración, etc.) +3. **Signature**: Firma criptográfica para verificar la autenticidad + +Ejemplo de JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (parece gibberish, ¡pero es data estructurada!) + +### ¿Por qué usar JWT? + +- **Sin estado**: No se necesita almacenamiento de sesiones en el servidor, perfecto para microservicios y APIs +- **Escalable**: Funciona genial con balanceadores de carga ya que no hay requisito de afinidad de sesión +- **Multi-dominio**: Se puede usar a través de diferentes dominios y servicios +- **Amigable con móviles**: Genial para apps móviles donde las cookies pueden no funcionar bien +- **Estandarizado**: Enfoque estándar de la industria (RFC 7519) + +## Instalación + +Instala vía Composer: + +```bash +composer require firebase/php-jwt +``` + +## Uso básico + +Aquí hay un ejemplo rápido de creación y verificación de un JWT: + +```php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; + +// Tu clave secreta (¡MANTÉNLA SEGURA!) +$secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; + +// Crear un token +$payload = [ + 'user_id' => 123, + 'username' => 'johndoe', + 'role' => 'admin', + 'iat' => time(), // Emitido en + 'exp' => time() + 3600 // Expira en 1 hora +]; + +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +echo "Token: " . $jwt; + +// Verificar y decodificar un token +try { + $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + echo "User ID: " . $decoded->user_id; +} catch (Exception $e) { + echo "Invalid token: " . $e->getMessage(); +} +``` + +## Middleware JWT para Flight (Enfoque recomendado) + +La forma más común y útil de usar JWT con Flight es como **middleware** para proteger tus rutas de API. Aquí hay un ejemplo completo, listo para producción: + +### Paso 1: Crear una clase de middleware JWT + +```php +// app/middleware/JwtMiddleware.php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; +use Firebase\JWT\ExpiredException; +use Firebase\JWT\SignatureInvalidException; +use flight\Engine; + +class JwtMiddleware { + + protected Engine $app; + protected string $secretKey; + + public function __construct(Engine $app) { + $this->app = $app; + // Almacena tu clave secreta en app/config/config.php, ¡NO la hardcodees! + $this->secretKey = $app->get('config')['jwt_secret']; + } + + public function before(array $params) { + $authHeader = $this->app->request()->getHeader('Authorization'); + + // Verificar si existe el header de Authorization + if (empty($authHeader)) { + $this->app->jsonHalt(['error' => 'No se proporcionó token de autorización'], 401); + } + + // Extraer token del formato "Bearer " + if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { + $this->app->jsonHalt(['error' => 'Formato de autorización inválido. Usa: Bearer '], 401); + } + + $jwt = $matches[1]; + + try { + // Decodificar y verificar el token + $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); + + // Almacenar datos de usuario en la solicitud para usar en manejadores de rutas + $this->app->request()->data->user = $decoded; + + } catch (ExpiredException $e) { + $this->app->jsonHalt(['error' => 'El token ha expirado'], 401); + } catch (SignatureInvalidException $e) { + $this->app->jsonHalt(['error' => 'Firma de token inválida'], 401); + } catch (Exception $e) { + $this->app->jsonHalt(['error' => 'Token inválido: ' . $e->getMessage()], 401); + } + } +} +``` + +### Paso 2: Registrar clave secreta JWT en tu configuración + +```php +// app/config/config.php +return [ + 'jwt_secret' => getenv('JWT_SECRET') ?: 'your-fallback-secret-for-development' +]; + +// app/config/bootstrap.php o index.php +// asegúrate de agregar esta línea si quieres exponer la config a la app +$app->set('config', $config); +``` + +> **Nota de seguridad**: ¡Nunca hardcodees tu clave secreta! Usa variables de entorno en producción. + +### Paso 3: Proteger tus rutas con middleware + +```php +// Proteger una ruta individual +Flight::route('GET /api/user/profile', function() { + $user = Flight::request()->data->user; // Establecido por el middleware + Flight::json([ + 'user_id' => $user->user_id, + 'username' => $user->username, + 'role' => $user->role + ]); +})->addMiddleware( JwtMiddleware::class); + +// Proteger un grupo entero de rutas (¡más común!) +Flight::group('/api', function() { + Flight::route('GET /users', function() { /* ... */ }); + Flight::route('GET /posts', function() { /* ... */ }); + Flight::route('POST /posts', function() { /* ... */ }); + Flight::route('DELETE /posts/@id', function($id) { /* ... */ }); +}, [ JwtMiddleware::class ]); // ¡Todas las rutas en este grupo están protegidas! +``` + +Para más detalles sobre middleware, ve la [documentación de middleware](/learn/middleware). + +## Casos de uso comunes + +### 1. Endpoint de login (Generación de token) + +Crea una ruta que genera un JWT después de una autenticación exitosa: + +```php +Flight::route('POST /api/login', function() { + $data = Flight::request()->data; + $username = $data->username ?? ''; + $password = $data->password ?? ''; + + // Validar credenciales (ejemplo - usa tu propia lógica!) + $user = validateUserCredentials($username, $password); + + if (!$user) { + Flight::jsonHalt(['error' => 'Credenciales inválidas'], 401); + } + + // Generar JWT + $secretKey = Flight::get('config')['jwt_secret']; + $payload = [ + 'user_id' => $user->id, + 'username' => $user->username, + 'role' => $user->role, + 'iat' => time(), + 'exp' => time() + (60 * 60) // Expiración en 1 hora + ]; + + $jwt = JWT::encode($payload, $secretKey, 'HS256'); + + Flight::json([ + 'success' => true, + 'token' => $jwt, + 'expires_in' => 3600 + ]); +}); + +function validateUserCredentials($username, $password) { + // Tu búsqueda en base de datos y verificación de contraseña aquí + // Ejemplo: + $db = Flight::db(); + $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); + + if ($user && password_verify($password, $user['password_hash'])) { + return (object) [ + 'id' => $user['id'], + 'username' => $user['username'], + 'role' => $user['role'] + ]; + } + return null; +} +``` + +### 2. Flujo de actualización de token + +Implementa un sistema de token de actualización para sesiones de larga duración: + +```php +Flight::route('POST /api/login', function() { + // ... validar credenciales ... + + $secretKey = Flight::get('config')['jwt_secret']; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + // Token de acceso de corta duración (15 minutos) + $accessToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + // Token de actualización de larga duración (7 días) + $refreshToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'refresh', + 'iat' => time(), + 'exp' => time() + (7 * 24 * 60 * 60) + ], $refreshSecret, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'refresh_token' => $refreshToken, + 'expires_in' => 900 + ]); +}); + +Flight::route('POST /api/refresh', function() { + $refreshToken = Flight::request()->data->refresh_token ?? ''; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + try { + $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); + + // Verificar que sea un token de actualización + if ($decoded->type !== 'refresh') { + Flight::jsonHalt(['error' => 'Tipo de token inválido'], 401); + } + + // Generar nuevo token de acceso + $secretKey = Flight::get('config')['jwt_secret']; + $accessToken = JWT::encode([ + 'user_id' => $decoded->user_id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'expires_in' => 900 + ]); + + } catch (Exception $e) { + Flight::jsonHalt(['error' => 'Token de actualización inválido'], 401); + } +}); +``` + +### 3. Control de acceso basado en roles + +Extiende tu middleware para verificar roles de usuario: + +```php +class JwtRoleMiddleware { + + protected Engine $app; + protected array $allowedRoles; + + public function __construct(Engine $app, array $allowedRoles = []) { + $this->app = $app; + $this->allowedRoles = $allowedRoles; + } + + public function before(array $params) { + // Asume que JwtMiddleware ya se ejecutó y estableció los datos de usuario + $user = $this->app->request()->data->user ?? null; + + if (!$user) { + $this->app->jsonHalt(['error' => 'Autenticación requerida'], 401); + } + + // Verificar si el usuario tiene el rol requerido + if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { + $this->app->jsonHalt(['error' => 'Permisos insuficientes'], 403); + } + } +} + +// Uso: Ruta solo para admin +Flight::route('DELETE /api/users/@id', function($id) { + // Lógica de eliminación de usuario +})->addMiddleware([ + JwtMiddleware::class, + new JwtRoleMiddleware(Flight::app(), ['admin']) +]); +``` + +### 4. API pública con limitación de tasa por usuario + +Usa JWT para rastrear y limitar la tasa de usuarios sin sesiones: + +```php +class RateLimitMiddleware { + + public function before(array $params) { + $user = Flight::request()->data->user ?? null; + $userId = $user ? $user->user_id : Flight::request()->ip; + + $cacheKey = "rate_limit:$userId"; + // Asegúrate de configurar un servicio de caché en app/config/services.php + $requests = Flight::cache()->get($cacheKey, 0); + + if ($requests >= 100) { // 100 solicitudes por hora + Flight::jsonHalt(['error' => 'Límite de tasa excedido'], 429); + } + + Flight::cache()->set($cacheKey, $requests + 1, 3600); + } +} +``` + +## Mejores prácticas de seguridad + +### 1. Usa claves secretas fuertes + +```php +// Genera una clave secreta segura (ejecuta una vez, guárdala en archivo .env) +$secretKey = base64_encode(random_bytes(32)); +echo $secretKey; // ¡Almacena esto en tu archivo .env! +``` + +### 2. Almacena secretos en variables de entorno + +```php +// ¡Nunca comprometas secretos en control de versiones! +// Usa un archivo .env y una librería como vlucas/phpdotenv + +// Archivo .env: +// JWT_SECRET=your-base64-encoded-secret-here +// JWT_REFRESH_SECRET=another-base64-encoded-secret-here + +// También puedes usar el archivo app/config/config.php para almacenar tus secretos +// solo asegúrate de que el archivo de config no se comprometa en control de versiones +// return [ +// 'jwt_secret' => 'your-base64-encoded-secret-here', +// 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', +// ]; + +// En tu app: +$secretKey = getenv('JWT_SECRET'); +``` + +### 3. Establece tiempos de expiración apropiados + +```php +// Buena práctica: tokens de acceso de corta duración +'exp' => time() + (15 * 60) // 15 minutos + +// Para tokens de actualización: expiración más larga +'exp' => time() + (7 * 24 * 60 * 60) // 7 días +``` + +### 4. Usa HTTPS en producción + +Los JWT deben **siempre** transmitirse sobre HTTPS. ¡Nunca envíes tokens sobre HTTP plano en producción! + +### 5. Valida las reclamaciones del token + +Siempre valida las reclamaciones que te importan: + +```php +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + +// La verificación de expiración se maneja automáticamente por la librería +// Pero puedes agregar validaciones personalizadas: +if ($decoded->iat > time()) { + throw new Exception('Token usado antes de ser emitido'); +} + +if (isset($decoded->nbf) && $decoded->nbf > time()) { + throw new Exception('Token aún no válido'); +} +``` + +### 6. Considera lista negra de tokens para logout + +Para seguridad extra, mantén una lista negra de tokens invalidados: + +```php +Flight::route('POST /api/logout', function() { + $authHeader = Flight::request()->getHeader('Authorization'); + preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches); + $jwt = $matches[1]; + + // Extraer la expiración del token + $decoded = Flight::request()->data->user; + $ttl = $decoded->exp - time(); + + // Almacenar en caché/redis hasta la expiración + Flight::cache()->set("blacklist:$jwt", true, $ttl); + + Flight::json(['message' => 'Cierre de sesión exitoso']); +}); + +// Agregar a tu JwtMiddleware: +public function before(array $params) { + // ... extraer JWT ... + + // Verificar lista negra + if (Flight::cache()->get("blacklist:$jwt")) { + $this->app->jsonHalt(['error' => 'El token ha sido revocado'], 401); + } + + // ... verificar token ... +} +``` + +## Algoritmos y tipos de claves + +Firebase JWT soporta múltiples algoritmos: + +### Algoritmos simétricos (HMAC) +- **HS256** (Recomendado para la mayoría de apps): Usa una sola clave secreta +- **HS384**, **HS512**: Variantes más fuertes + +```php +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Algoritmos asimétricos (RSA/ECDSA) +- **RS256**, **RS384**, **RS512**: Usa pares de claves pública/privada +- **ES256**, **ES384**, **ES512**: Variantes de curva elíptica + +```php +// Generar claves: openssl genrsa -out private.key 2048 +// openssl rsa -in private.key -pubout -out public.key + +$privateKey = file_get_contents('/path/to/private.key'); +$publicKey = file_get_contents('/path/to/public.key'); + +// Codificar con clave privada +$jwt = JWT::encode($payload, $privateKey, 'RS256'); + +// Decodificar con clave pública +$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); +``` + +> **Cuándo usar RSA**: Usa RSA cuando necesites distribuir la clave pública para verificación (p.ej., microservicios, integraciones de terceros). Para una sola aplicación, HS256 es más simple y suficiente. + +## Solución de problemas + +### Error "Token expirado" +La reclamación `exp` de tu token está en el pasado. Emite un nuevo token o implementa actualización de token. + +### "Falla en verificación de firma" +- Estás usando una clave secreta diferente para decodificar que la que usaste para codificar +- El token ha sido manipulado +- Desfase de reloj entre servidores (agrega un buffer de tolerancia) + +```php +use Firebase\JWT\JWT; + +JWT::$leeway = 60; // Permitir 60 segundos de desfase de reloj +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Token no se envía en solicitudes +Asegúrate de que tu cliente esté enviando el header `Authorization`: + +```javascript +// Ejemplo en JavaScript +fetch('/api/users', { + headers: { + 'Authorization': 'Bearer ' + token + } +}); +``` + +## Métodos + +La librería Firebase JWT proporciona estos métodos principales: + +- `JWT::encode(array $payload, string $key, string $alg)`: Crea un JWT a partir de un payload +- `JWT::decode(string $jwt, Key $key)`: Decodifica y verifica un JWT +- `JWT::urlsafeB64Encode(string $input)`: Codificación Base64 URL-segura +- `JWT::urlsafeB64Decode(string $input)`: Decodificación Base64 URL-segura +- `JWT::$leeway`: Propiedad estática para establecer tolerancia de tiempo para validación (en segundos) + +## ¿Por qué usar esta librería? + +- **Estándar de la industria**: Firebase JWT es la librería JWT más popular y confiable para PHP +- **Mantenimiento activo**: Mantenida por el equipo de Google/Firebase +- **Enfocada en seguridad**: Actualizaciones regulares y parches de seguridad +- **API simple**: Fácil de entender e implementar +- **Bien documentada**: Documentación extensa y soporte de comunidad +- **Flexible**: Soporta múltiples algoritmos y opciones configurables + +## Ver también + +- [Repositorio de Github de Firebase JWT](https://github.com/firebase/php-jwt) +- [JWT.io](https://jwt.io/) - Depura y decodifica JWTs +- [RFC 7519](https://tools.ietf.org/html/rfc7519) - Especificación oficial de JWT +- [Documentación de middleware de Flight](/learn/middleware) +- [Plugin de sesión de Flight](/awesome-plugins/session) - Para autenticación basada en sesiones tradicionales + +## Licencia + +La librería Firebase JWT está licenciada bajo la Licencia BSD 3-Clause. Ve el [repositorio de Github](https://github.com/firebase/php-jwt) para detalles. \ No newline at end of file diff --git a/content/v3/fr/awesome-plugins/awesome_plugins.md b/content/v3/fr/awesome-plugins/awesome_plugins.md index c82b0d49..4564bd42 100644 --- a/content/v3/fr/awesome-plugins/awesome_plugins.md +++ b/content/v3/fr/awesome-plugins/awesome_plugins.md @@ -1,13 +1,13 @@ -# Plugins Formidables +# Plugins Géniaux -Flight est incroyablement extensible. Il existe un certain nombre de plugins qui peuvent être utilisés pour ajouter des fonctionnalités à votre application Flight. Certains sont officiellement pris en charge par l'équipe Flight et d'autres sont des bibliothèques micro/lite pour vous aider à démarrer. +Flight est incroyablement extensible. Il existe un certain nombre de plugins qui peuvent être utilisés pour ajouter des fonctionnalités à votre application Flight. Certains sont officiellement supportés par l'équipe Flight et d'autres sont des bibliothèques micro/lite pour vous aider à démarrer. -## Documentation de l'API +## Documentation API -La documentation de l'API est cruciale pour toute API. Elle aide les développeurs à comprendre comment interagir avec votre API et ce qu'ils peuvent attendre en retour. Il existe quelques outils disponibles pour vous aider à générer la documentation de l'API pour vos projets Flight. +La documentation API est cruciale pour toute API. Elle aide les développeurs à comprendre comment interagir avec votre API et ce qu'ils peuvent attendre en retour. Il existe quelques outils disponibles pour vous aider à générer la documentation API pour vos projets Flight. - [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Article de blog écrit par Daniel Schreiber sur la façon d'utiliser la spécification OpenAPI avec FlightPHP pour construire votre API en adoptant une approche API-first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI est un excellent outil pour vous aider à générer la documentation de l'API pour vos projets Flight. Il est très facile à utiliser et peut être personnalisé pour répondre à vos besoins. Il s'agit de la bibliothèque PHP pour vous aider à générer la documentation Swagger. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI est un excellent outil pour vous aider à générer la documentation API pour vos projets Flight. Il est très facile à utiliser et peut être personnalisé selon vos besoins. C'est la bibliothèque PHP pour vous aider à générer la documentation Swagger. ## Surveillance des Performances des Applications (APM) @@ -16,31 +16,37 @@ La surveillance des performances des applications (APM) est cruciale pour toute ## Asynchrone -Flight est déjà un framework rapide, mais lui ajouter un turbo le rend encore plus amusant (et stimulant) ! +Flight est déjà un framework rapide, mais lui ajouter un turbo le rend encore plus amusant (et challenging) ! - [flightphp/async](/awesome-plugins/async) - Bibliothèque officielle Flight Async. Cette bibliothèque est une façon simple d'ajouter un traitement asynchrone à votre application. Elle utilise Swoole/Openswoole en arrière-plan pour fournir une façon simple et efficace d'exécuter des tâches de manière asynchrone. ## Autorisation/Permissions -L'autorisation et les permissions sont cruciales pour toute application qui nécessite des contrôles pour déterminer qui peut accéder à quoi. +L'autorisation et les permissions sont cruciales pour toute application qui nécessite des contrôles sur qui peut accéder à quoi. - officiel [flightphp/permissions](/awesome-plugins/permissions) - Bibliothèque officielle Flight Permissions. Cette bibliothèque est une façon simple d'ajouter des permissions au niveau utilisateur et application à votre application. +## Authentification + +L'authentification est essentielle pour les applications qui doivent vérifier l'identité des utilisateurs et sécuriser les points de terminaison API. + +- [firebase/php-jwt](/awesome-plugins/jwt) - Bibliothèque JSON Web Token (JWT) pour PHP. Une façon simple et sécurisée d'implémenter l'authentification basée sur des tokens dans vos applications Flight. Parfaite pour l'authentification API stateless, la protection des routes avec des middleware, et l'implémentation de flux d'autorisation de style OAuth. + ## Mise en Cache -La mise en cache est un excellent moyen d'accélérer votre application. Il existe un certain nombre de bibliothèques de mise en cache qui peuvent être utilisées avec Flight. +La mise en cache est une excellente façon d'accélérer votre application. Il existe un certain nombre de bibliothèques de mise en cache qui peuvent être utilisées avec Flight. -- officiel [flightphp/cache](/awesome-plugins/php-file-cache) - Classe PHP légère, simple et autonome pour la mise en cache en fichier +- officiel [flightphp/cache](/awesome-plugins/php-file-cache) - Classe de mise en cache légère, simple et autonome en fichier PHP ## CLI -Les applications CLI sont un excellent moyen d'interagir avec votre application. Vous pouvez les utiliser pour générer des contrôleurs, afficher toutes les routes, et plus encore. +Les applications CLI sont une excellente façon d'interagir avec votre application. Vous pouvez les utiliser pour générer des contrôleurs, afficher toutes les routes, et plus encore. - officiel [flightphp/runway](/awesome-plugins/runway) - Runway est une application CLI qui vous aide à gérer vos applications Flight. ## Cookies -Les cookies sont un excellent moyen de stocker de petites quantités de données côté client. Ils peuvent être utilisés pour stocker les préférences utilisateur, les paramètres d'application, et plus encore. +Les cookies sont une excellente façon de stocker de petites quantités de données côté client. Ils peuvent être utilisés pour stocker les préférences utilisateur, les paramètres d'application, et plus encore. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie est une bibliothèque PHP qui fournit une façon simple et efficace de gérer les cookies. @@ -48,14 +54,14 @@ Les cookies sont un excellent moyen de stocker de petites quantités de données Le débogage est crucial lorsque vous développez dans votre environnement local. Il existe quelques plugins qui peuvent améliorer votre expérience de débogage. -- [tracy/tracy](/awesome-plugins/tracy) - Il s'agit d'un gestionnaire d'erreurs complet qui peut être utilisé avec Flight. Il dispose d'un certain nombre de panneaux qui peuvent vous aider à déboguer votre application. Il est également très facile à étendre et à ajouter vos propres panneaux. +- [tracy/tracy](/awesome-plugins/tracy) - C'est un gestionnaire d'erreurs complet qui peut être utilisé avec Flight. Il dispose d'un certain nombre de panneaux qui peuvent vous aider à déboguer votre application. Il est également très facile à étendre et à ajouter vos propres panneaux. - officiel [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Utilisé avec le gestionnaire d'erreurs [Tracy](/awesome-plugins/tracy), ce plugin ajoute quelques panneaux supplémentaires pour aider au débogage spécifiquement pour les projets Flight. ## Bases de Données -Les bases de données sont au cœur de la plupart des applications. C'est ainsi que vous stockez et récupérez les données. Certaines bibliothèques de base de données sont simplement des wrappers pour écrire des requêtes et d'autres sont des ORMs complets. +Les bases de données sont au cœur de la plupart des applications. C'est ainsi que vous stockez et récupérez les données. Certaines bibliothèques de bases de données sont simplement des wrappers pour écrire des requêtes et d'autres sont des ORMs complets. -- officiel [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO officiel Flight qui fait partie du cœur. Il s'agit d'un wrapper simple pour aider à simplifier le processus d'écriture et d'exécution des requêtes. Ce n'est pas un ORM. +- officiel [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO officiel Flight qui fait partie du cœur. C'est un wrapper simple pour aider à simplifier le processus d'écriture et d'exécution des requêtes. Ce n'est pas un ORM. - officiel [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord officiel Flight. Excellente petite bibliothèque pour récupérer et stocker facilement des données dans votre base de données. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin pour suivre toutes les modifications de base de données pour votre projet. @@ -63,7 +69,7 @@ Les bases de données sont au cœur de la plupart des applications. C'est ainsi Le chiffrement est crucial pour toute application qui stocke des données sensibles. Chiffrer et déchiffrer les données n'est pas terriblement difficile, mais stocker correctement la clé de chiffrement [peut](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [être](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difficile](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). La chose la plus importante est de ne jamais stocker votre clé de chiffrement dans un répertoire public ou de l'engager dans votre dépôt de code. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Il s'agit d'une bibliothèque qui peut être utilisée pour chiffrer et déchiffrer des données. Se lancer est assez simple pour commencer à chiffrer et déchiffrer des données. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - C'est une bibliothèque qui peut être utilisée pour chiffrer et déchiffrer les données. Se lancer est assez simple pour commencer à chiffrer et déchiffrer les données. ## File d'Attente de Tâches @@ -73,25 +79,25 @@ Les files d'attente de tâches sont vraiment utiles pour traiter les tâches de ## Session -Les sessions ne sont pas vraiment utiles pour les API, mais pour construire une application web, les sessions peuvent être cruciales pour maintenir l'état et les informations de connexion. +Les sessions ne sont pas vraiment utiles pour les API mais pour construire une application web, les sessions peuvent être cruciales pour maintenir l'état et les informations de connexion. -- officiel [flightphp/session](/awesome-plugins/session) - Bibliothèque officielle Flight Session. Il s'agit d'une bibliothèque de session simple qui peut être utilisée pour stocker et récupérer les données de session. Elle utilise la gestion de session intégrée de PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - Gestionnaire de Sessions PHP (non-bloquant, flash, segment, chiffrement de session). Utilise PHP open_ssl pour le chiffrement/déchiffrement optionnel des données de session. +- officiel [flightphp/session](/awesome-plugins/session) - Bibliothèque officielle Flight Session. C'est une bibliothèque de session simple qui peut être utilisée pour stocker et récupérer les données de session. Elle utilise la gestion de session intégrée de PHP. +- [Ghostff/Session](/awesome-plugins/ghost-session) - Gestionnaire de Session PHP (non-bloquant, flash, segment, chiffrement de session). Utilise PHP open_ssl pour le chiffrement/déchiffrement optionnel des données de session. ## Modélisation La modélisation est au cœur de toute application web avec une interface utilisateur. Il existe un certain nombre de moteurs de modélisation qui peuvent être utilisés avec Flight. -- déprécié [flightphp/core View](/learn#views) - Il s'agit d'un moteur de modélisation très basique qui fait partie du cœur. Il n'est pas recommandé de l'utiliser si vous avez plus de quelques pages dans votre projet. -- [latte/latte](/awesome-plugins/latte) - Latte est un moteur de modélisation complet qui est très facile à utiliser et qui ressemble plus à une syntaxe PHP que Twig ou Smarty. Il est également très facile à étendre et à ajouter vos propres filtres et fonctions. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate est un puissant moteur de templates PHP avec compilation d'actifs, héritage de templates, et traitement de variables. Fonctionnalités : minification automatique CSS/JS, mise en cache, encodage Base64, et intégration optionnelle avec le framework PHP Flight. +- déprécié [flightphp/core View](/learn#views) - C'est un moteur de modélisation très basique qui fait partie du cœur. Il n'est pas recommandé de l'utiliser si vous avez plus de quelques pages dans votre projet. +- [latte/latte](/awesome-plugins/latte) - Latte est un moteur de modélisation complet qui est très facile à utiliser et se rapproche plus de la syntaxe PHP que Twig ou Smarty. Il est également très facile à étendre et à ajouter vos propres filtres et fonctions. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate est un puissant moteur de template PHP avec compilation d'actifs, héritage de templates, et traitement de variables. Fonctionnalités : minification automatique CSS/JS, mise en cache, encodage Base64, et intégration optionnelle avec le framework PHP Flight. ## Intégration WordPress -Vous souhaitez utiliser Flight dans votre projet WordPress ? Il existe un plugin pratique pour cela ! +Vous voulez utiliser Flight dans votre projet WordPress ? Il y a un plugin pratique pour cela ! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Ce plugin WordPress vous permet d'exécuter Flight directement aux côtés de WordPress. Il est parfait pour ajouter des API personnalisées, des microservices, ou même des applications complètes à votre site WordPress en utilisant le framework Flight. Super utile si vous voulez le meilleur des deux mondes ! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Ce plugin WordPress vous permet d'exécuter Flight juste à côté de WordPress. C'est parfait pour ajouter des API personnalisées, des microservices, ou même des applications complètes à votre site WordPress en utilisant le framework Flight. Super utile si vous voulez le meilleur des deux mondes ! ## Contribution -Vous avez un plugin que vous aimeriez partager ? Soumettez une demande de tirage pour l'ajouter à la liste ! \ No newline at end of file +Vous avez un plugin que vous aimeriez partager ? Soumettez une pull request pour l'ajouter à la liste ! \ No newline at end of file diff --git a/content/v3/fr/awesome-plugins/jwt.md b/content/v3/fr/awesome-plugins/jwt.md new file mode 100644 index 00000000..9bd87ca1 --- /dev/null +++ b/content/v3/fr/awesome-plugins/jwt.md @@ -0,0 +1,532 @@ +# Firebase JWT - Authentification par JSON Web Token pour Flight + +JWT (JSON Web Tokens) est une méthode compacte et sûre pour les URL pour représenter des revendications entre votre application et un client. Ils sont parfaits pour l'authentification d'API sans état — pas besoin de stockage de sessions côté serveur ! Ce guide vous montre comment intégrer [Firebase JWT](https://github.com/firebase/php-jwt) avec Flight pour une authentification sécurisée basée sur des tokens. + +Visitez le [dépôt Github](https://github.com/firebase/php-jwt) pour la documentation complète et les détails. + +## Qu'est-ce que JWT ? + +Un JSON Web Token est une chaîne qui contient trois parties : +1. **En-tête** : Métadonnées sur le token (algorithme, type) +2. **Charge utile** : Vos données (ID utilisateur, rôles, expiration, etc.) +3. **Signature** : Signature cryptographique pour vérifier l'authenticité + +Exemple de JWT : `eyJ0eXAiOiJKV1QiLCJhbGc...` (ça ressemble à du charabia, mais c'est des données structurées !) + +### Pourquoi utiliser JWT ? + +- **Sans état** : Pas besoin de stockage de sessions côté serveur — parfait pour les microservices et les API +- **Évolutif** : Fonctionne bien avec les équilibreurs de charge car il n'y a pas d'exigence d'affinité de session +- **Multi-domaines** : Peut être utilisé à travers différents domaines et services +- **Adapté aux mobiles** : Idéal pour les applications mobiles où les cookies ne fonctionnent pas bien +- **Standardisé** : Approche standard de l'industrie (RFC 7519) + +## Installation + +Installez via Composer : + +```bash +composer require firebase/php-jwt +``` + +## Utilisation de base + +Voici un exemple rapide de création et de vérification d'un JWT : + +```php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; + +// Votre clé secrète (GARDEZ-LA SÉCURISÉE !) +$secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; + +// Créer un token +$payload = [ + 'user_id' => 123, + 'username' => 'johndoe', + 'role' => 'admin', + 'iat' => time(), // Émis à + 'exp' => time() + 3600 // Expire dans 1 heure +]; + +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +echo "Token: " . $jwt; + +// Vérifier et décoder un token +try { + $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + echo "User ID: " . $decoded->user_id; +} catch (Exception $e) { + echo "Token invalide : " . $e->getMessage(); +} +``` + +## Middleware JWT pour Flight (Approche recommandée) + +La façon la plus courante et utile d'utiliser JWT avec Flight est en tant que **middleware** pour protéger vos routes API. Voici un exemple complet, prêt pour la production : + +### Étape 1 : Créer une classe de middleware JWT + +```php +// app/middleware/JwtMiddleware.php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; +use Firebase\JWT\ExpiredException; +use Firebase\JWT\SignatureInvalidException; +use flight\Engine; + +class JwtMiddleware { + + protected Engine $app; + protected string $secretKey; + + public function __construct(Engine $app) { + $this->app = $app; + // Stockez votre clé secrète dans app/config/config.php, PAS en dur ! + $this->secretKey = $app->get('config')['jwt_secret']; + } + + public function before(array $params) { + $authHeader = $this->app->request()->getHeader('Authorization'); + + // Vérifier si l'en-tête Authorization existe + if (empty($authHeader)) { + $this->app->jsonHalt(['error' => 'Aucun token d\'autorisation fourni'], 401); + } + + // Extraire le token du format "Bearer " + if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { + $this->app->jsonHalt(['error' => 'Format d\'autorisation invalide. Utilisez : Bearer '], 401); + } + + $jwt = $matches[1]; + + try { + // Décoder et vérifier le token + $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); + + // Stocker les données utilisateur dans la requête pour utilisation dans les gestionnaires de routes + $this->app->request()->data->user = $decoded; + + } catch (ExpiredException $e) { + $this->app->jsonHalt(['error' => 'Le token a expiré'], 401); + } catch (SignatureInvalidException $e) { + $this->app->jsonHalt(['error' => 'Signature de token invalide'], 401); + } catch (Exception $e) { + $this->app->jsonHalt(['error' => 'Token invalide : ' . $e->getMessage()], 401); + } + } +} +``` + +### Étape 2 : Enregistrer la clé secrète JWT dans votre configuration + +```php +// app/config/config.php +return [ + 'jwt_secret' => getenv('JWT_SECRET') ?: 'your-fallback-secret-for-development' +]; + +// app/config/bootstrap.php ou index.php +// assurez-vous d'ajouter cette ligne si vous voulez exposer la config à l'app +$app->set('config', $config); +``` + +> **Note de sécurité** : Ne mettez jamais votre clé secrète en dur ! Utilisez des variables d'environnement en production. + +### Étape 3 : Protéger vos routes avec le middleware + +```php +// Protéger une seule route +Flight::route('GET /api/user/profile', function() { + $user = Flight::request()->data->user; // Défini par le middleware + Flight::json([ + 'user_id' => $user->user_id, + 'username' => $user->username, + 'role' => $user->role + ]); +})->addMiddleware( JwtMiddleware::class); + +// Protéger un groupe entier de routes (plus courant !) +Flight::group('/api', function() { + Flight::route('GET /users', function() { /* ... */ }); + Flight::route('GET /posts', function() { /* ... */ }); + Flight::route('POST /posts', function() { /* ... */ }); + Flight::route('DELETE /posts/@id', function($id) { /* ... */ }); +}, [ JwtMiddleware::class ]); // Toutes les routes de ce groupe sont protégées ! +``` + +Pour plus de détails sur le middleware, consultez la [documentation middleware](/learn/middleware). + +## Cas d'utilisation courants + +### 1. Point de terminaison de connexion (Génération de token) + +Créez une route qui génère un JWT après une authentification réussie : + +```php +Flight::route('POST /api/login', function() { + $data = Flight::request()->data; + $username = $data->username ?? ''; + $password = $data->password ?? ''; + + // Valider les identifiants (exemple - utilisez votre propre logique !) + $user = validateUserCredentials($username, $password); + + if (!$user) { + Flight::jsonHalt(['error' => 'Identifiants invalides'], 401); + } + + // Générer JWT + $secretKey = Flight::get('config')['jwt_secret']; + $payload = [ + 'user_id' => $user->id, + 'username' => $user->username, + 'role' => $user->role, + 'iat' => time(), + 'exp' => time() + (60 * 60) // Expiration dans 1 heure + ]; + + $jwt = JWT::encode($payload, $secretKey, 'HS256'); + + Flight::json([ + 'success' => true, + 'token' => $jwt, + 'expires_in' => 3600 + ]); +}); + +function validateUserCredentials($username, $password) { + // Votre recherche en base de données et vérification de mot de passe ici + // Exemple : + $db = Flight::db(); + $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); + + if ($user && password_verify($password, $user['password_hash'])) { + return (object) [ + 'id' => $user['id'], + 'username' => $user['username'], + 'role' => $user['role'] + ]; + } + return null; +} +``` + +### 2. Flux de rafraîchissement de token + +Implémentez un système de token de rafraîchissement pour des sessions longues : + +```php +Flight::route('POST /api/login', function() { + // ... valider les identifiants ... + + $secretKey = Flight::get('config')['jwt_secret']; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + // Token d'accès à vie courte (15 minutes) + $accessToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + // Token de rafraîchissement à vie longue (7 jours) + $refreshToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'refresh', + 'iat' => time(), + 'exp' => time() + (7 * 24 * 60 * 60) + ], $refreshSecret, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'refresh_token' => $refreshToken, + 'expires_in' => 900 + ]); +}); + +Flight::route('POST /api/refresh', function() { + $refreshToken = Flight::request()->data->refresh_token ?? ''; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + try { + $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); + + // Vérifier que c'est un token de rafraîchissement + if ($decoded->type !== 'refresh') { + Flight::jsonHalt(['error' => 'Type de token invalide'], 401); + } + + // Générer un nouveau token d'accès + $secretKey = Flight::get('config')['jwt_secret']; + $accessToken = JWT::encode([ + 'user_id' => $decoded->user_id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'expires_in' => 900 + ]); + + } catch (Exception $e) { + Flight::jsonHalt(['error' => 'Token de rafraîchissement invalide'], 401); + } +}); +``` + +### 3. Contrôle d'accès basé sur les rôles + +Étendez votre middleware pour vérifier les rôles des utilisateurs : + +```php +class JwtRoleMiddleware { + + protected Engine $app; + protected array $allowedRoles; + + public function __construct(Engine $app, array $allowedRoles = []) { + $this->app = $app; + $this->allowedRoles = $allowedRoles; + } + + public function before(array $params) { + // Suppose que JwtMiddleware a déjà exécuté et défini les données utilisateur + $user = $this->app->request()->data->user ?? null; + + if (!$user) { + $this->app->jsonHalt(['error' => 'Authentification requise'], 401); + } + + // Vérifier si l'utilisateur a le rôle requis + if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { + $this->app->jsonHalt(['error' => 'Permissions insuffisantes'], 403); + } + } +} + +// Utilisation : Route admin seulement +Flight::route('DELETE /api/users/@id', function($id) { + // Logique de suppression d'utilisateur +})->addMiddleware([ + JwtMiddleware::class, + new JwtRoleMiddleware(Flight::app(), ['admin']) +]); +``` + +### 4. API publique avec limitation de taux par utilisateur + +Utilisez JWT pour suivre et limiter le taux des utilisateurs sans sessions : + +```php +class RateLimitMiddleware { + + public function before(array $params) { + $user = Flight::request()->data->user ?? null; + $userId = $user ? $user->user_id : Flight::request()->ip; + + $cacheKey = "rate_limit:$userId"; + // Assurez-vous d'avoir configuré un service de cache dans app/config/services.php + $requests = Flight::cache()->get($cacheKey, 0); + + if ($requests >= 100) { // 100 requêtes par heure + Flight::jsonHalt(['error' => 'Limite de taux dépassée'], 429); + } + + Flight::cache()->set($cacheKey, $requests + 1, 3600); + } +} +``` + +## Meilleures pratiques de sécurité + +### 1. Utiliser des clés secrètes fortes + +```php +// Générer une clé secrète sécurisée (exécutez une fois, sauvegardez dans le fichier .env) +$secretKey = base64_encode(random_bytes(32)); +echo $secretKey; // Stockez ceci dans votre fichier .env ! +``` + +### 2. Stocker les secrets dans les variables d'environnement + +```php +// Ne commitez jamais les secrets dans le contrôle de version ! +// Utilisez un fichier .env et une bibliothèque comme vlucas/phpdotenv + +// Fichier .env : +// JWT_SECRET=your-base64-encoded-secret-here +// JWT_REFRESH_SECRET=another-base64-encoded-secret-here + +// Vous pouvez aussi utiliser le fichier app/config/config.php pour stocker vos secrets +// assurez-vous simplement que le fichier de config n'est pas commité dans le contrôle de version +// return [ +// 'jwt_secret' => 'your-base64-encoded-secret-here', +// 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', +// ]; + +// Dans votre app : +$secretKey = getenv('JWT_SECRET'); +``` + +### 3. Définir des temps d'expiration appropriés + +```php +// Bonne pratique : tokens d'accès à vie courte +'exp' => time() + (15 * 60) // 15 minutes + +// Pour les tokens de rafraîchissement : expiration plus longue +'exp' => time() + (7 * 24 * 60 * 60) // 7 jours +``` + +### 4. Utiliser HTTPS en production + +Les JWT doivent **toujours** être transmis via HTTPS. N'envoyez jamais de tokens via HTTP pur en production ! + +### 5. Valider les revendications des tokens + +Validez toujours les revendications qui vous importent : + +```php +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + +// La vérification de l'expiration est gérée automatiquement par la bibliothèque +// Mais vous pouvez ajouter des validations personnalisées : +if ($decoded->iat > time()) { + throw new Exception('Token utilisé avant sa date d\'émission'); +} + +if (isset($decoded->nbf) && $decoded->nbf > time()) { + throw new Exception('Token pas encore valide'); +} +``` + +### 6. Considérer la liste noire des tokens pour la déconnexion + +Pour une sécurité supplémentaire, maintenez une liste noire de tokens invalidés : + +```php +Flight::route('POST /api/logout', function() { + $authHeader = Flight::request()->getHeader('Authorization'); + preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches); + $jwt = $matches[1]; + + // Extraire l'expiration du token + $decoded = Flight::request()->data->user; + $ttl = $decoded->exp - time(); + + // Stocker dans le cache/redis jusqu'à expiration + Flight::cache()->set("blacklist:$jwt", true, $ttl); + + Flight::json(['message' => 'Déconnexion réussie']); +}); + +// Ajoutez à votre JwtMiddleware : +public function before(array $params) { + // ... extraire JWT ... + + // Vérifier la liste noire + if (Flight::cache()->get("blacklist:$jwt")) { + $this->app->jsonHalt(['error' => 'Le token a été révoqué'], 401); + } + + // ... vérifier le token ... +} +``` + +## Algorithmes et types de clés + +Firebase JWT supporte plusieurs algorithmes : + +### Algorithmes symétriques (HMAC) +- **HS256** (Recommandé pour la plupart des apps) : Utilise une seule clé secrète +- **HS384**, **HS512** : Variantes plus fortes + +```php +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Algorithmes asymétriques (RSA/ECDSA) +- **RS256**, **RS384**, **RS512** : Utilise des paires de clés publique/privée +- **ES256**, **ES384**, **ES512** : Variantes à courbe elliptique + +```php +// Générer des clés : openssl genrsa -out private.key 2048 +// openssl rsa -in private.key -pubout -out public.key + +$privateKey = file_get_contents('/path/to/private.key'); +$publicKey = file_get_contents('/path/to/public.key'); + +// Encoder avec la clé privée +$jwt = JWT::encode($payload, $privateKey, 'RS256'); + +// Décoder avec la clé publique +$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); +``` + +> **Quand utiliser RSA** : Utilisez RSA lorsque vous devez distribuer la clé publique pour la vérification (ex. : microservices, intégrations tierces). Pour une seule application, HS256 est plus simple et suffisant. + +## Dépannage + +### Erreur "Token expiré" +La revendication `exp` de votre token est dans le passé. Émettez un nouveau token ou implémentez le rafraîchissement de token. + +### "Échec de la vérification de signature" +- Vous utilisez une clé secrète différente pour décoder que pour encoder +- Le token a été modifié +- Décalage d'horloge entre les serveurs (ajoutez un tampon de tolérance) + +```php +use Firebase\JWT\JWT; + +JWT::$leeway = 60; // Autoriser 60 secondes de décalage d'horloge +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Token non envoyé dans les requêtes +Assurez-vous que votre client envoie l'en-tête `Authorization` : + +```javascript +// Exemple JavaScript +fetch('/api/users', { + headers: { + 'Authorization': 'Bearer ' + token + } +}); +``` + +## Méthodes + +La bibliothèque Firebase JWT fournit ces méthodes principales : + +- `JWT::encode(array $payload, string $key, string $alg)` : Crée un JWT à partir d'une charge utile +- `JWT::decode(string $jwt, Key $key)` : Décode et vérifie un JWT +- `JWT::urlsafeB64Encode(string $input)` : Encodage Base64 URL-safe +- `JWT::urlsafeB64Decode(string $input)` : Décodage Base64 URL-safe +- `JWT::$leeway` : Propriété statique pour définir la tolérance temporelle pour la validation (en secondes) + +## Pourquoi utiliser cette bibliothèque ? + +- **Standard de l'industrie** : Firebase JWT est la bibliothèque JWT la plus populaire et la plus fiable pour PHP +- **Maintenance active** : Maintenue par l'équipe Google/Firebase +- **Axée sur la sécurité** : Mises à jour régulières et correctifs de sécurité +- **API simple** : Facile à comprendre et à implémenter +- **Bien documentée** : Documentation étendue et support communautaire +- **Flexible** : Supporte plusieurs algorithmes et options configurables + +## Voir aussi + +- [Dépôt Github de Firebase JWT](https://github.com/firebase/php-jwt) +- [JWT.io](https://jwt.io/) - Déboguer et décoder les JWT +- [RFC 7519](https://tools.ietf.org/html/rfc7519) - Spécification officielle JWT +- [Documentation Middleware de Flight](/learn/middleware) +- [Plugin Session de Flight](/awesome-plugins/session) - Pour l'authentification basée sur sessions traditionnelles + +## Licence + +La bibliothèque Firebase JWT est sous licence BSD 3-Clause. Consultez le [dépôt Github](https://github.com/firebase/php-jwt) pour les détails. \ No newline at end of file diff --git a/content/v3/id/awesome-plugins/awesome_plugins.md b/content/v3/id/awesome-plugins/awesome_plugins.md index 50725e91..1895bdd8 100644 --- a/content/v3/id/awesome-plugins/awesome_plugins.md +++ b/content/v3/id/awesome-plugins/awesome_plugins.md @@ -1,18 +1,18 @@ # Plugin Hebat -Flight sangat dapat diperluas. Ada sejumlah plugin yang dapat digunakan untuk menambahkan fungsionalitas ke aplikasi Flight Anda. Beberapa didukung secara resmi oleh Tim Flight dan yang lain adalah pustaka mikro/lite untuk membantu Anda memulai. +Flight sangat mudah diperluas. Ada sejumlah plugin yang dapat digunakan untuk menambahkan fungsionalitas ke aplikasi Flight Anda. Beberapa didukung secara resmi oleh Tim Flight dan yang lain adalah pustaka mikro/lite untuk membantu Anda memulai. ## Dokumentasi API Dokumentasi API sangat penting untuk API apa pun. Ini membantu pengembang memahami cara berinteraksi dengan API Anda dan apa yang diharapkan sebagai balasan. Ada beberapa alat yang tersedia untuk membantu Anda menghasilkan dokumentasi API untuk Proyek Flight Anda. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Posting blog yang ditulis oleh Daniel Schreiber tentang cara menggunakan Spesifikasi OpenAPI dengan FlightPHP untuk membangun API Anda menggunakan pendekatan API first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI adalah alat hebat untuk membantu Anda menghasilkan dokumentasi API untuk proyek Flight Anda. Ini sangat mudah digunakan dan dapat disesuaikan sesuai kebutuhan Anda. Ini adalah pustaka PHP untuk membantu Anda menghasilkan dokumentasi Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Posting blog yang ditulis oleh Daniel Schreiber tentang cara menggunakan Spesifikasi OpenAPI dengan FlightPHP untuk membangun API Anda menggunakan pendekatan API pertama. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI adalah alat yang hebat untuk membantu Anda menghasilkan dokumentasi API untuk proyek Flight Anda. Ini sangat mudah digunakan dan dapat disesuaikan sesuai kebutuhan Anda. Ini adalah pustaka PHP untuk membantu Anda menghasilkan dokumentasi Swagger. ## Pemantauan Kinerja Aplikasi (APM) -Pemantauan Kinerja Aplikasi (APM) sangat penting untuk aplikasi apa pun. Ini membantu Anda memahami bagaimana aplikasi Anda berkinerja dan di mana titik lemahnya. Ada sejumlah alat APM yang dapat digunakan dengan Flight. -- resmi [flightphp/apm](/awesome-plugins/apm) - Flight APM adalah pustaka APM sederhana yang dapat digunakan untuk memantau aplikasi Flight Anda. Ini dapat digunakan untuk memantau kinerja aplikasi Anda dan membantu Anda mengidentifikasi titik lemah. +Pemantauan Kinerja Aplikasi (APM) sangat penting untuk aplikasi apa pun. Ini membantu Anda memahami bagaimana aplikasi Anda berkinerja dan di mana kemacetan berada. Ada sejumlah alat APM yang dapat digunakan dengan Flight. +- resmi [flightphp/apm](/awesome-plugins/apm) - Flight APM adalah pustaka APM sederhana yang dapat digunakan untuk memantau aplikasi Flight Anda. Ini dapat digunakan untuk memantau kinerja aplikasi Anda dan membantu Anda mengidentifikasi kemacetan. ## Async @@ -26,11 +26,17 @@ Otorisasi dan Izin sangat penting untuk aplikasi apa pun yang memerlukan kontrol - resmi [flightphp/permissions](/awesome-plugins/permissions) - Pustaka Permissions Flight resmi. Pustaka ini adalah cara sederhana untuk menambahkan izin tingkat pengguna dan aplikasi ke aplikasi Anda. +## Otentikasi + +Otentikasi sangat penting untuk aplikasi yang perlu memverifikasi identitas pengguna dan mengamankan endpoint API. + +- [firebase/php-jwt](/awesome-plugins/jwt) - Pustaka JSON Web Token (JWT) untuk PHP. Cara sederhana dan aman untuk mengimplementasikan otentikasi berbasis token di aplikasi Flight Anda. Sempurna untuk otentikasi API tanpa status, melindungi rute dengan middleware, dan mengimplementasikan alur otorisasi gaya OAuth. + ## Penyimpanan Cache Penyimpanan cache adalah cara hebat untuk mempercepat aplikasi Anda. Ada sejumlah pustaka caching yang dapat digunakan dengan Flight. -- resmi [flightphp/cache](/awesome-plugins/php-file-cache) - Kelas caching in-file PHP yang ringan, sederhana, dan standalone +- resmi [flightphp/cache](/awesome-plugins/php-file-cache) - Kelas caching dalam file PHP yang ringan, sederhana, dan mandiri ## CLI @@ -40,13 +46,13 @@ Aplikasi CLI adalah cara hebat untuk berinteraksi dengan aplikasi Anda. Anda dap ## Cookies -Cookies adalah cara hebat untuk menyimpan potongan data kecil di sisi klien. Mereka dapat digunakan untuk menyimpan preferensi pengguna, pengaturan aplikasi, dan banyak lagi. +Cookies adalah cara hebat untuk menyimpan bit data kecil di sisi klien. Mereka dapat digunakan untuk menyimpan preferensi pengguna, pengaturan aplikasi, dan banyak lagi. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie adalah pustaka PHP yang menyediakan cara sederhana dan efektif untuk mengelola cookies. ## Debugging -Debugging sangat penting ketika Anda mengembangkan di lingkungan lokal Anda. Ada beberapa plugin yang dapat meningkatkan pengalaman debugging Anda. +Debugging sangat penting saat Anda mengembangkan di lingkungan lokal Anda. Ada beberapa plugin yang dapat meningkatkan pengalaman debugging Anda. - [tracy/tracy](/awesome-plugins/tracy) - Ini adalah penanganan kesalahan lengkap yang dapat digunakan dengan Flight. Ini memiliki sejumlah panel yang dapat membantu Anda mendebug aplikasi Anda. Ini juga sangat mudah untuk diperluas dan menambahkan panel Anda sendiri. - resmi [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Digunakan dengan penanganan kesalahan [Tracy](/awesome-plugins/tracy), plugin ini menambahkan beberapa panel tambahan untuk membantu debugging khusus untuk proyek Flight. @@ -67,7 +73,7 @@ Enkripsi sangat penting untuk aplikasi apa pun yang menyimpan data sensitif. Men ## Antrian Pekerjaan -Antrian pekerjaan sangat membantu untuk memproses tugas secara asinkron. Ini bisa berupa mengirim email, memproses gambar, atau apa pun yang tidak perlu dilakukan secara real time. +Antrian pekerjaan sangat membantu untuk memproses tugas secara asinkron. Ini bisa berupa mengirim email, memproses gambar, atau apa pun yang tidak perlu dilakukan secara real-time. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue adalah pustaka yang dapat digunakan untuk memproses pekerjaan secara asinkron. Ini dapat digunakan dengan beanstalkd, MySQL/MariaDB, SQLite, dan PostgreSQL. @@ -82,9 +88,9 @@ Sesi tidak terlalu berguna untuk API tetapi untuk membangun aplikasi web, sesi b Templating adalah inti dari aplikasi web apa pun dengan UI. Ada sejumlah mesin templating yang dapat digunakan dengan Flight. -- deprecated [flightphp/core View](/learn#views) - Ini adalah mesin templating dasar yang merupakan bagian dari inti. Tidak direkomendasikan untuk digunakan jika Anda memiliki lebih dari beberapa halaman di proyek Anda. +- deprecated [flightphp/core View](/learn#views) - Ini adalah mesin templating dasar yang merupakan bagian dari inti. Tidak disarankan digunakan jika Anda memiliki lebih dari beberapa halaman di proyek Anda. - [latte/latte](/awesome-plugins/latte) - Latte adalah mesin templating lengkap yang sangat mudah digunakan dan terasa lebih dekat dengan sintaks PHP daripada Twig atau Smarty. Ini juga sangat mudah untuk diperluas dan menambahkan filter dan fungsi Anda sendiri. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate adalah mesin template PHP yang kuat dengan kompilasi aset, pewarisan template, dan pemrosesan variabel. Fitur minifikasi CSS/JS otomatis, caching, pengkodean Base64, dan integrasi framework PHP Flight opsional. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate adalah mesin template PHP yang kuat dengan kompilasi aset, pewarisan template, dan pemrosesan variabel. Fitur minifikasi CSS/JS otomatis, caching, pengkodean Base64, dan integrasi opsional dengan framework PHP Flight. ## Integrasi WordPress @@ -94,4 +100,4 @@ Ingin menggunakan Flight di proyek WordPress Anda? Ada plugin yang berguna untuk ## Berkontribusi -Punya plugin yang ingin Anda bagikan? Kirimkan pull request untuk menambahkannya ke daftar! \ No newline at end of file +Punya plugin yang ingin dibagikan? Kirimkan pull request untuk menambahkannya ke daftar! \ No newline at end of file diff --git a/content/v3/id/awesome-plugins/jwt.md b/content/v3/id/awesome-plugins/jwt.md new file mode 100644 index 00000000..2349fab2 --- /dev/null +++ b/content/v3/id/awesome-plugins/jwt.md @@ -0,0 +1,532 @@ +# Firebase JWT - Autentikasi JSON Web Token untuk Flight + +JWT (JSON Web Tokens) adalah cara yang ringkas dan aman untuk URL untuk merepresentasikan klaim antara aplikasi Anda dan klien. Mereka sempurna untuk autentikasi API tanpa state—tidak perlu penyimpanan sesi di sisi server! Panduan ini menunjukkan cara mengintegrasikan [Firebase JWT](https://github.com/firebase/php-jwt) dengan Flight untuk autentikasi berbasis token yang aman. + +Kunjungi [repositori Github](https://github.com/firebase/php-jwt) untuk dokumentasi lengkap dan detail. + +## Apa itu JWT? + +JSON Web Token adalah string yang berisi tiga bagian: +1. **Header**: Metadata tentang token (algoritma, tipe) +2. **Payload**: Data Anda (ID pengguna, peran, kedaluwarsa, dll.) +3. **Signature**: Tanda tangan kriptografis untuk memverifikasi keaslian + +Contoh JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (terlihat seperti sampah, tapi ini data terstruktur!) + +### Mengapa Menggunakan JWT? + +- **Tanpa State**: Tidak perlu penyimpanan sesi di sisi server—sempurna untuk microservices dan API +- **Skalabel**: Bekerja dengan baik dengan load balancer karena tidak ada persyaratan affinity sesi +- **Cross-Domain**: Dapat digunakan di berbagai domain dan layanan +- **Ramah Mobile**: Bagus untuk aplikasi mobile di mana cookie mungkin tidak bekerja dengan baik +- **Standar**: Pendekatan standar industri (RFC 7519) + +## Instalasi + +Instal melalui Composer: + +```bash +composer require firebase/php-jwt +``` + +## Penggunaan Dasar + +Berikut adalah contoh cepat untuk membuat dan memverifikasi JWT: + +```php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; + +// Kunci rahasia Anda (JAGA INI AMAN!) +$secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; + +// Buat token +$payload = [ + 'user_id' => 123, + 'username' => 'johndoe', + 'role' => 'admin', + 'iat' => time(), // Diterbitkan pada + 'exp' => time() + 3600 // Berakhir dalam 1 jam +]; + +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +echo "Token: " . $jwt; + +// Verifikasi dan dekode token +try { + $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + echo "User ID: " . $decoded->user_id; +} catch (Exception $e) { + echo "Token tidak valid: " . $e->getMessage(); +} +``` + +## Middleware JWT untuk Flight (Pendekatan yang Direkomendasikan) + +Cara paling umum dan berguna untuk menggunakan JWT dengan Flight adalah sebagai **middleware** untuk melindungi rute API Anda. Berikut adalah contoh lengkap yang siap produksi: + +### Langkah 1: Buat Kelas Middleware JWT + +```php +// app/middleware/JwtMiddleware.php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; +use Firebase\JWT\ExpiredException; +use Firebase\JWT\SignatureInvalidException; +use flight\Engine; + +class JwtMiddleware { + + protected Engine $app; + protected string $secretKey; + + public function __construct(Engine $app) { + $this->app = $app; + // Simpan kunci rahasia Anda di app/config/config.php, BUKAN hardcoded! + $this->secretKey = $app->get('config')['jwt_secret']; + } + + public function before(array $params) { + $authHeader = $this->app->request()->getHeader('Authorization'); + + // Periksa apakah header Authorization ada + if (empty($authHeader)) { + $this->app->jsonHalt(['error' => 'Tidak ada token otorisasi yang disediakan'], 401); + } + + // Ekstrak token dari format "Bearer " + if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { + $this->app->jsonHalt(['error' => 'Format otorisasi tidak valid. Gunakan: Bearer '], 401); + } + + $jwt = $matches[1]; + + try { + // Dekode dan verifikasi token + $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); + + // Simpan data pengguna di request untuk digunakan di handler rute + $this->app->request()->data->user = $decoded; + + } catch (ExpiredException $e) { + $this->app->jsonHalt(['error' => 'Token telah kedaluwarsa'], 401); + } catch (SignatureInvalidException $e) { + $this->app->jsonHalt(['error' => 'Tanda tangan token tidak valid'], 401); + } catch (Exception $e) { + $this->app->jsonHalt(['error' => 'Token tidak valid: ' . $e->getMessage()], 401); + } + } +} +``` + +### Langkah 2: Daftarkan Kunci Rahasia JWT di Konfigurasi Anda + +```php +// app/config/config.php +return [ + 'jwt_secret' => getenv('JWT_SECRET') ?: 'your-fallback-secret-for-development' +]; + +// app/config/bootstrap.php atau index.php +// pastikan untuk menambahkan baris ini jika Anda ingin mengekspos konfigurasi ke app +$app->set('config', $config); +``` + +> **Catatan Keamanan**: Jangan pernah hardcoded kunci rahasia Anda! Gunakan variabel lingkungan di produksi. + +### Langkah 3: Lindungi Rute Anda dengan Middleware + +```php +// Lindungi satu rute +Flight::route('GET /api/user/profile', function() { + $user = Flight::request()->data->user; // Ditetapkan oleh middleware + Flight::json([ + 'user_id' => $user->user_id, + 'username' => $user->username, + 'role' => $user->role + ]); +})->addMiddleware( JwtMiddleware::class); + +// Lindungi seluruh grup rute (lebih umum!) +Flight::group('/api', function() { + Flight::route('GET /users', function() { /* ... */ }); + Flight::route('GET /posts', function() { /* ... */ }); + Flight::route('POST /posts', function() { /* ... */ }); + Flight::route('DELETE /posts/@id', function($id) { /* ... */ }); +}, [ JwtMiddleware::class ]); // Semua rute di grup ini dilindungi! +``` + +Untuk detail lebih lanjut tentang middleware, lihat [dokumentasi middleware](/learn/middleware). + +## Kasus Penggunaan Umum + +### 1. Endpoint Login (Pembuatan Token) + +Buat rute yang menghasilkan JWT setelah autentikasi berhasil: + +```php +Flight::route('POST /api/login', function() { + $data = Flight::request()->data; + $username = $data->username ?? ''; + $password = $data->password ?? ''; + + // Validasi kredensial (contoh - gunakan logika Anda sendiri!) + $user = validateUserCredentials($username, $password); + + if (!$user) { + Flight::jsonHalt(['error' => 'Kredensial tidak valid'], 401); + } + + // Hasilkan JWT + $secretKey = Flight::get('config')['jwt_secret']; + $payload = [ + 'user_id' => $user->id, + 'username' => $user->username, + 'role' => $user->role, + 'iat' => time(), + 'exp' => time() + (60 * 60) // Kedaluwarsa 1 jam + ]; + + $jwt = JWT::encode($payload, $secretKey, 'HS256'); + + Flight::json([ + 'success' => true, + 'token' => $jwt, + 'expires_in' => 3600 + ]); +}); + +function validateUserCredentials($username, $password) { + // Pencarian database dan verifikasi kata sandi Anda di sini + // Contoh: + $db = Flight::db(); + $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); + + if ($user && password_verify($password, $user['password_hash'])) { + return (object) [ + 'id' => $user['id'], + 'username' => $user['username'], + 'role' => $user['role'] + ]; + } + return null; +} +``` + +### 2. Alur Refresh Token + +Implementasikan sistem refresh token untuk sesi yang panjang umurnya: + +```php +Flight::route('POST /api/login', function() { + // ... validasi kredensial ... + + $secretKey = Flight::get('config')['jwt_secret']; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + // Access token yang pendek umurnya (15 menit) + $accessToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + // Refresh token yang panjang umurnya (7 hari) + $refreshToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'refresh', + 'iat' => time(), + 'exp' => time() + (7 * 24 * 60 * 60) + ], $refreshSecret, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'refresh_token' => $refreshToken, + 'expires_in' => 900 + ]); +}); + +Flight::route('POST /api/refresh', function() { + $refreshToken = Flight::request()->data->refresh_token ?? ''; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + try { + $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); + + // Verifikasi ini adalah refresh token + if ($decoded->type !== 'refresh') { + Flight::jsonHalt(['error' => 'Tipe token tidak valid'], 401); + } + + // Hasilkan access token baru + $secretKey = Flight::get('config')['jwt_secret']; + $accessToken = JWT::encode([ + 'user_id' => $decoded->user_id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'expires_in' => 900 + ]); + + } catch (Exception $e) { + Flight::jsonHalt(['error' => 'Refresh token tidak valid'], 401); + } +}); +``` + +### 3. Kontrol Akses Berdasarkan Peran + +Perluas middleware Anda untuk memeriksa peran pengguna: + +```php +class JwtRoleMiddleware { + + protected Engine $app; + protected array $allowedRoles; + + public function __construct(Engine $app, array $allowedRoles = []) { + $this->app = $app; + $this->allowedRoles = $allowedRoles; + } + + public function before(array $params) { + // Asumsikan JwtMiddleware sudah berjalan dan menetapkan data pengguna + $user = $this->app->request()->data->user ?? null; + + if (!$user) { + $this->app->jsonHalt(['error' => 'Autentikasi diperlukan'], 401); + } + + // Periksa apakah pengguna memiliki peran yang diperlukan + if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { + $this->app->jsonHalt(['error' => 'Izin tidak mencukupi'], 403); + } + } +} + +// Penggunaan: Rute hanya untuk admin +Flight::route('DELETE /api/users/@id', function($id) { + // Logika hapus pengguna +})->addMiddleware([ + JwtMiddleware::class, + new JwtRoleMiddleware(Flight::app(), ['admin']) +]); +``` + +### 4. API Publik dengan Rate Limiting berdasarkan Pengguna + +Gunakan JWT untuk melacak dan membatasi laju pengguna tanpa sesi: + +```php +class RateLimitMiddleware { + + public function before(array $params) { + $user = Flight::request()->data->user ?? null; + $userId = $user ? $user->user_id : Flight::request()->ip; + + $cacheKey = "rate_limit:$userId"; + // Pastikan Anda menyiapkan layanan cache di app/config/services.php + $requests = Flight::cache()->get($cacheKey, 0); + + if ($requests >= 100) { // 100 permintaan per jam + Flight::jsonHalt(['error' => 'Batas laju terlampaui'], 429); + } + + Flight::cache()->set($cacheKey, $requests + 1, 3600); + } +} +``` + +## Praktik Terbaik Keamanan + +### 1. Gunakan Kunci Rahasia yang Kuat + +```php +// Hasilkan kunci rahasia yang aman (jalankan sekali, simpan ke file .env) +$secretKey = base64_encode(random_bytes(32)); +echo $secretKey; // Simpan ini di file .env Anda! +``` + +### 2. Simpan Rahasia di Variabel Lingkungan + +```php +// Jangan pernah commit rahasia ke kontrol versi! +// Gunakan file .env dan library seperti vlucas/phpdotenv + +// File .env: +// JWT_SECRET=your-base64-encoded-secret-here +// JWT_REFRESH_SECRET=another-base64-encoded-secret-here + +// Anda juga bisa menggunakan file app/config/config.php untuk menyimpan rahasia Anda +// pastikan file konfigurasi tidak di-commit ke kontrol versi +// return [ +// 'jwt_secret' => 'your-base64-encoded-secret-here', +// 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', +// ]; + +// Di aplikasi Anda: +$secretKey = getenv('JWT_SECRET'); +``` + +### 3. Atur Waktu Kedaluwarsa yang Sesuai + +```php +// Praktik baik: access token yang pendek umurnya +'exp' => time() + (15 * 60) // 15 menit + +// Untuk refresh token: kedaluwarsa lebih lama +'exp' => time() + (7 * 24 * 60 * 60) // 7 hari +``` + +### 4. Gunakan HTTPS di Produksi + +JWT harus **selalu** dikirim melalui HTTPS. Jangan pernah kirim token melalui HTTP biasa di produksi! + +### 5. Validasi Klaim Token + +Selalu validasi klaim yang Anda pedulikan: + +```php +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + +// Pemeriksaan kedaluwarsa ditangani secara otomatis oleh library +// Tapi Anda bisa menambahkan validasi kustom: +if ($decoded->iat > time()) { + throw new Exception('Token digunakan sebelum diterbitkan'); +} + +if (isset($decoded->nbf) && $decoded->nbf > time()) { + throw new Exception('Token belum valid'); +} +``` + +### 6. Pertimbangkan Blacklisting Token untuk Logout + +Untuk keamanan ekstra, pertahankan daftar hitam token yang dibatalkan: + +```php +Flight::route('POST /api/logout', function() { + $authHeader = Flight::request()->getHeader('Authorization'); + preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches); + $jwt = $matches[1]; + + // Ekstrak kedaluwarsa token + $decoded = Flight::request()->data->user; + $ttl = $decoded->exp - time(); + + // Simpan di cache/redis hingga kedaluwarsa + Flight::cache()->set("blacklist:$jwt", true, $ttl); + + Flight::json(['message' => 'Berhasil logout']); +}); + +// Tambahkan ke JwtMiddleware Anda: +public function before(array $params) { + // ... ekstrak JWT ... + + // Periksa daftar hitam + if (Flight::cache()->get("blacklist:$jwt")) { + $this->app->jsonHalt(['error' => 'Token telah dicabut'], 401); + } + + // ... verifikasi token ... +} +``` + +## Algoritma dan Tipe Kunci + +Firebase JWT mendukung beberapa algoritma: + +### Algoritma Simetris (HMAC) +- **HS256** (Direkomendasikan untuk sebagian besar aplikasi): Menggunakan satu kunci rahasia +- **HS384**, **HS512**: Varian yang lebih kuat + +```php +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Algoritma Asimetris (RSA/ECDSA) +- **RS256**, **RS384**, **RS512**: Menggunakan pasangan kunci publik/privat +- **ES256**, **ES384**, **ES512**: Varian kurva eliptik + +```php +// Hasilkan kunci: openssl genrsa -out private.key 2048 +// openssl rsa -in private.key -pubout -out public.key + +$privateKey = file_get_contents('/path/to/private.key'); +$publicKey = file_get_contents('/path/to/public.key'); + +// Enkode dengan kunci privat +$jwt = JWT::encode($payload, $privateKey, 'RS256'); + +// Dekode dengan kunci publik +$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); +``` + +> **Kapan menggunakan RSA**: Gunakan RSA ketika Anda perlu mendistribusikan kunci publik untuk verifikasi (misalnya, microservices, integrasi pihak ketiga). Untuk aplikasi tunggal, HS256 lebih sederhana dan cukup. + +## Pemecahan Masalah + +### Kesalahan "Token kedaluwarsa" +Klaim `exp` token Anda sudah lewat. Terbitkan token baru atau implementasikan refresh token. + +### "Verifikasi tanda tangan gagal" +- Anda menggunakan kunci rahasia yang berbeda untuk dekode daripada yang digunakan untuk encode +- Token telah dimanipulasi +- Perbedaan jam antara server (tambahkan buffer leeway) + +```php +use Firebase\JWT\JWT; + +JWT::$leeway = 60; // Izinkan 60 detik perbedaan jam +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Token Tidak Dikirim dalam Permintaan +Pastikan klien Anda mengirim header `Authorization`: + +```javascript +// Contoh JavaScript +fetch('/api/users', { + headers: { + 'Authorization': 'Bearer ' + token + } +}); +``` + +## Metode + +Library Firebase JWT menyediakan metode inti ini: + +- `JWT::encode(array $payload, string $key, string $alg)`: Membuat JWT dari payload +- `JWT::decode(string $jwt, Key $key)`: Mendekode dan memverifikasi JWT +- `JWT::urlsafeB64Encode(string $input)`: Encoding Base64 URL-safe +- `JWT::urlsafeB64Decode(string $input)`: Decoding Base64 URL-safe +- `JWT::$leeway`: Properti statis untuk mengatur leeway waktu untuk validasi (dalam detik) + +## Mengapa Menggunakan Library Ini? + +- **Standar Industri**: Firebase JWT adalah library JWT paling populer dan tepercaya untuk PHP +- **Pemeliharaan Aktif**: Dipelihara oleh tim Google/Firebase +- **Fokus Keamanan**: Pembaruan rutin dan patch keamanan +- **API Sederhana**: Mudah dipahami dan diimplementasikan +- **Dokumentasi Lengkap**: Dokumentasi ekstensif dan dukungan komunitas +- **Fleksibel**: Mendukung beberapa algoritma dan opsi yang dapat dikonfigurasi + +## Lihat Juga + +- [Repositori Github Firebase JWT](https://github.com/firebase/php-jwt) +- [JWT.io](https://jwt.io/) - Debug dan dekode JWT +- [RFC 7519](https://tools.ietf.org/html/rfc7519) - Spesifikasi resmi JWT +- [Dokumentasi Middleware Flight](/learn/middleware) +- [Plugin Sesi Flight](/awesome-plugins/session) - Untuk autentikasi berbasis sesi tradisional + +## Lisensi + +Library Firebase JWT dilisensikan di bawah Lisensi BSD 3-Clause. Lihat [repositori Github](https://github.com/firebase/php-jwt) untuk detail. \ No newline at end of file diff --git a/content/v3/ja/awesome-plugins/awesome_plugins.md b/content/v3/ja/awesome-plugins/awesome_plugins.md index 4abe21ea..d96af062 100644 --- a/content/v3/ja/awesome-plugins/awesome_plugins.md +++ b/content/v3/ja/awesome-plugins/awesome_plugins.md @@ -1,73 +1,79 @@ # 素晴らしいプラグイン -Flight は非常に拡張性が高いです。Flight アプリケーションに機能を追加するために使用できるプラグインがいくつかあります。一部は Flight チームによって公式にサポートされており、他のものはあなたが始めるのを助けるマイクロ/ライトライブラリです。 +Flight は非常に拡張性が高いです。Flight アプリケーションに機能を追加するために使用できるプラグインがいくつかあります。一部は Flight Team によって公式にサポートされており、他のものは開始するためのマイクロ/ライトライブラリです。 ## API ドキュメント -API ドキュメントは、API にとって非常に重要です。開発者が API とどのようにやり取りし、返されるものを期待するかを理解するのに役立ちます。Flight プロジェクトの API ドキュメントを生成するのに役立つツールがいくつかあります。 +API ドキュメントは任意の API にとって重要です。開発者が API とどのようにやり取りするかを理解し、返されるものを期待するのに役立ちます。Flight プロジェクトの API ドキュメントを生成するのに役立つツールがいくつかあります。 -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber によるブログ記事で、OpenAPI Spec を FlightPHP と使用して API ファーストアプローチで API を構築する方法について説明しています。 +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber によるブログ投稿で、OpenAPI Spec を FlightPHP と使用して API ファーストアプローチで API を構築する方法について説明しています。 - [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI は、Flight プロジェクトの API ドキュメントを生成するのに役立つ優れたツールです。非常に使いやすく、ニーズに合わせてカスタマイズできます。これは Swagger ドキュメントを生成するための PHP ライブラリです。 ## アプリケーション パフォーマンス監視 (APM) -アプリケーション パフォーマンス監視 (APM) は、アプリケーションにとって非常に重要です。アプリケーションのパフォーマンスを理解し、ボトルネックがどこにあるかを特定するのに役立ちます。Flight で使用できる APM ツールがいくつかあります。 +アプリケーション パフォーマンス監視 (APM) は任意のアプリケーションにとって重要です。アプリケーションのパフォーマンスを理解し、ボトルネックがどこにあるかを特定するのに役立ちます。Flight で使用できる APM ツールがいくつかあります。 - official [flightphp/apm](/awesome-plugins/apm) - Flight APM は、Flight アプリケーションを監視するために使用できるシンプルな APM ライブラリです。アプリケーションのパフォーマンスを監視し、ボトルネックを特定するのに役立ちます。 -## 非同期 +## Async -Flight はすでに高速なフレームワークですが、それにターボエンジンを追加するとすべてがより楽しく(そして挑戦的)になります! +Flight はすでに高速なフレームワークですが、ターボエンジンを追加するとすべてがより楽しく(そして挑戦的)になります! -- [flightphp/async](/awesome-plugins/async) - 公式の Flight Async ライブラリです。このライブラリは、アプリケーションに非同期処理を追加するシンプルな方法です。バックエンドで Swoole/Openswoole を使用して、タスクを非同期で実行するためのシンプルで効果的な方法を提供します。 +- [flightphp/async](/awesome-plugins/async) - 公式の Flight Async ライブラリです。このライブラリは、アプリケーションに非同期処理を追加するシンプルな方法です。Swoole/Openswoole を内部で使用して、タスクを非同期で実行するシンプルで効果的な方法を提供します。 ## 認可/権限 -認可と権限は、誰が何にアクセスできるかを制御する必要があるアプリケーションにとって非常に重要です。 +認可と権限は、誰が何にアクセスできるかを制御する必要がある任意のアプリケーションにとって重要です。 -- official [flightphp/permissions](/awesome-plugins/permissions) - 公式の Flight Permissions ライブラリです。このライブラリは、アプリケーションにユーザーおよびアプリケーション レベルの権限を追加するシンプルな方法です。 +- official [flightphp/permissions](/awesome-plugins/permissions) - 公式の Flight Permissions ライブラリです。このライブラリは、アプリケーションにユーザーおよびアプリケーション レベルの権限を追加するシンプルな方法です。 + +## 認証 + +認証は、ユーザー ID を検証し、API エンドポイントを保護する必要があるアプリケーションに不可欠です。 + +- [firebase/php-jwt](/awesome-plugins/jwt) - PHP 用の JSON Web Token (JWT) ライブラリです。Flight アプリケーションでトークンベースの認証を実装するためのシンプルで安全な方法です。ステートレス API 認証、ミドルウェアによるルートの保護、OAuth スタイルの認可フローの実装に最適です。 ## キャッシュ キャッシュはアプリケーションを高速化する優れた方法です。Flight で使用できるキャッシュ ライブラリがいくつかあります。 -- official [flightphp/cache](/awesome-plugins/php-file-cache) - 軽量でシンプルなスタンドアロン PHP インデータベースキャッシュクラス +- official [flightphp/cache](/awesome-plugins/php-file-cache) - 軽量でシンプルなスタンドアロンの PHP イン-File キャッシュ クラス ## CLI -CLI アプリケーションは、アプリケーションとやり取りする優れた方法です。コントローラーを生成したり、すべてのルートを表示したり、その他多くのことを行うことができます。 +CLI アプリケーションは、アプリケーションとやり取りする優れた方法です。コントローラーを生成したり、すべてのルートを表示したり、その他多くの機能に使用できます。 - official [flightphp/runway](/awesome-plugins/runway) - Runway は、Flight アプリケーションを管理するのに役立つ CLI アプリケーションです。 -## クッキー +## Cookies クッキーは、クライアント側に少量のデータを保存する優れた方法です。ユーザー設定、アプリケーション設定などを保存するために使用できます。 -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie は、クッキーを管理するためのシンプルで効果的な方法を提供する PHP ライブラリです。 +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie は、クッキーを管理するためのシンプルで効果的な PHP ライブラリです。 ## デバッグ -ローカル環境で開発する際、デバッグは非常に重要です。デバッグ体験を向上させるプラグインがいくつかあります。 +ローカル環境で開発する際のデバッグは重要です。デバッグ体験を向上させるプラグインがいくつかあります。 -- [tracy/tracy](/awesome-plugins/tracy) - Flight で使用できる完全なエラーハンドラーです。アプリケーションのデバッグに役立つパネルがいくつかあります。また、拡張して独自のパネルを追加することも非常に簡単です。 -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) エラーハンドラーと使用され、このプラグインは Flight プロジェクト特有のデバッグに役立つ追加のパネルをいくつか追加します。 +- [tracy/tracy](/awesome-plugins/tracy) - Flight で使用できるフル機能のエラー ハンドラーです。アプリケーションをデバッグするのに役立つパネルがいくつかあります。また、拡張して独自のパネルを追加することも非常に簡単です。 +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) エラー ハンドラーと使用され、このプラグインは Flight プロジェクト特有のデバッグを支援するための追加パネルをいくつか追加します。 ## データベース -データベースはほとんどのアプリケーションのコアです。これによりデータを保存および取得します。一部のデータベース ライブラリはクエリを書くためのラッパーであり、他のものは完全な ORM です。 +データベースはほとんどのアプリケーションのコアです。これによりデータを保存および取得します。一部のデータベース ライブラリはクエリを書くための単なるラッパーであり、他のものはフル機能の ORM です。 -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - コアの一部である公式の Flight PDO Wrapper です。クエリの書き方と実行を簡素化するためのシンプルなラッパーです。ORM ではありません。 -- official [flightphp/active-record](/awesome-plugins/active-record) - 公式の Flight ActiveRecord ORM/マッパーです。データベースからデータを簡単に取得および保存するための優れたライブラリです。 +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - コアの一部である公式の Flight PDO Wrapper です。クエリを書くプロセスを簡素化するためのシンプルなラッパーです。ORM ではありません。 +- official [flightphp/active-record](/awesome-plugins/active-record) - 公式の Flight ActiveRecord ORM/Mapper です。データベースからデータを簡単に取得および保存するための優れたライブラリです。 - [byjg/php-migration](/awesome-plugins/migrations) - プロジェクトのすべてのデータベース変更を追跡するためのプラグインです。 ## 暗号化 -暗号化は、機密データを保存するアプリケーションにとって非常に重要です。データを暗号化および復号化するのはそれほど難しくありませんが、暗号化キーを適切に保存することは [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [です](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [が難しい](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key) です。最も重要なのは、暗号化キーを公開ディレクトリに保存したり、コード リポジトリにコミットしたりしないことです。 +暗号化は、機密データを保存する任意のアプリケーションにとって重要です。データを暗号化および復号化するのはそれほど難しくありませんが、暗号化キーを適切に保存することは [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [です](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [が](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)、難しい場合があります。最も重要なことは、暗号化キーを公開ディレクトリに保存したり、コード リポジトリにコミットしたりしないことです。 -- [defuse/php-encryption](/awesome-plugins/php-encryption) - データを暗号化および復号化するために使用できるライブラリです。データを暗号化および復号化するためのセットアップはかなりシンプルです。 +- [defuse/php-encryption](/awesome-plugins/php-encryption) - データを暗号化および復号化するために使用できるライブラリです。データを暗号化および復号化するのに開始するのはかなりシンプルです。 -## ジョブキュー +## ジョブ キュー -ジョブキューは、タスクを非同期で処理するのに非常に役立ちます。これは、メールの送信、画像の処理、またはリアルタイムで実行する必要がないあらゆるものです。 +ジョブ キューは、タスクを非同期で処理するのに非常に役立ちます。これはメールの送信、画像の処理、またはリアルタイムで実行する必要のない任意のものです。 - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue は、ジョブを非同期で処理するために使用できるライブラリです。beanstalkd、MySQL/MariaDB、SQLite、PostgreSQL と使用できます。 @@ -75,22 +81,22 @@ CLI アプリケーションは、アプリケーションとやり取りする セッションは API にはあまり有用ではありませんが、Web アプリケーションを構築する際には、状態とログイン情報を維持するために重要です。 -- official [flightphp/session](/awesome-plugins/session) - 公式の Flight Session ライブラリです。セッションデータを保存および取得するために使用できるシンプルなセッション ライブラリです。PHP のビルトインセッション処理を使用します。 -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (非ブロッキング、フラッシュ、セグメント、セッション暗号化)。セッションデータのオプションの暗号化/復号化のために PHP open_ssl を使用します。 +- official [flightphp/session](/awesome-plugins/session) - 公式の Flight Session ライブラリです。セッションデータを保存および取得するために使用できるシンプルなセッション ライブラリです。PHP の組み込みセッション処理を使用します。 +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (非ブロッキング、フラッシュ、セグメント、セッション暗号化)。セッションデータのオプションの暗号化/復号化に PHP open_ssl を使用します。 ## テンプレート -テンプレートは UI を持つ Web アプリケーションのコアです。Flight で使用できるテンプレート エンジンがいくつかあります。 +テンプレートは UI を備えた任意の Web アプリケーションのコアです。Flight で使用できるテンプレート エンジンがいくつかあります。 -- deprecated [flightphp/core View](/learn#views) - コアの一部である非常に基本的なテンプレート エンジンです。プロジェクトに数ページ以上ある場合は使用を推奨しません。 -- [latte/latte](/awesome-plugins/latte) - Latte は、Twig や Smarty よりも PHP 構文に近い、非常に使いやすく完全なテンプレート エンジンです。また、独自のフィルターと関数を拡張して追加することも非常に簡単です。 -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate は、アセットコンパイル、テンプレート継承、変数処理を備えた強力な PHP テンプレート エンジンです。自動 CSS/JS 圧縮、キャッシュ、Base64 エンコーディング、およびオプションの Flight PHP フレームワーク統合を備えています。 +- deprecated [flightphp/core View](/learn#views) - コアの一部である非常に基本的なテンプレート エンジンです。プロジェクトに数ページ以上ある場合は使用しないことを推奨します。 +- [latte/latte](/awesome-plugins/latte) - Latte は、Twig や Smarty よりも PHP 構文に近いフル機能のテンプレート エンジンで、非常に使いやすいです。また、拡張して独自のフィルターと関数を追加することも非常に簡単です。 +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate は、アセット コンパイル、テンプレート継承、変数処理を備えた強力な PHP テンプレート エンジンです。自動 CSS/JS 最小化、キャッシュ、Base64 エンコーディング、およびオプションの Flight PHP フレームワーク統合を備えています。 ## WordPress 統合 WordPress プロジェクトで Flight を使用したいですか?そのための便利なプラグインがあります! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - この WordPress プラグインにより、WordPress と Flight を並行して実行できます。Flight フレームワークを使用して WordPress サイトにカスタム API、マイクロサービス、または完全なアプリを追加するのに最適です。両方の世界の最高のものを手に入れたい場合に超便利です! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - この WordPress プラグインにより、WordPress と並行して Flight を実行できます。カスタム API、マイクロサービス、または WordPress サイトに Flight フレームワークを使用してフルアプリを追加するのに最適です。両方の世界の最高のものを求める場合に非常に便利です! ## 貢献 diff --git a/content/v3/ja/awesome-plugins/jwt.md b/content/v3/ja/awesome-plugins/jwt.md new file mode 100644 index 00000000..e25efcf0 --- /dev/null +++ b/content/v3/ja/awesome-plugins/jwt.md @@ -0,0 +1,532 @@ +# Firebase JWT - Flight 用の JSON Web Token 認証 + +JWT (JSON Web Tokens) は、アプリケーションとクライアント間の主張を表すコンパクトで URL セーフな方法です。サーバー側のセッションストレージが不要なステートレス API 認証に最適です!このガイドでは、[Firebase JWT](https://github.com/firebase/php-jwt) を Flight と統合して、セキュアなトークンベースの認証を行う方法を示します。 + +完全なドキュメントと詳細については、[Github リポジトリ](https://github.com/firebase/php-jwt) をご覧ください。 + +## JWT とは? + +JSON Web Token は、3つの部分を含む文字列です: +1. **ヘッダー**: トークンに関するメタデータ (アルゴリズム、タイプ) +2. **ペイロード**: あなたのデータ (ユーザー ID、ロール、期限切れなど) +3. **シグネチャー**: 真正性を検証するための暗号署名 + +例の JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (意味不明に見えますが、構造化されたデータです!) + +### JWT を使用する理由は? + +- **ステートレス**: サーバー側のセッションストレージが不要 — マイクロサービスや API に最適 +- **スケーラブル**: セッションアフィニティの要件がないため、ロードバランサーとよく動作 +- **クロスドメイン**: 異なるドメインやサービス間で使用可能 +- **モバイルフレンドリー**: クッキーがうまく動作しないモバイルアプリに最適 +- **標準化**: 業界標準のアプローチ (RFC 7519) + +## インストール + +Composer を使用してインストール: + +```bash +composer require firebase/php-jwt +``` + +## 基本的な使用方法 + +JWT を作成して検証する簡単な例: + +```php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; + +// あなたの秘密鍵 (これをセキュアに保ってください!) +$secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; + +// トークンを作成 +$payload = [ + 'user_id' => 123, + 'username' => 'johndoe', + 'role' => 'admin', + 'iat' => time(), // 発行日時 + 'exp' => time() + 3600 // 1時間後に期限切れ +]; + +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +echo "Token: " . $jwt; + +// トークンを検証してデコード +try { + $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + echo "User ID: " . $decoded->user_id; +} catch (Exception $e) { + echo "Invalid token: " . $e->getMessage(); +} +``` + +## Flight 用の JWT ミドルウェア (推奨アプローチ) + +Flight で JWT を使用する最も一般的で有用な方法は、**ミドルウェア**として API ルートを保護することです。以下は、完全で本番環境対応の例です: + +### ステップ 1: JWT ミドルウェアクラスを作成 + +```php +// app/middleware/JwtMiddleware.php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; +use Firebase\JWT\ExpiredException; +use Firebase\JWT\SignatureInvalidException; +use flight\Engine; + +class JwtMiddleware { + + protected Engine $app; + protected string $secretKey; + + public function __construct(Engine $app) { + $this->app = $app; + // 秘密鍵を app/config/config.php に保存し、ハードコードしないでください! + $this->secretKey = $app->get('config')['jwt_secret']; + } + + public function before(array $params) { + $authHeader = $this->app->request()->getHeader('Authorization'); + + // Authorization ヘッダーが存在するかチェック + if (empty($authHeader)) { + $this->app->jsonHalt(['error' => 'No authorization token provided'], 401); + } + + // "Bearer " 形式からトークンを抽出 + if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { + $this->app->jsonHalt(['error' => 'Invalid authorization format. Use: Bearer '], 401); + } + + $jwt = $matches[1]; + + try { + // トークンをデコードして検証 + $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); + + // ルートハンドラーで使用するためにユーザー情報をリクエストに保存 + $this->app->request()->data->user = $decoded; + + } catch (ExpiredException $e) { + $this->app->jsonHalt(['error' => 'Token has expired'], 401); + } catch (SignatureInvalidException $e) { + $this->app->jsonHalt(['error' => 'Invalid token signature'], 401); + } catch (Exception $e) { + $this->app->jsonHalt(['error' => 'Invalid token: ' . $e->getMessage()], 401); + } + } +} +``` + +### ステップ 2: 設定に JWT 秘密鍵を登録 + +```php +// app/config/config.php +return [ + 'jwt_secret' => getenv('JWT_SECRET') ?: 'your-fallback-secret-for-development' +]; + +// app/config/bootstrap.php または index.php +// 設定をアプリに公開したい場合、この行を追加してください +$app->set('config', $config); +``` + +> **セキュリティノート**: 秘密鍵をハードコードしないでください!本番環境では環境変数を使用してください。 + +### ステップ 3: ミドルウェアでルートを保護 + +```php +// 単一のルートを保護 +Flight::route('GET /api/user/profile', function() { + $user = Flight::request()->data->user; // ミドルウェアによって設定 + Flight::json([ + 'user_id' => $user->user_id, + 'username' => $user->username, + 'role' => $user->role + ]); +})->addMiddleware( JwtMiddleware::class); + +// ルートのグループ全体を保護 (より一般的!) +Flight::group('/api', function() { + Flight::route('GET /users', function() { /* ... */ }); + Flight::route('GET /posts', function() { /* ... */ }); + Flight::route('POST /posts', function() { /* ... */ }); + Flight::route('DELETE /posts/@id', function($id) { /* ... */ }); +}, [ JwtMiddleware::class ]); // このグループ内のすべてのルートが保護されます! +``` + +ミドルウェアの詳細については、[ミドルウェアドキュメント](/learn/middleware) を参照してください。 + +## 一般的なユースケース + +### 1. ログインエンドポイント (トークン生成) + +認証成功後に JWT を生成するルートを作成: + +```php +Flight::route('POST /api/login', function() { + $data = Flight::request()->data; + $username = $data->username ?? ''; + $password = $data->password ?? ''; + + // 認証情報を検証 (例 — 独自のロジックを使用!) + $user = validateUserCredentials($username, $password); + + if (!$user) { + Flight::jsonHalt(['error' => 'Invalid credentials'], 401); + } + + // JWT を生成 + $secretKey = Flight::get('config')['jwt_secret']; + $payload = [ + 'user_id' => $user->id, + 'username' => $user->username, + 'role' => $user->role, + 'iat' => time(), + 'exp' => time() + (60 * 60) // 1時間後の期限切れ + ]; + + $jwt = JWT::encode($payload, $secretKey, 'HS256'); + + Flight::json([ + 'success' => true, + 'token' => $jwt, + 'expires_in' => 3600 + ]); +}); + +function validateUserCredentials($username, $password) { + // ここにデータベース検索とパスワード検証を実装 + // 例: + $db = Flight::db(); + $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); + + if ($user && password_verify($password, $user['password_hash'])) { + return (object) [ + 'id' => $user['id'], + 'username' => $user['username'], + 'role' => $user['role'] + ]; + } + return null; +} +``` + +### 2. トークンリフレッシュフロー + +長期間のセッションのためのリフレッシュトークンシステムを実装: + +```php +Flight::route('POST /api/login', function() { + // ... 認証情報を検証 ... + + $secretKey = Flight::get('config')['jwt_secret']; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + // 短期間のアクセス トークン (15 分) + $accessToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + // 長期間のリフレッシュ トークン (7 日) + $refreshToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'refresh', + 'iat' => time(), + 'exp' => time() + (7 * 24 * 60 * 60) + ], $refreshSecret, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'refresh_token' => $refreshToken, + 'expires_in' => 900 + ]); +}); + +Flight::route('POST /api/refresh', function() { + $refreshToken = Flight::request()->data->refresh_token ?? ''; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + try { + $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); + + // これがリフレッシュ トークンであることを検証 + if ($decoded->type !== 'refresh') { + Flight::jsonHalt(['error' => 'Invalid token type'], 401); + } + + // 新しいアクセス トークンを生成 + $secretKey = Flight::get('config')['jwt_secret']; + $accessToken = JWT::encode([ + 'user_id' => $decoded->user_id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'expires_in' => 900 + ]); + + } catch (Exception $e) { + Flight::jsonHalt(['error' => 'Invalid refresh token'], 401); + } +}); +``` + +### 3. ロールベースのアクセス制御 + +ミドルウェアを拡張してユーザー ロールをチェック: + +```php +class JwtRoleMiddleware { + + protected Engine $app; + protected array $allowedRoles; + + public function __construct(Engine $app, array $allowedRoles = []) { + $this->app = $app; + $this->allowedRoles = $allowedRoles; + } + + public function before(array $params) { + // JwtMiddleware が既に実行され、ユーザー データが設定されていると仮定 + $user = $this->app->request()->data->user ?? null; + + if (!$user) { + $this->app->jsonHalt(['error' => 'Authentication required'], 401); + } + + // ユーザーが必要なロールを持っているかチェック + if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { + $this->app->jsonHalt(['error' => 'Insufficient permissions'], 403); + } + } +} + +// 使用例: 管理者限定ルート +Flight::route('DELETE /api/users/@id', function($id) { + // ユーザー削除ロジック +})->addMiddleware([ + JwtMiddleware::class, + new JwtRoleMiddleware(Flight::app(), ['admin']) +]); +``` + +### 4. ユーザーごとのレート制限付きパブリック API + +セッションなしでユーザーを追跡してレート制限: + +```php +class RateLimitMiddleware { + + public function before(array $params) { + $user = Flight::request()->data->user ?? null; + $userId = $user ? $user->user_id : Flight::request()->ip; + + $cacheKey = "rate_limit:$userId"; + // app/config/services.php でキャッシュ サービスを設定してください + $requests = Flight::cache()->get($cacheKey, 0); + + if ($requests >= 100) { // 1時間あたり 100 リクエスト + Flight::jsonHalt(['error' => 'Rate limit exceeded'], 429); + } + + Flight::cache()->set($cacheKey, $requests + 1, 3600); + } +} +``` + +## セキュリティのベストプラクティス + +### 1. 強力な秘密鍵を使用 + +```php +// セキュアな秘密鍵を生成 (一度実行し、.env ファイルに保存) +$secretKey = base64_encode(random_bytes(32)); +echo $secretKey; // これを .env ファイルに保存! +``` + +### 2. 秘密鍵を環境変数に保存 + +```php +// 秘密鍵をバージョン管理にコミットしないでください! +// .env ファイルと vlucas/phpdotenv などのライブラリを使用 + +// .env ファイル: +// JWT_SECRET=your-base64-encoded-secret-here +// JWT_REFRESH_SECRET=another-base64-encoded-secret-here + +// アプリの設定ファイル app/config/config.php にも秘密鍵を保存可能 +// ただし、設定ファイルはバージョン管理にコミットしないでください +// return [ +// 'jwt_secret' => 'your-base64-encoded-secret-here', +// 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', +// ]; + +// アプリ内: +// $secretKey = getenv('JWT_SECRET'); +``` + +### 3. 適切な有効期限を設定 + +```php +// 良い習慣: 短期間のアクセス トークン +'exp' => time() + (15 * 60) // 15 分 + +// リフレッシュ トークンの場合: 長い有効期限 +'exp' => time() + (7 * 24 * 60 * 60) // 7 日 +``` + +### 4. 本番環境で HTTPS を使用 + +JWT は **常に** HTTPS を介して送信してください。本番環境でプレーン HTTP を使用しないでください! + +### 5. トークン主張を検証 + +重要な主張を常に検証: + +```php +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + +// 期限切れのチェックはライブラリによって自動的に処理されます +// ただし、カスタム検証を追加可能: +if ($decoded->iat > time()) { + throw new Exception('Token used before it was issued'); +} + +if (isset($decoded->nbf) && $decoded->nbf > time()) { + throw new Exception('Token not yet valid'); +} +``` + +### 6. ログアウトのためのトークンブラックリストを検討 + +追加のセキュリティのために、無効化されたトークンのブラックリストを維持: + +```php +Flight::route('POST /api/logout', function() { + $authHeader = Flight::request()->getHeader('Authorization'); + preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches); + $jwt = $matches[1]; + + // トークンの有効期限を抽出 + $decoded = Flight::request()->data->user; + $ttl = $decoded->exp - time(); + + // 有効期限までキャッシュ/Redis に保存 + Flight::cache()->set("blacklist:$jwt", true, $ttl); + + Flight::json(['message' => 'Successfully logged out']); +}); + +// JwtMiddleware に追加: +public function before(array $params) { + // ... JWT を抽出 ... + + // ブラックリストをチェック + if (Flight::cache()->get("blacklist:$jwt")) { + $this->app->jsonHalt(['error' => 'Token has been revoked'], 401); + } + + // ... トークンを検証 ... +} +``` + +## アルゴリズムと鍵の種類 + +Firebase JWT は複数のアルゴリズムをサポート: + +### 対称アルゴリズム (HMAC) +- **HS256** (ほとんどのアプリで推奨): 単一の秘密鍵を使用 +- **HS384**, **HS512**: より強力なバリエーション + +```php +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### 非対称アルゴリズム (RSA/ECDSA) +- **RS256**, **RS384**, **RS512**: 公開/秘密鍵ペアを使用 +- **ES256**, **ES384**, **ES512**: 楕円曲線バリエーション + +```php +// 鍵を生成: openssl genrsa -out private.key 2048 +// openssl rsa -in private.key -pubout -out public.key + +$privateKey = file_get_contents('/path/to/private.key'); +$publicKey = file_get_contents('/path/to/public.key'); + +// 秘密鍵でエンコード +$jwt = JWT::encode($payload, $privateKey, 'RS256'); + +// 公開鍵でデコード +$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); +``` + +> **RSA を使用するタイミング**: 公開鍵を検証のために配布する必要がある場合 (例: マイクロサービス、サードパーティ統合) に RSA を使用。単一のアプリケーションの場合、HS256 がよりシンプルで十分です。 + +## トラブルシューティング + +### "Expired token" エラー +トークンの `exp` 主張が過去です。新しいトークンを発行するか、トークンリフレッシュを実装してください。 + +### "Signature verification failed" +- エンコードに使用したものと異なる秘密鍵でデコードしている +- トークンが改ざんされている +- サーバー間のクロックスキュー (レウェイバッファを追加) + +```php +use Firebase\JWT\JWT; + +JWT::$leeway = 60; // 60 秒のクロックスキューを許可 +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### リクエストでトークンが送信されない +クライアントが `Authorization` ヘッダーを送信していることを確認: + +```javascript +// JavaScript の例 +fetch('/api/users', { + headers: { + 'Authorization': 'Bearer ' + token + } +}); +``` + +## メソッド + +Firebase JWT ライブラリはこれらのコアメソッドを提供: + +- `JWT::encode(array $payload, string $key, string $alg)`: ペイロードから JWT を作成 +- `JWT::decode(string $jwt, Key $key)`: JWT をデコードして検証 +- `JWT::urlsafeB64Encode(string $input)`: Base64 URL セーフエンコード +- `JWT::urlsafeB64Decode(string $input)`: Base64 URL セーフデコード +- `JWT::$leeway`: 検証のための時間レウェイを設定する静的プロパティ (秒単位) + +## このライブラリを使用する理由は? + +- **業界標準**: Firebase JWT は PHP で最も人気があり、広く信頼されている JWT ライブラリ +- **積極的なメンテナンス**: Google/Firebase チームによるメンテナンス +- **セキュリティ重視**: 定期的な更新とセキュリティパッチ +- **シンプルな API**: 理解しやすく実装しやすい +- **よくドキュメント化**: 広範なドキュメントとコミュニティサポート +- **柔軟**: 複数のアルゴリズムと設定可能なオプションをサポート + +## 関連項目 + +- [Firebase JWT Github リポジトリ](https://github.com/firebase/php-jwt) +- [JWT.io](https://jwt.io/) - JWT をデバッグおよびデコード +- [RFC 7519](https://tools.ietf.org/html/rfc7519) - 公式 JWT 仕様 +- [Flight ミドルウェアドキュメント](/learn/middleware) +- [Flight セッションプラグイン](/awesome-plugins/session) - 従来のセッションベース認証用 + +## ライセンス + +Firebase JWT ライブラリは BSD 3-Clause ライセンスの下でライセンスされています。詳細は [Github リポジトリ](https://github.com/firebase/php-jwt) を参照してください。 \ No newline at end of file diff --git a/content/v3/ko/awesome-plugins/awesome_plugins.md b/content/v3/ko/awesome-plugins/awesome_plugins.md index bb0e94df..6a5f3a4e 100644 --- a/content/v3/ko/awesome-plugins/awesome_plugins.md +++ b/content/v3/ko/awesome-plugins/awesome_plugins.md @@ -2,17 +2,17 @@ Flight는 놀라울 정도로 확장 가능합니다. Flight 애플리케이션에 기능을 추가하는 데 사용할 수 있는 여러 플러그인이 있습니다. 일부는 Flight 팀에서 공식적으로 지원하며, 다른 일부는 시작하는 데 도움을 주는 마이크로/라이트 라이브러리입니다. -## API 문서 +## API 문서화 -API 문서는 모든 API에 필수적입니다. 개발자들이 API와 상호 작용하는 방법을 이해하고 반환되는 것을 예상할 수 있도록 돕습니다. Flight 프로젝트를 위한 API 문서를 생성하는 데 도움을 주는 몇 가지 도구가 있습니다. +API 문서화는 모든 API에 필수적입니다. 개발자들이 API와 상호 작용하는 방법을 이해하고 반환되는 것을 예상할 수 있도록 도와줍니다. Flight 프로젝트에 대한 API 문서화를 생성하는 데 도움이 되는 몇 가지 도구가 있습니다. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber가 작성한 블로그 포스트로, OpenAPI 사양을 FlightPHP와 함께 사용하여 API 우선 접근 방식을 통해 API를 구축하는 방법에 대해 설명합니다. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI는 Flight 프로젝트를 위한 API 문서를 생성하는 데 훌륭한 도구입니다. 사용하기 매우 쉽고 필요에 맞게 사용자 정의할 수 있습니다. 이는 Swagger 문서를 생성하는 데 도움을 주는 PHP 라이브러리입니다. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber가 작성한 블로그 포스트로, API 우선 접근 방식을 사용하여 FlightPHP와 함께 OpenAPI 사양을 사용하는 방법에 대해 설명합니다. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI는 Flight 프로젝트에 대한 API 문서화를 생성하는 데 도움이 되는 훌륭한 도구입니다. 사용하기 매우 쉽고 필요에 맞게 사용자 지정할 수 있습니다. 이는 Swagger 문서화를 생성하는 데 도움이 되는 PHP 라이브러리입니다. ## 애플리케이션 성능 모니터링 (APM) -애플릭케이션 성능 모니터링 (APM)은 모든 애플리케이션에 필수적입니다. 애플리케이션이 어떻게 작동하는지 이해하고 병목 현상이 어디에 있는지 파악하는 데 도움이 됩니다. Flight와 함께 사용할 수 있는 여러 APM 도구가 있습니다. -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM은 Flight 애플리케이션을 모니터링하는 데 사용할 수 있는 간단한 APM 라이브러리입니다. 애플리케이션 성능을 모니터링하고 병목 현상을 식별하는 데 도움이 됩니다. +애플리케이션 성능 모니터링 (APM)은 모든 애플리케이션에 필수적입니다. 애플리케이션이 어떻게 작동하는지 이해하고 병목 현상이 어디에 있는지 파악하는 데 도움을 줍니다. Flight와 함께 사용할 수 있는 여러 APM 도구가 있습니다. +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM은 Flight 애플리케이션을 모니터링하는 데 사용할 수 있는 간단한 APM 라이브러리입니다. 애플리케이션의 성능을 모니터링하고 병목 현상을 식별하는 데 도움을 줄 수 있습니다. ## 비동기 @@ -26,6 +26,12 @@ Flight는 이미 빠른 프레임워크이지만, 터보 엔진을 장착하면 - official [flightphp/permissions](/awesome-plugins/permissions) - 공식 Flight Permissions 라이브러리입니다. 이 라이브러리는 애플리케이션에 사용자 및 애플리케이션 수준의 권한을 추가하는 간단한 방법입니다. +## 인증 + +인증은 사용자 ID를 확인하고 API 엔드포인트를 보호해야 하는 애플리케이션에 필수적입니다. + +- [firebase/php-jwt](/awesome-plugins/jwt) - PHP용 JSON Web Token (JWT) 라이브러리입니다. Flight 애플리케이션에서 토큰 기반 인증을 구현하는 간단하고 안전한 방법입니다. 상태 비저장 API 인증, 미들웨어를 사용한 라우트 보호, OAuth 스타일의 권한 부여 흐름 구현에 완벽합니다. + ## 캐싱 캐싱은 애플리케이션을 가속화하는 훌륭한 방법입니다. Flight와 함께 사용할 수 있는 여러 캐싱 라이브러리가 있습니다. @@ -34,7 +40,7 @@ Flight는 이미 빠른 프레임워크이지만, 터보 엔진을 장착하면 ## CLI -CLI 애플리케이션은 애플리케이션과 상호 작용하는 훌륭한 방법입니다. 컨트롤러 생성, 모든 경로 표시 등에 사용할 수 있습니다. +CLI 애플리케이션은 애플리케이션과 상호 작용하는 훌륭한 방법입니다. 컨트롤러 생성, 모든 라우트 표시 등에 사용할 수 있습니다. - official [flightphp/runway](/awesome-plugins/runway) - Runway는 Flight 애플리케이션을 관리하는 데 도움을 주는 CLI 애플리케이션입니다. @@ -46,10 +52,10 @@ CLI 애플리케이션은 애플리케이션과 상호 작용하는 훌륭한 ## 디버깅 -로컬 환경에서 개발할 때 디버깅은 필수적입니다. 디버깅 경험을 향상시킬 수 있는 몇 가지 플러그인이 있습니다. +디버깅은 로컬 환경에서 개발할 때 필수적입니다. 디버깅 경험을 향상시킬 수 있는 몇 가지 플러그인이 있습니다. -- [tracy/tracy](/awesome-plugins/tracy) - Flight와 함께 사용할 수 있는 완전한 기능을 갖춘 오류 핸들러입니다. 애플리케이션을 디버깅하는 데 도움이 되는 여러 패널을 가지고 있습니다. 확장하고 자신의 패널을 추가하기도 매우 쉽습니다. -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) 오류 핸들러와 함께 사용되며, Flight 프로젝트를 위한 디버깅을 돕기 위해 몇 가지 추가 패널을 제공합니다. +- [tracy/tracy](/awesome-plugins/tracy) - Flight와 함께 사용할 수 있는 완전한 기능을 갖춘 오류 핸들러입니다. 애플리케이션을 디버깅하는 데 도움을 주는 여러 패널이 있습니다. 확장하기 쉽고 자체 패널을 추가할 수도 있습니다. +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) 오류 핸들러와 함께 사용되며, Flight 프로젝트에 특화된 디버깅을 돕기 위해 몇 가지 추가 패널을 제공하는 플러그인입니다. ## 데이터베이스 @@ -61,36 +67,36 @@ CLI 애플리케이션은 애플리케이션과 상호 작용하는 훌륭한 ## 암호화 -암호화는 민감한 데이터를 저장하는 모든 애플리케이션에 필수적입니다. 데이터를 암호화하고 복호화하는 것은 그리 어렵지 않지만, 암호화 키를 적절히 저장하는 것은 [어렵습니다](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [수 있습니다](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [것입니다](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). 가장 중요한 것은 암호화 키를 공개 디렉토리에 저장하지 않거나 코드 저장소에 커밋하지 않는 것입니다. +암호화는 민감한 데이터를 저장하는 모든 애플리케이션에 필수적입니다. 데이터를 암호화하고 복호화하는 것은 그리 어렵지 않지만, 암호화 키를 적절히 저장하는 것은 [어렵습니다](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [있습니다](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [입니다](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). 가장 중요한 것은 암호화 키를 공개 디렉토리에 저장하거나 코드 저장소에 커밋하지 않는 것입니다. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - 데이터를 암호화하고 복호화하는 데 사용할 수 있는 라이브러리입니다. 데이터를 암호화하고 복호화하는 데 시작하기 위해 실행하는 것이 상당히 간단합니다. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - 데이터를 암호화하고 복호화하는 데 사용할 수 있는 라이브러리입니다. 데이터를 암호화하고 복호화하는 데 시작하기가 상당히 간단합니다. ## 작업 큐 -작업 큐는 작업을 비동기적으로 처리하는 데 매우 도움이 됩니다. 이메일 보내기, 이미지 처리 또는 실시간으로 처리할 필요가 없는 모든 것에 사용할 수 있습니다. +작업 큐는 작업을 비동기적으로 처리하는 데 매우 유용합니다. 이메일 보내기, 이미지 처리 또는 실시간으로 수행할 필요가 없는 모든 작업에 사용할 수 있습니다. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue는 작업을 비동기적으로 처리하는 데 사용할 수 있는 라이브러리입니다. beanstalkd, MySQL/MariaDB, SQLite, PostgreSQL과 함께 사용할 수 있습니다. ## 세션 -세션은 API에는 정말 유용하지 않지만, 웹 애플리케이션을 구축할 때 상태와 로그인 정보를 유지하는 데 필수적일 수 있습니다. +세션은 API에는 별로 유용하지 않지만, 웹 애플리케이션을 구축할 때 상태와 로그인 정보를 유지하는 데 필수적일 수 있습니다. -- official [flightphp/session](/awesome-plugins/session) - 공식 Flight Session 라이브러리입니다. 세션 데이터를 저장하고 검색하는 데 사용할 수 있는 간단한 세션 라이브러리입니다. PHP의 내장 세션 처리 방식을 사용합니다. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 세션 관리자 (비동기 차단 없음, 플래시, 세그먼트, 세션 암호화). 세션 데이터의 선택적 암호화/복호화를 위해 PHP open_ssl을 사용합니다. +- official [flightphp/session](/awesome-plugins/session) - 공식 Flight Session 라이브러리입니다. 세션 데이터를 저장하고 검색하는 데 사용할 수 있는 간단한 세션 라이브러리입니다. PHP의 내장 세션 처리를 사용합니다. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 세션 관리자 (비차단, 플래시, 세그먼트, 세션 암호화). 세션 데이터의 선택적 암호화/복호화를 위해 PHP open_ssl을 사용합니다. ## 템플릿 템플릿은 UI가 있는 모든 웹 애플리케이션의 핵심입니다. Flight와 함께 사용할 수 있는 여러 템플릿 엔진이 있습니다. - deprecated [flightphp/core View](/learn#views) - 코어의 일부인 매우 기본적인 템플릿 엔진입니다. 프로젝트에 몇 페이지 이상이 있다면 사용하지 않는 것이 좋습니다. -- [latte/latte](/awesome-plugins/latte) - Latte는 사용하기 매우 쉽고 Twig나 Smarty보다 PHP 구문에 더 가까운 느낌을 주는 완전한 기능을 갖춘 템플릿 엔진입니다. 확장하고 자신의 필터와 함수를 추가하기도 매우 쉽습니다. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate는 자산 컴파일, 템플릿 상속, 변수 처리 기능을 가진 강력한 PHP 템플릿 엔진입니다. 자동 CSS/JS 최소화, 캐싱, Base64 인코딩, 선택적 Flight PHP 프레임워크 통합 기능을 제공합니다. +- [latte/latte](/awesome-plugins/latte) - Latte는 사용하기 매우 쉽고 Twig나 Smarty보다 PHP 구문에 더 가까운 느낌의 완전한 기능을 갖춘 템플릿 엔진입니다. 확장하기 쉽고 자체 필터와 함수를 추가할 수도 있습니다. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate는 자산 컴파일, 템플릿 상속, 변수 처리 기능을 가진 강력한 PHP 템플릿 엔진입니다. 자동 CSS/JS 최소화, 캐싱, Base64 인코딩, 선택적 Flight PHP 프레임워크 통합을 제공합니다. ## WordPress 통합 WordPress 프로젝트에서 Flight를 사용하고 싶으신가요? 이를 위한 편리한 플러그인이 있습니다! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 이 WordPress 플러그인은 Flight를 WordPress와 함께 실행할 수 있게 합니다. WordPress 사이트에 사용자 정의 API, 마이크로서비스 또는 전체 앱을 Flight 프레임워크를 사용하여 추가하는 데 완벽합니다. 두 세계의 장점을 모두 누리고 싶다면 매우 유용합니다! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 이 WordPress 플러그인은 WordPress와 함께 Flight를 실행할 수 있게 합니다. WordPress 사이트에 사용자 지정 API, 마이크로서비스 또는 전체 앱을 Flight 프레임워크를 사용하여 추가하는 데 완벽합니다. 두 세계의 장점을 모두 누리고 싶다면 매우 유용합니다! ## 기여 diff --git a/content/v3/ko/awesome-plugins/jwt.md b/content/v3/ko/awesome-plugins/jwt.md new file mode 100644 index 00000000..4c23b8f3 --- /dev/null +++ b/content/v3/ko/awesome-plugins/jwt.md @@ -0,0 +1,532 @@ +# Firebase JWT - JSON Web Token 인증을 위한 Flight + +JWT (JSON Web Tokens)는 애플리케이션과 클라이언트 간에 클레임을 나타내는 컴팩트하고 URL-안전한 방법입니다. 서버 측 세션 저장소가 필요 없는 stateless API 인증에 완벽합니다! 이 가이드는 [Firebase JWT](https://github.com/firebase/php-jwt)를 Flight와 통합하여 안전한 토큰 기반 인증을 구현하는 방법을 보여줍니다. + +전체 문서와 세부 사항은 [Github 저장소](https://github.com/firebase/php-jwt)를 방문하세요. + +## JWT란 무엇인가? + +JSON Web Token은 세 부분을 포함하는 문자열입니다: +1. **헤더**: 토큰에 대한 메타데이터 (알고리즘, 유형) +2. **페이로드**: 데이터 (사용자 ID, 역할, 만료 등) +3. **서명**: 진위성을 확인하기 위한 암호화 서명 + +예제 JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (무의미해 보이지만 구조화된 데이터입니다!) + +### JWT를 사용하는 이유는? + +- **Stateless**: 서버 측 세션 저장소가 필요 없음—마이크로서비스와 API에 완벽 +- **확장성**: 세션 affinity 요구사항이 없어 로드 밸런서와 잘 작동 +- **크로스 도메인**: 다른 도메인과 서비스 간에 사용 가능 +- **모바일 친화적**: 쿠키가 잘 작동하지 않는 모바일 앱에 좋음 +- **표준화**: 산업 표준 접근법 (RFC 7519) + +## 설치 + +Composer를 통해 설치하세요: + +```bash +composer require firebase/php-jwt +``` + +## 기본 사용법 + +JWT 생성 및 확인의 간단한 예제입니다: + +```php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; + +// 비밀 키 (이것을 안전하게 보관하세요!) +$secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; + +// 토큰 생성 +$payload = [ + 'user_id' => 123, + 'username' => 'johndoe', + 'role' => 'admin', + 'iat' => time(), // 발급 시각 + 'exp' => time() + 3600 // 1시간 후 만료 +]; + +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +echo "Token: " . $jwt; + +// 토큰 확인 및 디코딩 +try { + $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + echo "User ID: " . $decoded->user_id; +} catch (Exception $e) { + echo "Invalid token: " . $e->getMessage(); +} +``` + +## Flight를 위한 JWT 미들웨어 (권장 접근법) + +Flight에서 JWT를 가장 일반적이고 유용하게 사용하는 방법은 API 경로를 보호하는 **미들웨어**입니다. 여기 완전하고 프로덕션 준비된 예제가 있습니다: + +### 1단계: JWT 미들웨어 클래스 생성 + +```php +// app/middleware/JwtMiddleware.php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; +use Firebase\JWT\ExpiredException; +use Firebase\JWT\SignatureInvalidException; +use flight\Engine; + +class JwtMiddleware { + + protected Engine $app; + protected string $secretKey; + + public function __construct(Engine $app) { + $this->app = $app; + // 비밀 키를 app/config/config.php에 저장하세요. 하드코딩하지 마세요! + $this->secretKey = $app->get('config')['jwt_secret']; + } + + public function before(array $params) { + $authHeader = $this->app->request()->getHeader('Authorization'); + + // Authorization 헤더 존재 확인 + if (empty($authHeader)) { + $this->app->jsonHalt(['error' => 'No authorization token provided'], 401); + } + + // "Bearer " 형식에서 토큰 추출 + if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { + $this->app->jsonHalt(['error' => 'Invalid authorization format. Use: Bearer '], 401); + } + + $jwt = $matches[1]; + + try { + // 토큰 디코딩 및 확인 + $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); + + // 라우트 핸들러에서 사용할 사용자 데이터를 요청에 저장 + $this->app->request()->data->user = $decoded; + + } catch (ExpiredException $e) { + $this->app->jsonHalt(['error' => 'Token has expired'], 401); + } catch (SignatureInvalidException $e) { + $this->app->jsonHalt(['error' => 'Invalid token signature'], 401); + } catch (Exception $e) { + $this->app->jsonHalt(['error' => 'Invalid token: ' . $e->getMessage()], 401); + } + } +} +``` + +### 2단계: 구성에 JWT 비밀 등록 + +```php +// app/config/config.php +return [ + 'jwt_secret' => getenv('JWT_SECRET') ?: 'your-fallback-secret-for-development' +]; + +// app/config/bootstrap.php 또는 index.php +// 구성에 앱을 노출하려면 이 줄을 추가하세요 +$app->set('config', $config); +``` + +> **보안 주의**: 비밀 키를 하드코딩하지 마세요! 프로덕션에서는 환경 변수를 사용하세요. + +### 3단계: 미들웨어로 경로 보호 + +```php +// 단일 경로 보호 +Flight::route('GET /api/user/profile', function() { + $user = Flight::request()->data->user; // 미들웨어에서 설정 + Flight::json([ + 'user_id' => $user->user_id, + 'username' => $user->username, + 'role' => $user->role + ]); +})->addMiddleware( JwtMiddleware::class); + +// 전체 경로 그룹 보호 (더 일반적!) +Flight::group('/api', function() { + Flight::route('GET /users', function() { /* ... */ }); + Flight::route('GET /posts', function() { /* ... */ }); + Flight::route('POST /posts', function() { /* ... */ }); + Flight::route('DELETE /posts/@id', function($id) { /* ... */ }); +}, [ JwtMiddleware::class ]); // 이 그룹의 모든 경로가 보호됩니다! +``` + +미들웨어에 대한 자세한 내용은 [미들웨어 문서](/learn/middleware)를 참조하세요. + +## 일반적인 사용 사례 + +### 1. 로그인 엔드포인트 (토큰 생성) + +성공적인 인증 후 JWT를 생성하는 경로를 만드세요: + +```php +Flight::route('POST /api/login', function() { + $data = Flight::request()->data; + $username = $data->username ?? ''; + $password = $data->password ?? ''; + + // 자격 증명 확인 (예제 - 자체 로직 사용!) + $user = validateUserCredentials($username, $password); + + if (!$user) { + Flight::jsonHalt(['error' => 'Invalid credentials'], 401); + } + + // JWT 생성 + $secretKey = Flight::get('config')['jwt_secret']; + $payload = [ + 'user_id' => $user->id, + 'username' => $user->username, + 'role' => $user->role, + 'iat' => time(), + 'exp' => time() + (60 * 60) // 1시간 만료 + ]; + + $jwt = JWT::encode($payload, $secretKey, 'HS256'); + + Flight::json([ + 'success' => true, + 'token' => $jwt, + 'expires_in' => 3600 + ]); +}); + +function validateUserCredentials($username, $password) { + // 데이터베이스 조회 및 비밀번호 확인 로직 + // 예제: + $db = Flight::db(); + $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); + + if ($user && password_verify($password, $user['password_hash'])) { + return (object) [ + 'id' => $user['id'], + 'username' => $user['username'], + 'role' => $user['role'] + ]; + } + return null; +} +``` + +### 2. 토큰 새로고침 흐름 + +장기 세션을 위한 새로고침 토큰 시스템을 구현하세요: + +```php +Flight::route('POST /api/login', function() { + // ... 자격 증명 확인 ... + + $secretKey = Flight::get('config')['jwt_secret']; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + // 단기 액세스 토큰 (15분) + $accessToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + // 장기 새로고침 토큰 (7일) + $refreshToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'refresh', + 'iat' => time(), + 'exp' => time() + (7 * 24 * 60 * 60) + ], $refreshSecret, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'refresh_token' => $refreshToken, + 'expires_in' => 900 + ]); +}); + +Flight::route('POST /api/refresh', function() { + $refreshToken = Flight::request()->data->refresh_token ?? ''; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + try { + $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); + + // 새로고침 토큰인지 확인 + if ($decoded->type !== 'refresh') { + Flight::jsonHalt(['error' => 'Invalid token type'], 401); + } + + // 새 액세스 토큰 생성 + $secretKey = Flight::get('config')['jwt_secret']; + $accessToken = JWT::encode([ + 'user_id' => $decoded->user_id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'expires_in' => 900 + ]); + + } catch (Exception $e) { + Flight::jsonHalt(['error' => 'Invalid refresh token'], 401); + } +}); +``` + +### 3. 역할 기반 액세스 제어 + +미들웨어를 확장하여 사용자 역할을 확인하세요: + +```php +class JwtRoleMiddleware { + + protected Engine $app; + protected array $allowedRoles; + + public function __construct(Engine $app, array $allowedRoles = []) { + $this->app = $app; + $this->allowedRoles = $allowedRoles; + } + + public function before(array $params) { + // JwtMiddleware가 이미 실행되어 사용자 데이터를 설정했다고 가정 + $user = $this->app->request()->data->user ?? null; + + if (!$user) { + $this->app->jsonHalt(['error' => 'Authentication required'], 401); + } + + // 필요한 역할이 있는지 확인 + if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { + $this->app->jsonHalt(['error' => 'Insufficient permissions'], 403); + } + } +} + +// 사용: 관리자 전용 경로 +Flight::route('DELETE /api/users/@id', function($id) { + // 사용자 삭제 로직 +})->addMiddleware([ + JwtMiddleware::class, + new JwtRoleMiddleware(Flight::app(), ['admin']) +]); +``` + +### 4. 사용자별 속도 제한이 있는 공용 API + +세션 없이 JWT를 사용하여 사용자 추적 및 속도 제한: + +```php +class RateLimitMiddleware { + + public function before(array $params) { + $user = Flight::request()->data->user ?? null; + $userId = $user ? $user->user_id : Flight::request()->ip; + + $cacheKey = "rate_limit:$userId"; + // app/config/services.php에 캐시 서비스를 설정하세요 + $requests = Flight::cache()->get($cacheKey, 0); + + if ($requests >= 100) { // 시간당 100 요청 + Flight::jsonHalt(['error' => 'Rate limit exceeded'], 429); + } + + Flight::cache()->set($cacheKey, $requests + 1, 3600); + } +} +``` + +## 보안 모범 사례 + +### 1. 강력한 비밀 키 사용 + +```php +// 안전한 비밀 키 생성 (한 번 실행 후 .env 파일에 저장) +$secretKey = base64_encode(random_bytes(32)); +echo $secretKey; // .env 파일에 저장하세요! +``` + +### 2. 환경 변수에 비밀 저장 + +```php +// 비밀을 버전 제어에 커밋하지 마세요! +// .env 파일과 vlucas/phpdotenv 같은 라이브러리 사용 + +// .env 파일: +// JWT_SECRET=your-base64-encoded-secret-here +// JWT_REFRESH_SECRET=another-base64-encoded-secret-here + +// app/config/config.php 파일에도 비밀을 저장할 수 있습니다 +// 구성 파일이 버전 제어에 커밋되지 않도록 하세요 +// return [ +// 'jwt_secret' => 'your-base64-encoded-secret-here', +// 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', +// ]; + +// 앱에서: +$secretKey = getenv('JWT_SECRET'); +``` + +### 3. 적절한 만료 시간 설정 + +```php +// 모범 사례: 단기 액세스 토큰 +'exp' => time() + (15 * 60) // 15분 + +// 새로고침 토큰: 더 긴 만료 +'exp' => time() + (7 * 24 * 60 * 60) // 7일 +``` + +### 4. 프로덕션에서 HTTPS 사용 + +JWT는 **항상** HTTPS를 통해 전송해야 합니다. 프로덕션에서 평문 HTTP로 토큰을 보내지 마세요! + +### 5. 토큰 클레임 확인 + +중요한 클레임을 항상 확인하세요: + +```php +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + +// 만료 확인은 라이브러리에서 자동 처리 +// 하지만 사용자 지정 확인을 추가할 수 있습니다: +if ($decoded->iat > time()) { + throw new Exception('Token used before it was issued'); +} + +if (isset($decoded->nbf) && $decoded->nbf > time()) { + throw new Exception('Token not yet valid'); +} +``` + +### 6. 로그아웃을 위한 토큰 블랙리스트 고려 + +추가 보안을 위해 무효화된 토큰의 블랙리스트를 유지하세요: + +```php +Flight::route('POST /api/logout', function() { + $authHeader = Flight::request()->getHeader('Authorization'); + preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches); + $jwt = $matches[1]; + + // 토큰 만료 추출 + $decoded = Flight::request()->data->user; + $ttl = $decoded->exp - time(); + + // 만료까지 캐시/Redis에 저장 + Flight::cache()->set("blacklist:$jwt", true, $ttl); + + Flight::json(['message' => 'Successfully logged out']); +}); + +// JwtMiddleware에 추가: +public function before(array $params) { + // ... JWT 추출 ... + + // 블랙리스트 확인 + if (Flight::cache()->get("blacklist:$jwt")) { + $this->app->jsonHalt(['error' => 'Token has been revoked'], 401); + } + + // ... 토큰 확인 ... +} +``` + +## 알고리즘 및 키 유형 + +Firebase JWT는 여러 알고리즘을 지원합니다: + +### 대칭 알고리즘 (HMAC) +- **HS256** (대부분의 앱에 권장): 단일 비밀 키 사용 +- **HS384**, **HS512**: 더 강력한 변형 + +```php +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### 비대칭 알고리즘 (RSA/ECDSA) +- **RS256**, **RS384**, **RS512**: 공개/비공개 키 쌍 사용 +- **ES256**, **ES384**, **ES512**: 타원 곡선 변형 + +```php +// 키 생성: openssl genrsa -out private.key 2048 +// openssl rsa -in private.key -pubout -out public.key + +$privateKey = file_get_contents('/path/to/private.key'); +$publicKey = file_get_contents('/path/to/public.key'); + +// 비공개 키로 인코딩 +$jwt = JWT::encode($payload, $privateKey, 'RS256'); + +// 공개 키로 디코딩 +$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); +``` + +> **RSA를 사용할 때**: 확인을 위해 공개 키를 배포해야 할 때 사용 (예: 마이크로서비스, 타사 통합). 단일 애플리케이션의 경우 HS256이 더 간단하고 충분합니다. + +## 문제 해결 + +### "만료된 토큰" 오류 +토큰의 `exp` 클레임이 과거입니다. 새 토큰을 발급하거나 토큰 새로고침을 구현하세요. + +### "서명 확인 실패" +- 인코딩에 사용한 비밀 키와 다른 키로 디코딩 +- 토큰이 변조됨 +- 서버 간 시계 왜곡 (leeway 버퍼 추가) + +```php +use Firebase\JWT\JWT; + +JWT::$leeway = 60; // 60초 시계 왜곡 허용 +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### 요청에서 토큰이 전송되지 않음 +클라이언트가 `Authorization` 헤더를 보내는지 확인하세요: + +```javascript +// JavaScript 예제 +fetch('/api/users', { + headers: { + 'Authorization': 'Bearer ' + token + } +}); +``` + +## 메서드 + +Firebase JWT 라이브러리는 다음 핵심 메서드를 제공합니다: + +- `JWT::encode(array $payload, string $key, string $alg)`: 페이로드에서 JWT 생성 +- `JWT::decode(string $jwt, Key $key)`: JWT 디코딩 및 확인 +- `JWT::urlsafeB64Encode(string $input)`: Base64 URL-안전 인코딩 +- `JWT::urlsafeB64Decode(string $input)`: Base64 URL-안전 디코딩 +- `JWT::$leeway`: 확인을 위한 시간 여유 설정 정적 속성 (초 단위) + +## 이 라이브러리를 사용하는 이유는? + +- **산업 표준**: Firebase JWT는 PHP에서 가장 인기 있고 신뢰받는 JWT 라이브러리 +- **활성 유지보수**: Google/Firebase 팀이 유지보수 +- **보안 중심**: 정기 업데이트 및 보안 패치 +- **간단한 API**: 이해하고 구현하기 쉬움 +- **잘 문서화됨**: 광범위한 문서와 커뮤니티 지원 +- **유연성**: 여러 알고리즘 및 구성 가능한 옵션 지원 + +## 관련 자료 + +- [Firebase JWT Github 저장소](https://github.com/firebase/php-jwt) +- [JWT.io](https://jwt.io/) - JWT 디버그 및 디코딩 +- [RFC 7519](https://tools.ietf.org/html/rfc7519) - 공식 JWT 사양 +- [Flight 미들웨어 문서](/learn/middleware) +- [Flight 세션 플러그인](/awesome-plugins/session) - 전통적인 세션 기반 인증용 + +## 라이선스 + +Firebase JWT 라이브러리는 BSD 3-Clause License로 라이선스되었습니다. 세부 사항은 [Github 저장소](https://github.com/firebase/php-jwt)를 참조하세요. \ No newline at end of file diff --git a/content/v3/lv/awesome-plugins/awesome_plugins.md b/content/v3/lv/awesome-plugins/awesome_plugins.md index 1d132321..1f5c3a43 100644 --- a/content/v3/lv/awesome-plugins/awesome_plugins.md +++ b/content/v3/lv/awesome-plugins/awesome_plugins.md @@ -4,39 +4,45 @@ Flight ir neticami paplašināms. Ir vairāki spraudņi, ko var izmantot, lai pi ## API dokumentācija -API dokumentācija ir izšķiroša jebkuram API. Tā palīdz izstrādātājiem saprast, kā mijiedarboties ar jūsu API un ko sagaidīt pretī. Ir pieejami vairāki rīki, lai palīdzētu jums ģenerēt API dokumentāciju jūsu Flight projektiem. +API dokumentācija ir izšķiroša jebkurai API. Tā palīdz izstrādātājiem saprast, kā mijiedarboties ar jūsu API un ko sagaidīt pretī. Ir pieejami vairāki rīki, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Bloga ieraksts, ko uzrakstījis Daniels Šreibers par to, kā izmantot OpenAPI specifikāciju ar FlightPHP, lai izveidotu jūsu API, izmantojot API pirmo pieeju. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Bloga ieraksts, ko uzrakstījis Daniels Šraibers par to, kā izmantot OpenAPI specifikāciju ar FlightPHP, lai izveidotu jūsu API, izmantojot API pirmo pieeju. - [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ir lielisks rīks, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. To ir ļoti viegli izmantot, un to var pielāgot jūsu vajadzībām. Šī ir PHP bibliotēka, lai palīdzētu ģenerēt Swagger dokumentāciju. ## Lietojumprogrammas veiktspējas uzraudzība (APM) -Lietojumprogrammas veiktspējas uzraudzība (APM) ir izšķiroša jebkurai lietojumprogrammai. Tā palīdz saprast, kā jūsu lietojumprogramma darbojas un kur ir pudeles kakli. Ir vairāki APM rīki, ko var izmantot ar Flight. +Lietojumprogrammas veiktspējas uzraudzība (APM) ir izšķiroša jebkurai lietojumprogrammai. Tā palīdz jums saprast, kā darbojas jūsu lietojumprogramma un kur ir pudeles kakli. Ir vairāki APM rīki, ko var izmantot ar Flight. - oficiāls [flightphp/apm](/awesome-plugins/apm) - Flight APM ir vienkārša APM bibliotēka, ko var izmantot, lai uzraudzītu jūsu Flight lietojumprogrammas. To var izmantot, lai uzraudzītu jūsu lietojumprogrammas veiktspēju un palīdzētu identificēt pudeles kaklus. ## Async -Flight jau ir ātrs ietvars, bet pievienojot tam turbīnas dzinēju, viss kļūst jautrāks (un izaicināmāks)! +Flight jau ir ātrs ietvars, bet, pievienojot tam turbīnas dzinēju, viss kļūst jautrāks (un izaicinošāks)! - [flightphp/async](/awesome-plugins/async) - Oficiālā Flight Async bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot asinhrono apstrādi jūsu lietojumprogrammai. Tā izmanto Swoole/Openswoole zem pārsega, lai nodrošinātu vienkāršu un efektīvu veidu, kā palaist uzdevumus asinhroni. -## Autorizācija/Atļaujas +## Autorizācija/Atslēgas -Autorizācija un atļaujas ir izšķirošas jebkurai lietojumprogrammai, kas prasa kontroles, lai noteiktu, kas var piekļūt kam. +Autorizācija un atļaujas ir izšķirošas jebkurai lietojumprogrammai, kurai nepieciešami kontroles, lai noteiktu, kas var piekļūt kam. - oficiāls [flightphp/permissions](/awesome-plugins/permissions) - Oficiālā Flight Permissions bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot lietotāja un lietojumprogrammas līmeņa atļaujas jūsu lietojumprogrammai. +## Autentifikācija + +Autentifikācija ir būtiska lietojumprogrammām, kurām jāpārbauda lietotāja identitāte un jānodrošina droši API galapunkti. + +- [firebase/php-jwt](/awesome-plugins/jwt) - JSON Web Token (JWT) bibliotēka PHP. Vienkāršs un drošs veids, kā ieviest tokenu balstītu autentifikāciju jūsu Flight lietojumprogrammās. Ideāli piemērots bezstāvokļa API autentifikācijai, maršrutu aizsardzībai ar starpprogrammatūru un OAuth stila autorizācijas plūsmu ieviešanai. + ## Kešošana Kešošana ir lielisks veids, kā paātrināt jūsu lietojumprogrammu. Ir vairākas kešošanas bibliotēkas, ko var izmantot ar Flight. -- oficiāls [flightphp/cache](/awesome-plugins/php-file-cache) - Viegls, vienkāršs un neatkarīgs PHP failu kešošanas klase +- oficiāls [flightphp/cache](/awesome-plugins/php-file-cache) - Gaisma, vienkārša un neatkarīga PHP failu kešošanas klase ## CLI -CLI lietojumprogrammas ir lielisks veids, kā mijiedarboties ar jūsu lietojumprogrammu. Jūs varat izmantot tās, lai ģenerētu kontrolierus, parādītu visas maršrutus un vairāk. +CLI lietojumprogrammas ir lielisks veids, kā mijiedarboties ar jūsu lietojumprogrammu. Jūs varat izmantot tās, lai ģenerētu kontrolierus, parādītu visus maršrutus un vairāk. -- oficiāls [flightphp/runway](/awesome-plugins/runway) - Runway ir CLI lietojumprogramma, kas palīdz pārvaldīt jūsu Flight lietojumprogrammas. +- oficiāls [flightphp/runway](/awesome-plugins/runway) - Runway ir CLI lietojumprogramma, kas palīdz jums pārvaldīt jūsu Flight lietojumprogrammas. ## Sīkfaili @@ -46,52 +52,52 @@ Sīkfaili ir lielisks veids, kā uzglabāt mazas datu daļas klienta pusē. Tos ## Kļūdu labošana -Kļūdu labošana ir izšķiroša, kad jūs attīstāt savā lokālajā vidē. Ir daži spraudņi, kas var uzlabot jūsu kļūdu labošanas pieredzi. +Kļūdu labošana ir izšķiroša, kad jūs izstrādājat savā lokālajā vidē. Ir daži spraudņi, kas var uzlabot jūsu kļūdu labošanas pieredzi. -- [tracy/tracy](/awesome-plugins/tracy) - Šis ir pilnvērtīgs kļūdu apstrādātājs, ko var izmantot ar Flight. Tam ir vairāki paneļi, kas var palīdzēt labot kļūdas jūsu lietojumprogrammā. To ir arī ļoti viegli paplašināt un pievienot savus paneļus. +- [tracy/tracy](/awesome-plugins/tracy) - Šis ir pilnvērtīgs kļūdu apstrādātājs, ko var izmantot ar Flight. Tam ir vairāki paneļi, kas var palīdzēt jums labot kļūdas jūsu lietojumprogrammā. To ir arī ļoti viegli paplašināt un pievienot savus paneļus. - oficiāls [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Izmantojot ar [Tracy](/awesome-plugins/tracy) kļūdu apstrādātāju, šis spraudnis pievieno dažus papildu paneļus, lai palīdzētu ar kļūdu labošanu tieši Flight projektiem. ## Datubāzes -Datubāzes ir kodols lielākajai daļai lietojumprogrammu. Tādējādi jūs uzglabājat un izgūstat datus. Dažas datubāzu bibliotēkas ir tikai apvalki vaicājumu rakstīšanai, bet dažas ir pilnvērtīgas ORM. +Datubāzes ir kodols lielākajai daļai lietojumprogrammu. Tādējādi jūs uzglabājat un izgūstat datus. Dažas datubāzu bibliotēkas ir vienkārši apvalki vaicājumu rakstīšanai, bet dažas ir pilnvērtīgas ORM. - oficiāls [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Oficiālais Flight PDO apvalks, kas ir daļa no kodola. Šis ir vienkāršs apvalks, lai palīdzētu vienkāršot vaicājumu rakstīšanas un izpildes procesu. Tas nav ORM. -- oficiāls [flightphp/active-record](/awesome-plugins/active-record) - Oficiālā Flight ActiveRecord ORM/Mapper. Lieliska maza bibliotēka vieglai datu izgūšanai un uzglabāšanai jūsu datubāzē. +- oficiāls [flightphp/active-record](/awesome-plugins/active-record) - Oficiālā Flight ActiveRecord ORM/Kartētājs. Lieliska maza bibliotēka, lai viegli izgūtu un uzglabātu datus jūsu datubāzē. - [byjg/php-migration](/awesome-plugins/migrations) - Spraudnis, lai sekotu visām datubāzes izmaiņām jūsu projektā. ## Šifrēšana -Šifrēšana ir izšķiroša jebkurai lietojumprogrammai, kas uzglabā sensitīvus datus. Datu šifrēšana un atšifrēšana nav pārāk grūta, bet pareiza šifrēšanas atslēgas uzglabāšana [var](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [būt](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [grūta](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Visnozīmīgākais ir nekad neuzglabāt jūsu šifrēšanas atslēgu publiskā direktorijā vai neiekļaut to jūsu koda repozitorijā. +Šifrēšana ir izšķiroša jebkurai lietojumprogrammai, kas uzglabā sensitīvus datus. Datu šifrēšana un dešifrēšana nav pārāk grūta, bet pareiza šifrēšanas atslēgas uzglabāšana [var](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [būt](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [grūta](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Visnozīmīgākais ir nekad neuzglabāt savu šifrēšanas atslēgu publiskā direktorijā vai neiekļaut to jūsu koda repozitorijā. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Šī ir bibliotēka, ko var izmantot, lai šifrētu un atšifrētu datus. Sākšana ir diezgan vienkārša, lai sāktu šifrēt un atšifrēt datus. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - Šī ir bibliotēka, ko var izmantot, lai šifrētu un dešifrētu datus. Sākšana un palaišana ir diezgan vienkārša, lai sāktu šifrēt un dešifrēt datus. -## Darbu rinda +## Darba rinda -Darbu rindas ir patiešām noderīgas, lai asinhroni apstrādātu uzdevumus. Tas var būt e-pasta sūtīšana, attēlu apstrāde vai jebkas, kam nav jāveic reāllaikā. +Darba rindas ir patiešām noderīgas, lai asinhroni apstrādātu uzdevumus. Tas var būt e-pasta sūtīšana, attēlu apstrāde vai jebkas, kam nav jāveic reāllaikā. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue ir bibliotēka, ko var izmantot, lai apstrādātu darbus asinhroni. To var izmantot ar beanstalkd, MySQL/MariaDB, SQLite un PostgreSQL. ## Sesija -Sesijas nav īsti noderīgas API, bet veidojot tīmekļa lietojumprogrammu, sesijas var būt izšķirošas stāvokļa un pieteikšanās informācijas uzturēšanai. +Sesijas nav īsti noderīgas API, bet, veidojot tīmekļa lietojumprogrammu, sesijas var būt izšķirošas stāvokļa un pieteikšanās informācijas uzturēšanai. - oficiāls [flightphp/session](/awesome-plugins/session) - Oficiālā Flight Session bibliotēka. Šī ir vienkārša sesijas bibliotēka, ko var izmantot, lai uzglabātu un izgūtu sesijas datus. Tā izmanto PHP iebūvēto sesijas apstrādi. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (neblokējošs, zibspuldze, segments, sesijas šifrēšana). Izmanto PHP open_ssl opcionālai sesijas datu šifrēšanai/atšifrēšanai. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session pārvaldnieks (nebloķējošs, zibspuldze, segments, sesijas šifrēšana). Izmanto PHP open_ssl izvēles šifrēšanai/dešifrēšanai sesijas datiem. ## Veidnes -Veidnes ir kodols jebkurai tīmekļa lietojumprogrammai ar UI. Ir vairāki veidņu dzinēji, ko var izmantot ar Flight. +Veidnes ir kodols jebkurai tīmekļa lietojumprogrammai ar lietotāja interfeisu. Ir vairāki veidņu dzinēji, ko var izmantot ar Flight. - novecojis [flightphp/core View](/learn#views) - Šis ir ļoti pamata veidņu dzinējs, kas ir daļa no kodola. Nav ieteicams izmantot, ja jūsu projektā ir vairāk nekā pāris lapas. -- [latte/latte](/awesome-plugins/latte) - Latte ir pilnvērtīgs veidņu dzinējs, ko ir ļoti viegli izmantot un tas šķiet tuvāks PHP sintaksei nekā Twig vai Smarty. To ir arī ļoti viegli paplašināt un pievienot savus filtrus un funkcijas. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate ir jaudīgs PHP veidņu dzinējs ar resursu kompilāciju, veidnes mantojumu un mainīgo apstrādi. Funkcijas ietver automātisku CSS/JS minimizāciju, kešošanu, Base64 kodēšanu un opcionālu Flight PHP ietvara integrāciju. +- [latte/latte](/awesome-plugins/latte) - Latte ir pilnvērtīgs veidņu dzinējs, kas ir ļoti viegli lietojams un jūtas tuvāk PHP sintaksei nekā Twig vai Smarty. To ir arī ļoti viegli paplašināt un pievienot savus filtrus un funkcijas. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate ir jaudīgs PHP veidņu dzinējs ar resursu kompilāciju, veidņu mantošanu un mainīgo apstrādi. Funkcijas ietver automātisku CSS/JS minimizāciju, kešošanu, Base64 kodēšanu un izvēles Flight PHP ietvara integrāciju. ## WordPress integrācija Vai vēlaties izmantot Flight savā WordPress projektā? Tam ir ērts spraudnis! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Šis WordPress spraudnis ļauj palaist Flight tieši blakus WordPress. Tas ir ideāls, lai pievienotu pielāgotus API, mikroservisu vai pat pilnvērtīgas lietojumprogrammas jūsu WordPress vietnē, izmantojot Flight ietvaru. Ļoti noderīgi, ja vēlaties labāko no abām pasaulēm! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Šis WordPress spraudnis ļauj palaist Flight tieši blakus WordPress. Tas ir ideāli piemērots, lai pievienotu pielāgotas API, mikroservisus vai pat pilnvērtīgas lietojumprogrammas jūsu WordPress vietnē, izmantojot Flight ietvaru. Ļoti noderīgi, ja vēlaties labāko no abām pasaulēm! ## Iesaiste -Vai jums ir spraudnis, ko vēlaties dalīties? Iesniedziet pieprasījumu pēc vilkšanas, lai pievienotu to sarakstam! \ No newline at end of file +Vai jums ir spraudnis, ko vēlaties dalīties? Iesniedziet pieprasījumu, lai pievienotu to sarakstam! \ No newline at end of file diff --git a/content/v3/lv/awesome-plugins/jwt.md b/content/v3/lv/awesome-plugins/jwt.md new file mode 100644 index 00000000..b206c5d0 --- /dev/null +++ b/content/v3/lv/awesome-plugins/jwt.md @@ -0,0 +1,532 @@ +# Firebase JWT - JSON Web Token autentifikācija Flight + +JWT (JSON Web Tokens) ir kompakts, URL-drošs veids, kā pārstāvēt pretenzijas starp jūsu lietojumprogrammu un klientu. Tie ir ideāli piemēroti bezstāvokļa API autentifikācijai — nav vajadzīga servera puses sesiju uzglabāšana! Šis ceļvedis parāda, kā integrēt [Firebase JWT](https://github.com/firebase/php-jwt) ar Flight drošai, tokenu balstītai autentifikācijai. + +Apmeklējiet [Github krātuvi](https://github.com/firebase/php-jwt), lai iegūtu pilnu dokumentāciju un detaļas. + +## Kas ir JWT? + +JSON Web Token ir virkne, kas satur trīs daļas: +1. **Virsnieks**: Metadati par tokenu (algoritms, tips) +2. **Ladējums**: Jūsu dati (lietotāja ID, lomas, termiņš utt.) +3. **Paraksts**: Kriptogrāfiskais paraksts autentiskuma pārbaudei + +Piemērs JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (izskatās pēc muļķībām, bet tas ir strukturēti dati!) + +### Kāpēc izmantot JWT? + +- **Bezstāvoklis**: Nav vajadzīga servera puses sesiju uzglabāšana — ideāli piemērots mikroservisiem un API +- **Mērogojams**: Labi darbojas ar slodzes līdzsvarotājjiem, jo nav sesiju saistības prasības +- **Pārrobežu**: Var izmantot dažādās domēnos un servisos +- **Mobilajām ierīcēm draudzīgs**: Lieliski piemērots mobilajām lietojumprogrammām, kur sīkfaili var nedarboties labi +- **Standartizēts**: Nozares standarta pieeja (RFC 7519) + +## Instalēšana + +Instalējiet, izmantojot Composer: + +```bash +composer require firebase/php-jwt +``` + +## Pamata izmantošana + +Šeit ir ātrs piemērs tokena izveidei un pārbaudei: + +```php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; + +// Jūsu slepenā atslēga (TURĒT TO DROŠU!) +$secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; + +// Izveidojiet tokenu +$payload = [ + 'user_id' => 123, + 'username' => 'johndoe', + 'role' => 'admin', + 'iat' => time(), // Izsniegts + 'exp' => time() + 3600 // Beidzas pēc 1 stundas +]; + +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +echo "Token: " . $jwt; + +// Pārbaudiet un atšifrējiet tokenu +try { + $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + echo "User ID: " . $decoded->user_id; +} catch (Exception $e) { + echo "Nederīgs tokens: " . $e->getMessage(); +} +``` + +## JWT starpprogrammatūra Flight (Ieteicamais pieeja) + +Visizplatītākais un noderīgākais veids, kā izmantot JWT ar Flight, ir kā **starpprogrammatūru**, lai aizsargātu jūsu API maršrutus. Šeit ir pilnīgs, ražošanai gatavs piemērs: + +### 1. solis: Izveidojiet JWT starpprogrammatūras klasi + +```php +// app/middleware/JwtMiddleware.php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; +use Firebase\JWT\ExpiredException; +use Firebase\JWT\SignatureInvalidException; +use flight\Engine; + +class JwtMiddleware { + + protected Engine $app; + protected string $secretKey; + + public function __construct(Engine $app) { + $this->app = $app; + // Uzglabājiet savu slepeno atslēgu app/config/config.php, nevis cietkodus! + $this->secretKey = $app->get('config')['jwt_secret']; + } + + public function before(array $params) { + $authHeader = $this->app->request()->getHeader('Authorization'); + + // Pārbaudiet, vai pastāv autorizācijas virsraksts + if (empty($authHeader)) { + $this->app->jsonHalt(['error' => 'Nav nodrošināts autorizācijas tokens'], 401); + } + + // Izvilciet tokenu no "Bearer " formāta + if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { + $this->app->jsonHalt(['error' => 'Nederīgs autorizācijas formāts. Izmantojiet: Bearer '], 401); + } + + $jwt = $matches[1]; + + try { + // Atšifrējiet un pārbaudiet tokenu + $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); + + // Uzglabājiet lietotāja datus pieprasījumā, lai izmantotu maršruta apstrādātājos + $this->app->request()->data->user = $decoded; + + } catch (ExpiredException $e) { + $this->app->jsonHalt(['error' => 'Tokens ir beidzies'], 401); + } catch (SignatureInvalidException $e) { + $this->app->jsonHalt(['error' => 'Nederīgs tokena paraksts'], 401); + } catch (Exception $e) { + $this->app->jsonHalt(['error' => 'Nederīgs tokens: ' . $e->getMessage()], 401); + } + } +} +``` + +### 2. solis: Reģistrējiet JWT slepeno atslēgu savā konfigurācijā + +```php +// app/config/config.php +return [ + 'jwt_secret' => getenv('JWT_SECRET') ?: 'your-fallback-secret-for-development' +]; + +// app/config/bootstrap.php vai index.php +// pārliecinieties, ka pievienojat šo rindu, ja vēlaties pakļaut konfigurāciju lietojumprogrammai +$app->set('config', $config); +``` + +> **Drošības piezīme**: Nekad necietkodējiet savu slepeno atslēgu! Izmantojiet vides mainīgos ražošanā. + +### 3. solis: Aizsargājiet savus maršrutus ar starpprogrammatūru + +```php +// Aizsargājiet vienu maršrutu +Flight::route('GET /api/user/profile', function() { + $user = Flight::request()->data->user; // Iestatīts ar starpprogrammatūru + Flight::json([ + 'user_id' => $user->user_id, + 'username' => $user->username, + 'role' => $user->role + ]); +})->addMiddleware( JwtMiddleware::class); + +// Aizsargājiet veselu maršrutu grupu (biežāk!) +Flight::group('/api', function() { + Flight::route('GET /users', function() { /* ... */ }); + Flight::route('GET /posts', function() { /* ... */ }); + Flight::route('POST /posts', function() { /* ... */ }); + Flight::route('DELETE /posts/@id', function($id) { /* ... */ }); +}, [ JwtMiddleware::class ]); // Visi maršruti šajā grupā ir aizsargāti! +``` + +Lai iegūtu vairāk detaļu par starpprogrammatūru, skatiet [starpprogrammatūras dokumentāciju](/learn/middleware). + +## Izplatīti izmantošanas gadījumi + +### 1. Pieteikšanās galapunkts (Tokena ģenerēšana) + +Izveidojiet maršrutu, kas ģenerē JWT pēc veiksmīgas autentifikācijas: + +```php +Flight::route('POST /api/login', function() { + $data = Flight::request()->data; + $username = $data->username ?? ''; + $password = $data->password ?? ''; + + // Validējiet akreditācijas datus (piemērs — izmantojiet savu loģiku!) + $user = validateUserCredentials($username, $password); + + if (!$user) { + Flight::jsonHalt(['error' => 'Nederīgas akreditācijas'], 401); + } + + // Ģenerējiet JWT + $secretKey = Flight::get('config')['jwt_secret']; + $payload = [ + 'user_id' => $user->id, + 'username' => $user->username, + 'role' => $user->role, + 'iat' => time(), + 'exp' => time() + (60 * 60) // 1 stundas termiņš + ]; + + $jwt = JWT::encode($payload, $secretKey, 'HS256'); + + Flight::json([ + 'success' => true, + 'token' => $jwt, + 'expires_in' => 3600 + ]); +}); + +function validateUserCredentials($username, $password) { + // Jūsu datubāzes meklēšana un paroles pārbaude šeit + // Piemērs: + $db = Flight::db(); + $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); + + if ($user && password_verify($password, $user['password_hash'])) { + return (object) [ + 'id' => $user['id'], + 'username' => $user['username'], + 'role' => $user['role'] + ]; + } + return null; +} +``` + +### 2. Tokena atjaunošanas plūsma + +Īstenojiet atjaunošanas tokena sistēmu ilgstošām sesijām: + +```php +Flight::route('POST /api/login', function() { + // ... validējiet akreditācijas datus ... + + $secretKey = Flight::get('config')['jwt_secret']; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + // Īstermiņa piekļuves tokens (15 minūtes) + $accessToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + // Ilgtermiņa atjaunošanas tokens (7 dienas) + $refreshToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'refresh', + 'iat' => time(), + 'exp' => time() + (7 * 24 * 60 * 60) + ], $refreshSecret, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'refresh_token' => $refreshToken, + 'expires_in' => 900 + ]); +}); + +Flight::route('POST /api/refresh', function() { + $refreshToken = Flight::request()->data->refresh_token ?? ''; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + try { + $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); + + // Pārbaudiet, vai tas ir atjaunošanas tokens + if ($decoded->type !== 'refresh') { + Flight::jsonHalt(['error' => 'Nederīgs tokena tips'], 401); + } + + // Ģenerējiet jaunu piekļuves tokenu + $secretKey = Flight::get('config')['jwt_secret']; + $accessToken = JWT::encode([ + 'user_id' => $decoded->user_id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'expires_in' => 900 + ]); + + } catch (Exception $e) { + Flight::jsonHalt(['error' => 'Nederīgs atjaunošanas tokens'], 401); + } +}); +``` + +### 3. Lomu balstīta piekļuves kontrole + +Paplašiniet savu starpprogrammatūru, lai pārbaudītu lietotāja lomas: + +```php +class JwtRoleMiddleware { + + protected Engine $app; + protected array $allowedRoles; + + public function __construct(Engine $app, array $allowedRoles = []) { + $this->app = $app; + $this->allowedRoles = $allowedRoles; + } + + public function before(array $params) { + // Pieņemiet, ka JwtMiddleware jau darbojās un iestatīja lietotāja datus + $user = $this->app->request()->data->user ?? null; + + if (!$user) { + $this->app->jsonHalt(['error' => 'Nepieciešama autentifikācija'], 401); + } + + // Pārbaudiet, vai lietotājam ir nepieciešamā loma + if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { + $this->app->jsonHalt(['error' => 'Nepietiekamas atļaujas'], 403); + } + } +} + +// Lietojums: Tikai administratora maršruts +Flight::route('DELETE /api/users/@id', function($id) { + // Dzēst lietotāja loģiku +})->addMiddleware([ + JwtMiddleware::class, + new JwtRoleMiddleware(Flight::app(), ['admin']) +]); +``` + +### 4. Publiska API ar ātruma ierobežošanu pēc lietotāja + +Izmantojiet JWT, lai izsekotu un ierobežotu ātrumu lietotājiem bez sesijām: + +```php +class RateLimitMiddleware { + + public function before(array $params) { + $user = Flight::request()->data->user ?? null; + $userId = $user ? $user->user_id : Flight::request()->ip; + + $cacheKey = "rate_limit:$userId"; + // Pārliecinieties, ka iestatāt kešatmiņas servisu app/config/services.php + $requests = Flight::cache()->get($cacheKey, 0); + + if ($requests >= 100) { // 100 pieprasījumi stundā + Flight::jsonHalt(['error' => 'Ātruma ierobežojums pārsniegts'], 429); + } + + Flight::cache()->set($cacheKey, $requests + 1, 3600); + } +} +``` + +## Drošības labākās prakses + +### 1. Izmantojiet spēcīgas slepenās atslēgas + +```php +// Ģenerējiet drošu slepeno atslēgu (palaižiet vienreiz, saglabājiet .env failā) +$secretKey = base64_encode(random_bytes(32)); +echo $secretKey; // Uzglabājiet to savā .env failā! +``` + +### 2. Uzglabājiet noslēpumus vides mainīgajos + +```php +// Nekad neapņemiet noslēpumus versiju kontrolē! +// Izmantojiet .env failu un bibliotēku, piemēram, vlucas/phpdotenv + +// .env fails: +// JWT_SECRET=your-base64-encoded-secret-here +// JWT_REFRESH_SECRET=another-base64-encoded-secret-here + +// Varat arī izmantot app/config/config.php failu, lai uzglabātu savus noslēpumus +// tikai pārliecinieties, ka konfigurācijas fails nav apņemts versiju kontrolē +// return [ +// 'jwt_secret' => 'your-base64-encoded-secret-here', +// 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', +// ]; + +// Savā lietojumprogrammā: +$secretKey = getenv('JWT_SECRET'); +``` + +### 3. Iestatiet piemērotus termiņu laikus + +```php +// Labā prakse: īstermiņa piekļuves tokeni +'exp' => time() + (15 * 60) // 15 minūtes + +// Atjaunošanas tokeniem: ilgāks termiņš +'exp' => time() + (7 * 24 * 60 * 60) // 7 dienas +``` + +### 4. Izmantojiet HTTPS ražošanā + +JWT vienmēr jāpārsūta pār HTTPS. Nekad nesūtiet tokenus pār vienkāršu HTTP ražošanā! + +### 5. Validējiet tokena pretenzijas + +Vienmēr validējiet pretenzijas, kas jums rūp: + +```php +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + +// Pārbaudiet termiņu, ko bibliotēka automātiski apstrādā +// Bet varat pievienot pielāgotas validācijas: +if ($decoded->iat > time()) { + throw new Exception('Tokens izmantots pirms izsniegšanas'); +} + +if (isset($decoded->nbf) && $decoded->nbf > time()) { + throw new Exception('Tokens vēl nav derīgs'); +} +``` + +### 6. Apsveriet tokena melno sarakstu izrakstīšanai + +Papildu drošībai uzturiet nederīgu tokenu melno sarakstu: + +```php +Flight::route('POST /api/logout', function() { + $authHeader = Flight::request()->getHeader('Authorization'); + preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches); + $jwt = $matches[1]; + + // Izvilciet tokena termiņu + $decoded = Flight::request()->data->user; + $ttl = $decoded->exp - time(); + + // Uzglabājiet kešatmiņā/redis līdz termiņam + Flight::cache()->set("blacklist:$jwt", true, $ttl); + + Flight::json(['message' => 'Veiksmīgi izrakstījies']); +}); + +// Pievienojiet savai JwtMiddleware: +public function before(array $params) { + // ... izvilciet JWT ... + + // Pārbaudiet melno sarakstu + if (Flight::cache()->get("blacklist:$jwt")) { + $this->app->jsonHalt(['error' => 'Tokens ir atcelts'], 401); + } + + // ... pārbaudiet tokenu ... +} +``` + +## Algoritmi un atslēgu tipi + +Firebase JWT atbalsta vairākus algoritmus: + +### Simetriskie algoritmi (HMAC) +- **HS256** (Ieteicams lielākajai daļai lietojumprogrammu): Izmanto vienu slepeno atslēgu +- **HS384**, **HS512**: Spēcīgākas variācijas + +```php +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Asimetriskie algoritmi (RSA/ECDSA) +- **RS256**, **RS384**, **RS512**: Izmanto publisko/privāto atslēgu pārus +- **ES256**, **ES384**, **ES512**: Elipses līknes variācijas + +```php +// Ģenerējiet atslēgas: openssl genrsa -out private.key 2048 +// openssl rsa -in private.key -pubout -out public.key + +$privateKey = file_get_contents('/path/to/private.key'); +$publicKey = file_get_contents('/path/to/public.key'); + +// Kodējiet ar privāto atslēgu +$jwt = JWT::encode($payload, $privateKey, 'RS256'); + +// Atšifrējiet ar publisko atslēgu +$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); +``` + +> **Kad izmantot RSA**: Izmantojiet RSA, kad nepieciešams izplatīt publisko atslēgu pārbaudei (piem., mikroservisi, trešo pušu integrācijas). Vienai lietojumprogrammai HS256 ir vienkāršāks un pietiekams. + +## Traucējummeklēšana + +### "Beidzies tokens" kļūda +Jūsu tokena `exp` pretenzija ir pagātnē. Izsniedziet jaunu tokenu vai īstenojiet tokena atjaunošanu. + +### "Paraksta pārbaude neizdevās" +- Jūs izmantojat citu slepeno atslēgu atšifrēšanai nekā kodēšanai +- Tokens ir modificēts +- Laika nobīde starp serveriem (pievienojiet atlaidzes buferi) + +```php +use Firebase\JWT\JWT; + +JWT::$leeway = 60; // Ļauj 60 sekunžu laika nobīdi +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Tokens netiek nosūtīts pieprasījumos +Pārliecinieties, ka jūsu klients nosūta `Authorization` virsrakstu: + +```javascript +// JavaScript piemērs +fetch('/api/users', { + headers: { + 'Authorization': 'Bearer ' + token + } +}); +``` + +## Metodes + +Firebase JWT bibliotēka nodrošina šīs pamata metodes: + +- `JWT::encode(array $payload, string $key, string $alg)`: Izveido JWT no ladējuma +- `JWT::decode(string $jwt, Key $key)`: Atšifrē un pārbauda JWT +- `JWT::urlsafeB64Encode(string $input)`: Base64 URL-droša kodēšana +- `JWT::urlsafeB64Decode(string $input)`: Base64 URL-droša atšifrēšana +- `JWT::$leeway`: Statiska īpašība, lai iestatītu laika atlaidzi validācijai (sekundēs) + +## Kāpēc izmantot šo bibliotēku? + +- **Nozares standarts**: Firebase JWT ir populārākā un plaši uzticamā JWT bibliotēka PHP +- **Aktīva uzturēšana**: Uztur Google/Firebase komanda +- **Uz drošību orientēta**: Regulāras atjauninājumi un drošības labojumi +- **Vienkārša API**: Viegli saprotama un īstenojama +- **Labu dokumentēšana**: Plaša dokumentācija un kopienas atbalsts +- **Elastīga**: Atbalsta vairākus algoritmus un konfigurējamās opcijas + +## Skatīt arī + +- [Firebase JWT Github krātuve](https://github.com/firebase/php-jwt) +- [JWT.io](https://jwt.io/) - Kļūdu labošana un JWT atšifrēšana +- [RFC 7519](https://tools.ietf.org/html/rfc7519) - Oficiālā JWT specifikācija +- [Flight starpprogrammatūras dokumentācija](/learn/middleware) +- [Flight sesijas spraudnis](/awesome-plugins/session) - Tradicionālai sesiju balstītai autentifikācijai + +## Licence + +Firebase JWT bibliotēka ir licencēta saskaņā ar BSD 3-Klauzulas licenci. Skatiet [Github krātuvi](https://github.com/firebase/php-jwt) detaļām. \ No newline at end of file diff --git a/content/v3/pt/awesome-plugins/awesome_plugins.md b/content/v3/pt/awesome-plugins/awesome_plugins.md index 62b62c07..f5f1940b 100644 --- a/content/v3/pt/awesome-plugins/awesome_plugins.md +++ b/content/v3/pt/awesome-plugins/awesome_plugins.md @@ -12,7 +12,7 @@ A documentação de API é crucial para qualquer API. Ela ajuda os desenvolvedor ## Monitoramento de Desempenho de Aplicação (APM) O Monitoramento de Desempenho de Aplicação (APM) é crucial para qualquer aplicação. Ele ajuda você a entender como sua aplicação está se saindo e onde estão os gargalos. Existem vários ferramentas APM que podem ser usadas com Flight. -- oficial [flightphp/apm](/awesome-plugins/apm) - Flight APM é uma biblioteca APM simples que pode ser usada para monitorar suas aplicações Flight. Pode ser usada para monitorar o desempenho da sua aplicação e ajudá-lo a identificar gargalos. +- oficial [flightphp/apm](/awesome-plugins/apm) - Flight APM é uma biblioteca APM simples que pode ser usada para monitorar suas aplicações Flight. Ela pode ser usada para monitorar o desempenho da sua aplicação e ajudá-lo a identificar gargalos. ## Async @@ -26,6 +26,12 @@ Autorização e Permissões são cruciais para qualquer aplicação que exija co - oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca de Permissões oficial do Flight. Esta biblioteca é uma maneira simples de adicionar permissões em nível de usuário e aplicação à sua aplicação. +## Autenticação + +A autenticação é essencial para aplicações que precisam verificar a identidade do usuário e proteger endpoints de API. + +- [firebase/php-jwt](/awesome-plugins/jwt) - Biblioteca JSON Web Token (JWT) para PHP. Uma maneira simples e segura de implementar autenticação baseada em tokens em suas aplicações Flight. Perfeita para autenticação de API stateless, proteção de rotas com middleware e implementação de fluxos de autorização no estilo OAuth. + ## Cache O cache é uma ótima maneira de acelerar sua aplicação. Existem várias bibliotecas de cache que podem ser usadas com Flight. @@ -48,42 +54,42 @@ Cookies são uma ótima maneira de armazenar pequenos pedaços de dados no lado A depuração é crucial quando você está desenvolvendo em seu ambiente local. Existem alguns plugins que podem elevar sua experiência de depuração. -- [tracy/tracy](/awesome-plugins/tracy) - Esta é uma manipuladora de erros completa que pode ser usada com Flight. Ela tem vários painéis que podem ajudá-lo a depurar sua aplicação. Também é muito fácil de estender e adicionar seus próprios painéis. -- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado com o manipulador de erros [Tracy](/awesome-plugins/tracy), este plugin adiciona alguns painéis extras para ajudar com a depuração especificamente para projetos Flight. +- [tracy/tracy](/awesome-plugins/tracy) - Este é um manipulador de erros completo que pode ser usado com Flight. Ele tem vários painéis que podem ajudá-lo a depurar sua aplicação. Também é muito fácil de estender e adicionar seus próprios painéis. +- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado com o manipulador de erros [Tracy](/awesome-plugins/tracy), este plugin adiciona alguns painéis extras para ajudar na depuração especificamente para projetos Flight. ## Bancos de Dados -Bancos de dados são o núcleo da maioria das aplicações. É assim que você armazena e recupera dados. Algumas bibliotecas de banco de dados são simplesmente wrappers para escrever consultas e algumas são ORMs completos. +Bancos de dados são o núcleo da maioria das aplicações. É assim que você armazena e recupera dados. Algumas bibliotecas de banco de dados são simplesmente wrappers para escrever consultas e outras são ORMs completos. - oficial [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO oficial do Flight que faz parte do núcleo. Este é um wrapper simples para ajudar a simplificar o processo de escrever consultas e executá-las. Não é um ORM. - oficial [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord oficial do Flight. Ótima biblioteca pequena para recuperar e armazenar dados facilmente em seu banco de dados. -- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para manter o controle de todas as alterações de banco de dados para seu projeto. +- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para rastrear todas as alterações de banco de dados para seu projeto. ## Criptografia -A criptografia é crucial para qualquer aplicação que armazena dados sensíveis. Criptografar e descriptografar os dados não é terrivelmente difícil, mas armazenar adequadamente a chave de criptografia [pode](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [ser](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difícil](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). O mais importante é nunca armazenar sua chave de criptografia em um diretório público ou commitá-la em seu repositório de código. +A criptografia é crucial para qualquer aplicação que armazena dados sensíveis. Criptografar e descriptografar os dados não é terrivelmente difícil, mas armazenar corretamente a chave de criptografia [pode](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [ser](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difícil](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). O mais importante é nunca armazenar sua chave de criptografia em um diretório público ou commitá-la em seu repositório de código. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Esta é uma biblioteca que pode ser usada para criptografar e descriptografar dados. Começar a usar é bastante simples para começar a criptografar e descriptografar dados. ## Fila de Tarefas -Filas de tarefas são realmente úteis para processar tarefas de forma assíncrona. Isso pode ser o envio de e-mails, processamento de imagens ou qualquer coisa que não precise ser feita em tempo real. +Filas de tarefas são realmente úteis para processar tarefas de forma assíncrona. Isso pode ser enviar e-mails, processar imagens ou qualquer coisa que não precise ser feita em tempo real. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue é uma biblioteca que pode ser usada para processar tarefas de forma assíncrona. Pode ser usada com beanstalkd, MySQL/MariaDB, SQLite e PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue é uma biblioteca que pode ser usada para processar tarefas de forma assíncrona. Ela pode ser usada com beanstalkd, MySQL/MariaDB, SQLite e PostgreSQL. ## Sessão Sessões não são realmente úteis para APIs, mas para construir uma aplicação web, sessões podem ser cruciais para manter o estado e informações de login. -- oficial [flightphp/session](/awesome-plugins/session) - Biblioteca de Sessão oficial do Flight. Esta é uma biblioteca de sessão simples que pode ser usada para armazenar e recuperar dados de sessão. Ela usa o manuseio de sessão integrado do PHP. +- oficial [flightphp/session](/awesome-plugins/session) - Biblioteca de Sessão oficial do Flight. Esta é uma biblioteca de sessão simples que pode ser usada para armazenar e recuperar dados de sessão. Ela usa o manipulador de sessão integrado do PHP. - [Ghostff/Session](/awesome-plugins/ghost-session) - Gerenciador de Sessão PHP (não bloqueante, flash, segmento, criptografia de sessão). Usa PHP open_ssl para criptografia/descriptografia opcional de dados de sessão. ## Templating O templating é o núcleo de qualquer aplicação web com uma UI. Existem vários motores de templating que podem ser usados com Flight. -- deprecado [flightphp/core View](/learn#views) - Este é um motor de templating muito básico que faz parte do núcleo. Não é recomendado usá-lo se você tiver mais do que algumas páginas em seu projeto. -- [latte/latte](/awesome-plugins/latte) - Latte é um motor de templating completo que é muito fácil de usar e se sente mais próximo da sintaxe PHP do que Twig ou Smarty. Também é muito fácil de estender e adicionar seus próprios filtros e funções. +- deprecado [flightphp/core View](/learn#views) - Este é um motor de templating muito básico que faz parte do núcleo. Não é recomendado usá-lo se você tiver mais de algumas páginas em seu projeto. +- [latte/latte](/awesome-plugins/latte) - Latte é um motor de templating completo que é muito fácil de usar e se sente mais próximo de uma sintaxe PHP do que Twig ou Smarty. Também é muito fácil de estender e adicionar seus próprios filtros e funções. - [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate é um poderoso motor de template PHP com compilação de assets, herança de templates e processamento de variáveis. Recursos incluem minificação automática de CSS/JS, cache, codificação Base64 e integração opcional com o framework Flight PHP. ## Integração com WordPress diff --git a/content/v3/pt/awesome-plugins/jwt.md b/content/v3/pt/awesome-plugins/jwt.md new file mode 100644 index 00000000..750e89b8 --- /dev/null +++ b/content/v3/pt/awesome-plugins/jwt.md @@ -0,0 +1,532 @@ +# Firebase JWT - Autenticação com JSON Web Token para Flight + +JWT (JSON Web Tokens) são uma forma compacta e segura para URLs de representar reivindicações entre sua aplicação e um cliente. Eles são perfeitos para autenticação de API stateless — sem necessidade de armazenamento de sessão no lado do servidor! Este guia mostra como integrar [Firebase JWT](https://github.com/firebase/php-jwt) com Flight para autenticação segura baseada em tokens. + +Visite o [repositório no Github](https://github.com/firebase/php-jwt) para documentação completa e detalhes. + +## O que é JWT? + +Um JSON Web Token é uma string que contém três partes: +1. **Header**: Metadados sobre o token (algoritmo, tipo) +2. **Payload**: Seus dados (ID do usuário, papéis, expiração, etc.) +3. **Signature**: Assinatura criptográfica para verificar a autenticidade + +Exemplo de JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (parece gibberish, mas é dados estruturados!) + +### Por que Usar JWT? + +- **Stateless**: Não é necessário armazenamento de sessão no lado do servidor — perfeito para microsserviços e APIs +- **Escalável**: Funciona bem com balanceadores de carga, pois não há requisito de afinidade de sessão +- **Cross-Domain**: Pode ser usado em diferentes domínios e serviços +- **Amigável para Mobile**: Ótimo para apps móveis onde cookies podem não funcionar bem +- **Padronizado**: Abordagem padrão da indústria (RFC 7519) + +## Instalação + +Instale via Composer: + +```bash +composer require firebase/php-jwt +``` + +## Uso Básico + +Aqui está um exemplo rápido de criação e verificação de um JWT: + +```php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; + +// Sua chave secreta (MANTENHA ISSO SEGURO!) +$secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; + +// Crie um token +$payload = [ + 'user_id' => 123, + 'username' => 'johndoe', + 'role' => 'admin', + 'iat' => time(), // Emitido em + 'exp' => time() + 3600 // Expira em 1 hora +]; + +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +echo "Token: " . $jwt; + +// Verifique e decodifique um token +try { + $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + echo "User ID: " . $decoded->user_id; +} catch (Exception $e) { + echo "Invalid token: " . $e->getMessage(); +} +``` + +## Middleware JWT para Flight (Abordagem Recomendada) + +A forma mais comum e útil de usar JWT com Flight é como **middleware** para proteger suas rotas de API. Aqui está um exemplo completo, pronto para produção: + +### Passo 1: Crie uma Classe de Middleware JWT + +```php +// app/middleware/JwtMiddleware.php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; +use Firebase\JWT\ExpiredException; +use Firebase\JWT\SignatureInvalidException; +use flight\Engine; + +class JwtMiddleware { + + protected Engine $app; + protected string $secretKey; + + public function __construct(Engine $app) { + $this->app = $app; + // Armazene sua chave secreta em app/config/config.php, NÃO hardcoded! + $this->secretKey = $app->get('config')['jwt_secret']; + } + + public function before(array $params) { + $authHeader = $this->app->request()->getHeader('Authorization'); + + // Verifique se o header de autorização existe + if (empty($authHeader)) { + $this->app->jsonHalt(['error' => 'No authorization token provided'], 401); + } + + // Extraia o token do formato "Bearer " + if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { + $this->app->jsonHalt(['error' => 'Invalid authorization format. Use: Bearer '], 401); + } + + $jwt = $matches[1]; + + try { + // Decodifique e verifique o token + $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); + + // Armazene os dados do usuário na requisição para uso em manipuladores de rota + $this->app->request()->data->user = $decoded; + + } catch (ExpiredException $e) { + $this->app->jsonHalt(['error' => 'Token has expired'], 401); + } catch (SignatureInvalidException $e) { + $this->app->jsonHalt(['error' => 'Invalid token signature'], 401); + } catch (Exception $e) { + $this->app->jsonHalt(['error' => 'Invalid token: ' . $e->getMessage()], 401); + } + } +} +``` + +### Passo 2: Registre a Chave Secreta JWT na Sua Configuração + +```php +// app/config/config.php +return [ + 'jwt_secret' => getenv('JWT_SECRET') ?: 'your-fallback-secret-for-development' +]; + +// app/config/bootstrap.php or index.php +// certifique-se de adicionar esta linha se quiser expor a configuração para o app +$app->set('config', $config); +``` + +> **Nota de Segurança**: Nunca hardcode sua chave secreta! Use variáveis de ambiente em produção. + +### Passo 3: Proteja Suas Rotas com Middleware + +```php +// Proteja uma rota única +Flight::route('GET /api/user/profile', function() { + $user = Flight::request()->data->user; // Definido pelo middleware + Flight::json([ + 'user_id' => $user->user_id, + 'username' => $user->username, + 'role' => $user->role + ]); +})->addMiddleware( JwtMiddleware::class); + +// Proteja um grupo inteiro de rotas (mais comum!) +Flight::group('/api', function() { + Flight::route('GET /users', function() { /* ... */ }); + Flight::route('GET /posts', function() { /* ... */ }); + Flight::route('POST /posts', function() { /* ... */ }); + Flight::route('DELETE /posts/@id', function($id) { /* ... */ }); +}, [ JwtMiddleware::class ]); // Todas as rotas neste grupo estão protegidas! +``` + +Para mais detalhes sobre middleware, veja a [documentação de middleware](/learn/middleware). + +## Casos de Uso Comuns + +### 1. Endpoint de Login (Geração de Token) + +Crie uma rota que gera um JWT após autenticação bem-sucedida: + +```php +Flight::route('POST /api/login', function() { + $data = Flight::request()->data; + $username = $data->username ?? ''; + $password = $data->password ?? ''; + + // Valide credenciais (exemplo - use sua própria lógica!) + $user = validateUserCredentials($username, $password); + + if (!$user) { + Flight::jsonHalt(['error' => 'Invalid credentials'], 401); + } + + // Gere JWT + $secretKey = Flight::get('config')['jwt_secret']; + $payload = [ + 'user_id' => $user->id, + 'username' => $user->username, + 'role' => $user->role, + 'iat' => time(), + 'exp' => time() + (60 * 60) // 1 hora de expiração + ]; + + $jwt = JWT::encode($payload, $secretKey, 'HS256'); + + Flight::json([ + 'success' => true, + 'token' => $jwt, + 'expires_in' => 3600 + ]); +}); + +function validateUserCredentials($username, $password) { + // Sua consulta ao banco de dados e verificação de senha aqui + // Exemplo: + $db = Flight::db(); + $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); + + if ($user && password_verify($password, $user['password_hash'])) { + return (object) [ + 'id' => $user['id'], + 'username' => $user['username'], + 'role' => $user['role'] + ]; + } + return null; +} +``` + +### 2. Fluxo de Atualização de Token + +Implemente um sistema de token de atualização para sessões de longa duração: + +```php +Flight::route('POST /api/login', function() { + // ... valide credenciais ... + + $secretKey = Flight::get('config')['jwt_secret']; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + // Token de acesso de curta duração (15 minutos) + $accessToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + // Token de atualização de longa duração (7 dias) + $refreshToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'refresh', + 'iat' => time(), + 'exp' => time() + (7 * 24 * 60 * 60) + ], $refreshSecret, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'refresh_token' => $refreshToken, + 'expires_in' => 900 + ]); +}); + +Flight::route('POST /api/refresh', function() { + $refreshToken = Flight::request()->data->refresh_token ?? ''; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + try { + $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); + + // Verifique se é um token de atualização + if ($decoded->type !== 'refresh') { + Flight::jsonHalt(['error' => 'Invalid token type'], 401); + } + + // Gere novo token de acesso + $secretKey = Flight::get('config')['jwt_secret']; + $accessToken = JWT::encode([ + 'user_id' => $decoded->user_id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'expires_in' => 900 + ]); + + } catch (Exception $e) { + Flight::jsonHalt(['error' => 'Invalid refresh token'], 401); + } +}); +``` + +### 3. Controle de Acesso Baseado em Papéis + +Estenda seu middleware para verificar papéis de usuário: + +```php +class JwtRoleMiddleware { + + protected Engine $app; + protected array $allowedRoles; + + public function __construct(Engine $app, array $allowedRoles = []) { + $this->app = $app; + $this->allowedRoles = $allowedRoles; + } + + public function before(array $params) { + // Assuma que JwtMiddleware já executou e definiu os dados do usuário + $user = $this->app->request()->data->user ?? null; + + if (!$user) { + $this->app->jsonHalt(['error' => 'Authentication required'], 401); + } + + // Verifique se o usuário tem o papel necessário + if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { + $this->app->jsonHalt(['error' => 'Insufficient permissions'], 403); + } + } +} + +// Uso: Rota apenas para admin +Flight::route('DELETE /api/users/@id', function($id) { + // Lógica de exclusão de usuário +})->addMiddleware([ + JwtMiddleware::class, + new JwtRoleMiddleware(Flight::app(), ['admin']) +]); +``` + +### 4. API Pública com Limitação de Taxa por Usuário + +Use JWT para rastrear e limitar a taxa de usuários sem sessões: + +```php +class RateLimitMiddleware { + + public function before(array $params) { + $user = Flight::request()->data->user ?? null; + $userId = $user ? $user->user_id : Flight::request()->ip; + + $cacheKey = "rate_limit:$userId"; + // Certifique-se de configurar um serviço de cache em app/config/services.php + $requests = Flight::cache()->get($cacheKey, 0); + + if ($requests >= 100) { // 100 requisições por hora + Flight::jsonHalt(['error' => 'Rate limit exceeded'], 429); + } + + Flight::cache()->set($cacheKey, $requests + 1, 3600); + } +} +``` + +## Melhores Práticas de Segurança + +### 1. Use Chaves Secretas Fortes + +```php +// Gere uma chave secreta segura (execute uma vez, salve no arquivo .env) +$secretKey = base64_encode(random_bytes(32)); +echo $secretKey; // Armazene isso no seu arquivo .env! +``` + +### 2. Armazene Segredos em Variáveis de Ambiente + +```php +// Nunca commite segredos no controle de versão! +// Use um arquivo .env e biblioteca como vlucas/phpdotenv + +// Arquivo .env: +// JWT_SECRET=your-base64-encoded-secret-here +// JWT_REFRESH_SECRET=another-base64-encoded-secret-here + +// Você também pode usar o arquivo app/config/config.php para armazenar seus segredos +// apenas certifique-se de que o arquivo de configuração não seja commitado no controle de versão +// return [ +// 'jwt_secret' => 'your-base64-encoded-secret-here', +// 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', +// ]; + +// Na sua app: +$secretKey = getenv('JWT_SECRET'); +``` + +### 3. Defina Tempos de Expiração Apropriados + +```php +// Boa prática: tokens de acesso de curta duração +'exp' => time() + (15 * 60) // 15 minutos + +// Para tokens de atualização: expiração mais longa +'exp' => time() + (7 * 24 * 60 * 60) // 7 dias +``` + +### 4. Use HTTPS em Produção + +JWTs devem **sempre** ser transmitidos via HTTPS. Nunca envie tokens via HTTP simples em produção! + +### 5. Valide Reivindicações do Token + +Sempre valide as reivindicações que você se importa: + +```php +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + +// Verificação de expiração é tratada automaticamente pela biblioteca +// Mas você pode adicionar validações personalizadas: +if ($decoded->iat > time()) { + throw new Exception('Token used before it was issued'); +} + +if (isset($decoded->nbf) && $decoded->nbf > time()) { + throw new Exception('Token not yet valid'); +} +``` + +### 6. Considere Blacklisting de Tokens para Logout + +Para segurança extra, mantenha uma lista negra de tokens invalidados: + +```php +Flight::route('POST /api/logout', function() { + $authHeader = Flight::request()->getHeader('Authorization'); + preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches); + $jwt = $matches[1]; + + // Extraia a expiração do token + $decoded = Flight::request()->data->user; + $ttl = $decoded->exp - time(); + + // Armazene no cache/redis até a expiração + Flight::cache()->set("blacklist:$jwt", true, $ttl); + + Flight::json(['message' => 'Successfully logged out']); +}); + +// Adicione ao seu JwtMiddleware: +public function before(array $params) { + // ... extraia JWT ... + + // Verifique a lista negra + if (Flight::cache()->get("blacklist:$jwt")) { + $this->app->jsonHalt(['error' => 'Token has been revoked'], 401); + } + + // ... verifique o token ... +} +``` + +## Algoritmos e Tipos de Chave + +Firebase JWT suporta múltiplos algoritmos: + +### Algoritmos Simétricos (HMAC) +- **HS256** (Recomendado para a maioria dos apps): Usa uma única chave secreta +- **HS384**, **HS512**: Variantes mais fortes + +```php +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Algoritmos Assimétricos (RSA/ECDSA) +- **RS256**, **RS384**, **RS512**: Usa pares de chaves pública/privada +- **ES256**, **ES384**, **ES512**: Variantes de curva elíptica + +```php +// Gere chaves: openssl genrsa -out private.key 2048 +// openssl rsa -in private.key -pubout -out public.key + +$privateKey = file_get_contents('/path/to/private.key'); +$publicKey = file_get_contents('/path/to/public.key'); + +// Codifique com chave privada +$jwt = JWT::encode($payload, $privateKey, 'RS256'); + +// Decodifique com chave pública +$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); +``` + +> **Quando usar RSA**: Use RSA quando precisar distribuir a chave pública para verificação (ex.: microsserviços, integrações de terceiros). Para uma única aplicação, HS256 é mais simples e suficiente. + +## Solução de Problemas + +### Erro "Token expirado" +A reivindicação `exp` do seu token está no passado. Emita um novo token ou implemente atualização de token. + +### "Falha na verificação de assinatura" +- Você está usando uma chave secreta diferente para decodificar do que usou para codificar +- O token foi adulterado +- Desvio de relógio entre servidores (adicione um buffer de leeway) + +```php +use Firebase\JWT\JWT; + +JWT::$leeway = 60; // Permita 60 segundos de desvio de relógio +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Token Não Enviado nas Requisições +Certifique-se de que seu cliente está enviando o header `Authorization`: + +```javascript +// Exemplo em JavaScript +fetch('/api/users', { + headers: { + 'Authorization': 'Bearer ' + token + } +}); +``` + +## Métodos + +A biblioteca Firebase JWT fornece estes métodos principais: + +- `JWT::encode(array $payload, string $key, string $alg)`: Cria um JWT a partir de um payload +- `JWT::decode(string $jwt, Key $key)`: Decodifica e verifica um JWT +- `JWT::urlsafeB64Encode(string $input)`: Codificação Base64 URL-safe +- `JWT::urlsafeB64Decode(string $input)`: Decodificação Base64 URL-safe +- `JWT::$leeway`: Propriedade estática para definir leeway de tempo para validação (em segundos) + +## Por que Usar Esta Biblioteca? + +- **Padrão da Indústria**: Firebase JWT é a biblioteca JWT mais popular e amplamente confiável para PHP +- **Manutenção Ativa**: Mantida pela equipe do Google/Firebase +- **Focada em Segurança**: Atualizações regulares e patches de segurança +- **API Simples**: Fácil de entender e implementar +- **Bem Documentada**: Documentação extensa e suporte da comunidade +- **Flexível**: Suporta múltiplos algoritmos e opções configuráveis + +## Veja Também + +- [Repositório Github do Firebase JWT](https://github.com/firebase/php-jwt) +- [JWT.io](https://jwt.io/) - Debug e decodificação de JWTs +- [RFC 7519](https://tools.ietf.org/html/rfc7519) - Especificação oficial de JWT +- [Documentação de Middleware do Flight](/learn/middleware) +- [Plugin de Sessão do Flight](/awesome-plugins/session) - Para autenticação baseada em sessões tradicionais + +## Licença + +A biblioteca Firebase JWT é licenciada sob a Licença BSD 3-Clause. Veja o [repositório no Github](https://github.com/firebase/php-jwt) para detalhes. \ No newline at end of file diff --git a/content/v3/ru/awesome-plugins/awesome_plugins.md b/content/v3/ru/awesome-plugins/awesome_plugins.md index 707230f6..7ab11e83 100644 --- a/content/v3/ru/awesome-plugins/awesome_plugins.md +++ b/content/v3/ru/awesome-plugins/awesome_plugins.md @@ -1,82 +1,88 @@ -# Крутой Плагины +# Крутой плагины -Flight невероятно расширяем. Существует множество плагинов, которые можно использовать для добавления функциональности в ваше приложение Flight. Некоторые официально поддерживаются командой Flight, а другие — это микробиблиотеки или лайт-библиотеки, чтобы помочь вам начать. +Flight невероятно расширяем. Существует множество плагинов, которые можно использовать для добавления функциональности в ваше приложение Flight. Некоторые из них официально поддерживаются командой Flight, а другие — это микро/лайт-библиотеки, чтобы помочь вам начать. ## Документация API Документация API крайне важна для любого API. Она помогает разработчикам понять, как взаимодействовать с вашим API и чего ожидать в ответ. Существует несколько инструментов, которые помогут вам генерировать документацию API для ваших проектов Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Блог-пост, написанный Daniel Schreiber, о том, как использовать спецификацию OpenAPI с FlightPHP для построения вашего API с использованием подхода API first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI — отличный инструмент для генерации документации API для ваших проектов Flight. Его очень легко использовать, и его можно настроить под ваши нужды. Это PHP-библиотека, которая поможет вам генерировать документацию Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Пост в блоге, написанный Даниэлем Шрайбером, о том, как использовать спецификацию OpenAPI с FlightPHP для создания вашего API с использованием подхода API first. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI — отличный инструмент, который поможет вам генерировать документацию API для ваших проектов Flight. Его очень легко использовать, и его можно настроить под ваши нужды. Это PHP-библиотека, которая поможет вам генерировать документацию Swagger. -## Мониторинг Производительности Приложений (APM) +## Мониторинг производительности приложений (APM) -Мониторинг производительности приложений (APM) крайне важен для любого приложения. Он помогает понять, как работает ваше приложение и где находятся узкие места. Существует множество инструментов APM, которые можно использовать с Flight. -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM — простая библиотека APM, которую можно использовать для мониторинга приложений Flight. Она может использоваться для мониторинга производительности вашего приложения и помощи в выявлении узких мест. +Мониторинг производительности приложений (APM) крайне важен для любого приложения. Он помогает вам понять, как работает ваше приложение и где находятся узкие места. Существует множество инструментов APM, которые можно использовать с Flight. +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM — это простая библиотека APM, которую можно использовать для мониторинга ваших приложений Flight. Её можно использовать для мониторинга производительности вашего приложения и помощи в выявлении узких мест. -## Async +## Асинхронность -Flight уже является быстрым фреймворком, но добавление к нему турбо-двигателя делает всё ещё более веселым (и challenging)! +Flight уже является быстрым фреймворком, но добавление к нему турбо-двигателя делает всё ещё веселее (и сложнее)! - [flightphp/async](/awesome-plugins/async) - Официальная библиотека Flight Async. Эта библиотека — простой способ добавить асинхронную обработку в ваше приложение. Она использует Swoole/Openswoole под капотом, чтобы предоставить простой и эффективный способ запуска задач асинхронно. ## Авторизация/Разрешения -Авторизация и разрешения крайне важны для любого приложения, которое требует контроля за тем, кто может получить доступ к чему. +Авторизация и разрешения крайне важны для любого приложения, которое требует контроля над тем, кто может получить доступ к чему. - official [flightphp/permissions](/awesome-plugins/permissions) - Официальная библиотека Flight Permissions. Эта библиотека — простой способ добавить разрешения на уровне пользователя и приложения в ваше приложение. +## Аутентификация + +Аутентификация необходима для приложений, которым нужно проверять идентичность пользователя и защищать конечные точки API. + +- [firebase/php-jwt](/awesome-plugins/jwt) - Библиотека JSON Web Token (JWT) для PHP. Простой и безопасный способ реализовать аутентификацию на основе токенов в ваших приложениях Flight. Идеально для бесстатусной аутентификации API, защиты маршрутов с помощью middleware и реализации потоков авторизации в стиле OAuth. + ## Кэширование Кэширование — отличный способ ускорить ваше приложение. Существует множество библиотек кэширования, которые можно использовать с Flight. -- official [flightphp/cache](/awesome-plugins/php-file-cache) - Легкий, простой и автономный класс PHP для кэширования в файле +- official [flightphp/cache](/awesome-plugins/php-file-cache) - Лёгкий, простой и автономный класс кэширования PHP в файле ## CLI -CLI-приложения — отличный способ взаимодействовать с вашим приложением. Вы можете использовать их для генерации контроллеров, отображения всех маршрутов и многого другого. +CLI-приложения — отличный способ взаимодействовать с вашим приложением. Их можно использовать для генерации контроллеров, отображения всех маршрутов и многого другого. -- official [flightphp/runway](/awesome-plugins/runway) - Runway — CLI-приложение, которое помогает управлять вашими приложениями Flight. +- official [flightphp/runway](/awesome-plugins/runway) - Runway — это CLI-приложение, которое помогает вам управлять вашими приложениями Flight. -## Cookies +## Куки -Cookies — отличный способ хранить небольшие объемы данных на стороне клиента. Их можно использовать для хранения предпочтений пользователя, настроек приложения и многого другого. +Куки — отличный способ хранить небольшие объёмы данных на стороне клиента. Их можно использовать для хранения предпочтений пользователя, настроек приложения и многого другого. -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie — PHP-библиотека, которая предоставляет простой и эффективный способ управления cookies. +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie — это PHP-библиотека, которая предоставляет простой и эффективный способ управления куки. ## Отладка -Отладка крайне важна при разработке в локальной среде. Существует несколько плагинов, которые могут улучшить ваш опыт отладки. +Отладка крайне важна, когда вы разрабатываете в локальной среде. Существует несколько плагинов, которые могут улучшить ваш опыт отладки. - [tracy/tracy](/awesome-plugins/tracy) - Это полнофункциональный обработчик ошибок, который можно использовать с Flight. У него есть несколько панелей, которые могут помочь вам отлаживать ваше приложение. Его также очень легко расширять и добавлять свои собственные панели. - official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Используется с обработчиком ошибок [Tracy](/awesome-plugins/tracy), этот плагин добавляет несколько дополнительных панелей для помощи в отладке специально для проектов Flight. -## Базы Данных +## Базы данных -Базы данных — основа большинства приложений. Это способ хранения и извлечения данных. Некоторые библиотеки баз данных — просто обертки для написания запросов, а некоторые — полноценные ORM. +Базы данных — основа большинства приложений. Это способ хранения и извлечения данных. Некоторые библиотеки баз данных — просто обёртки для написания запросов, а некоторые — полноценные ORM. -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Официальная обертка Flight PDO, которая является частью ядра. Это простая обертка, которая помогает упростить процесс написания запросов и их выполнения. Это не ORM. -- official [flightphp/active-record](/awesome-plugins/active-record) - Официальный ORM/Mapper Flight ActiveRecord. Отличная маленькая библиотека для легкого извлечения и хранения данных в вашей базе данных. -- [byjg/php-migration](/awesome-plugins/migrations) - Плагин для отслеживания всех изменений в базе данных для вашего проекта. +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Официальная обёртка Flight PDO, которая является частью ядра. Это простая обёртка, которая помогает упростить процесс написания запросов и их выполнения. Это не ORM. +- official [flightphp/active-record](/awesome-plugins/active-record) - Официальный ORM/Mapper Flight ActiveRecord. Отличная маленькая библиотека для лёгкого извлечения и хранения данных в вашей базе данных. +- [byjg/php-migration](/awesome-plugins/migrations) - Плагин для отслеживания всех изменений базы данных для вашего проекта. ## Шифрование Шифрование крайне важно для любого приложения, которое хранит конфиденциальные данные. Шифрование и дешифрование данных не так уж сложно, но правильное хранение ключа шифрования [может](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [быть](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [сложным](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Самое важное — никогда не хранить ключ шифрования в публичной директории или коммитить его в репозиторий кода. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Это библиотека, которую можно использовать для шифрования и дешифрования данных. Запуск и использование довольно просты для начала шифрования и дешифрования данных. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - Это библиотека, которую можно использовать для шифрования и дешифрования данных. Запуск и настройка довольно просты, чтобы начать шифровать и дешифровать данные. -## Очередь Задач +## Очередь заданий -Очереди задач очень полезны для асинхронной обработки задач. Это может быть отправка email, обработка изображений или что-то, что не требует выполнения в реальном времени. +Очереди заданий очень полезны для асинхронной обработки задач. Это может быть отправка email, обработка изображений или что угодно, что не требует выполнения в реальном времени. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue — библиотека, которую можно использовать для асинхронной обработки задач. Её можно использовать с beanstalkd, MySQL/MariaDB, SQLite и PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue — это библиотека, которую можно использовать для асинхронной обработки заданий. Её можно использовать с beanstalkd, MySQL/MariaDB, SQLite и PostgreSQL. ## Сессии -Сессии не очень полезны для API, но для построения веб-приложения сессии могут быть крайне важны для поддержания состояния и информации о входе. +Сессии не очень полезны для API, но для создания веб-приложения сессии могут быть крайне важны для поддержания состояния и информации о входе. - official [flightphp/session](/awesome-plugins/session) - Официальная библиотека Flight Session. Это простая библиотека сессий, которую можно использовать для хранения и извлечения данных сессии. Она использует встроенную обработку сессий PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - Менеджер сессий PHP (неблокирующий, flash, сегмент, шифрование сессии). Использует PHP open_ssl для опционального шифрования/дешифрования данных сессии. +- [Ghostff/Session](/awesome-plugins/ghost-session) - Менеджер сессий PHP (неблокирующий, flash, сегмент, шифрование сессий). Использует PHP open_ssl для опционального шифрования/дешифрования данных сессии. ## Шаблонизация @@ -84,13 +90,13 @@ Cookies — отличный способ хранить небольшие об - deprecated [flightphp/core View](/learn#views) - Это очень базовый шаблонизатор, который является частью ядра. Не рекомендуется использовать, если у вас больше нескольких страниц в проекте. - [latte/latte](/awesome-plugins/latte) - Latte — полнофункциональный шаблонизатор, который очень легко использовать и ближе к синтаксису PHP, чем Twig или Smarty. Его также очень легко расширять и добавлять свои собственные фильтры и функции. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate — мощный шаблонизатор PHP с компиляцией ассетов, наследованием шаблонов и обработкой переменных. Функции включают автоматическую минификацию CSS/JS, кэширование, кодирование Base64 и опциональную интеграцию с фреймворком Flight PHP. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate — мощный шаблонизатор PHP с компиляцией ассетов, наследованием шаблонов и обработкой переменных. Поддерживает автоматическую минификацию CSS/JS, кэширование, кодирование Base64 и опциональную интеграцию с фреймворком Flight PHP. ## Интеграция с WordPress Хотите использовать Flight в вашем проекте WordPress? Для этого есть удобный плагин! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Этот плагин WordPress позволяет запускать Flight прямо рядом с WordPress. Он идеален для добавления кастомных API, микросервисов или даже полноценных приложений на ваш сайт WordPress с использованием фреймворка Flight. Супер полезно, если вы хотите лучшее из двух миров! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Этот плагин WordPress позволяет запускать Flight прямо рядом с WordPress. Он идеален для добавления пользовательских API, микросервисов или даже полноценных приложений на ваш сайт WordPress с использованием фреймворка Flight. Супер полезно, если вы хотите лучшее из двух миров! ## Вклад diff --git a/content/v3/ru/awesome-plugins/jwt.md b/content/v3/ru/awesome-plugins/jwt.md new file mode 100644 index 00000000..09dc339c --- /dev/null +++ b/content/v3/ru/awesome-plugins/jwt.md @@ -0,0 +1,532 @@ +# Firebase JWT - Аутентификация с использованием JSON Web Token для Flight + +JWT (JSON Web Tokens) — это компактный, безопасный для URL способ представления утверждений между вашим приложением и клиентом. Они идеальны для аутентификации stateless API — без необходимости хранения сессий на сервере! Это руководство показывает, как интегрировать [Firebase JWT](https://github.com/firebase/php-jwt) с Flight для безопасной аутентификации на основе токенов. + +Посетите [репозиторий на Github](https://github.com/firebase/php-jwt) для полной документации и деталей. + +## Что такое JWT? + +JSON Web Token — это строка, содержащая три части: +1. **Заголовок**: Метаданные о токене (алгоритм, тип) +2. **Полезная нагрузка**: Ваши данные (ID пользователя, роли, срок действия и т.д.) +3. **Подпись**: Криптографическая подпись для проверки подлинности + +Пример JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (выглядит как бессмысленный набор символов, но это структурированные данные!) + +### Почему использовать JWT? + +- **Stateless**: Не требуется хранение сессий на сервере — идеально для микросервисов и API +- **Масштабируемость**: Хорошо работает с балансировщиками нагрузки, поскольку нет требования к affinity сессий +- **Кросс-доменная совместимость**: Может использоваться в разных доменах и сервисах +- **Дружественно к мобильным устройствам**: Отлично подходит для мобильных приложений, где куки могут работать не так хорошо +- **Стандартизировано**: Стандарт отрасли (RFC 7519) + +## Установка + +Установите через Composer: + +```bash +composer require firebase/php-jwt +``` + +## Основное использование + +Вот быстрый пример создания и проверки JWT: + +```php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; + +// Ваш секретный ключ (ХРАНИТЕ ЕГО В БЕЗОПАСНОСТИ!) +$secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; + +// Создание токена +$payload = [ + 'user_id' => 123, + 'username' => 'johndoe', + 'role' => 'admin', + 'iat' => time(), // Выдан в + 'exp' => time() + 3600 // Истекает через 1 час +]; + +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +echo "Token: " . $jwt; + +// Проверка и декодирование токена +try { + $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + echo "User ID: " . $decoded->user_id; +} catch (Exception $e) { + echo "Invalid token: " . $e->getMessage(); +} +``` + +## Middleware JWT для Flight (Рекомендуемый подход) + +Наиболее распространенный и полезный способ использования JWT с Flight — это как **middleware** для защиты маршрутов API. Вот полный, готовый для производства пример: + +### Шаг 1: Создание класса JWT Middleware + +```php +// app/middleware/JwtMiddleware.php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; +use Firebase\JWT\ExpiredException; +use Firebase\JWT\SignatureInvalidException; +use flight\Engine; + +class JwtMiddleware { + + protected Engine $app; + protected string $secretKey; + + public function __construct(Engine $app) { + $this->app = $app; + // Храните ваш секретный ключ в app/config/config.php, НЕ жёстко закодированным! + $this->secretKey = $app->get('config')['jwt_secret']; + } + + public function before(array $params) { + $authHeader = $this->app->request()->getHeader('Authorization'); + + // Проверка наличия заголовка Authorization + if (empty($authHeader)) { + $this->app->jsonHalt(['error' => 'No authorization token provided'], 401); + } + + // Извлечение токена из формата "Bearer " + if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { + $this->app->jsonHalt(['error' => 'Invalid authorization format. Use: Bearer '], 401); + } + + $jwt = $matches[1]; + + try { + // Декодирование и проверка токена + $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); + + // Сохранение данных пользователя в запросе для использования в обработчиках маршрутов + $this->app->request()->data->user = $decoded; + + } catch (ExpiredException $e) { + $this->app->jsonHalt(['error' => 'Token has expired'], 401); + } catch (SignatureInvalidException $e) { + $this->app->jsonHalt(['error' => 'Invalid token signature'], 401); + } catch (Exception $e) { + $this->app->jsonHalt(['error' => 'Invalid token: ' . $e->getMessage()], 401); + } + } +} +``` + +### Шаг 2: Регистрация JWT Secret в вашем конфиге + +```php +// app/config/config.php +return [ + 'jwt_secret' => getenv('JWT_SECRET') ?: 'your-fallback-secret-for-development' +]; + +// app/config/bootstrap.php или index.php +// убедитесь, что добавили эту строку, если хотите сделать конфиг доступным для приложения +$app->set('config', $config); +``` + +> **Примечание по безопасности**: Никогда не жёстко кодируйте ваш секретный ключ! Используйте переменные окружения в производстве. + +### Шаг 3: Защита ваших маршрутов с помощью Middleware + +```php +// Защита одного маршрута +Flight::route('GET /api/user/profile', function() { + $user = Flight::request()->data->user; // Установлено middleware + Flight::json([ + 'user_id' => $user->user_id, + 'username' => $user->username, + 'role' => $user->role + ]); +})->addMiddleware( JwtMiddleware::class); + +// Защита всей группы маршрутов (более распространено!) +Flight::group('/api', function() { + Flight::route('GET /users', function() { /* ... */ }); + Flight::route('GET /posts', function() { /* ... */ }); + Flight::route('POST /posts', function() { /* ... */ }); + Flight::route('DELETE /posts/@id', function($id) { /* ... */ }); +}, [ JwtMiddleware::class ]); // Все маршруты в этой группе защищены! +``` + +Для получения дополнительной информации о middleware см. [документацию по middleware](/learn/middleware). + +## Распространенные сценарии использования + +### 1. Эндпоинт входа (Генерация токена) + +Создайте маршрут, который генерирует JWT после успешной аутентификации: + +```php +Flight::route('POST /api/login', function() { + $data = Flight::request()->data; + $username = $data->username ?? ''; + $password = $data->password ?? ''; + + // Проверка учетных данных (пример — используйте свою логику!) + $user = validateUserCredentials($username, $password); + + if (!$user) { + Flight::jsonHalt(['error' => 'Invalid credentials'], 401); + } + + // Генерация JWT + $secretKey = Flight::get('config')['jwt_secret']; + $payload = [ + 'user_id' => $user->id, + 'username' => $user->username, + 'role' => $user->role, + 'iat' => time(), + 'exp' => time() + (60 * 60) // Истекает через 1 час + ]; + + $jwt = JWT::encode($payload, $secretKey, 'HS256'); + + Flight::json([ + 'success' => true, + 'token' => $jwt, + 'expires_in' => 3600 + ]); +}); + +function validateUserCredentials($username, $password) { + // Здесь ваш поиск в базе данных и проверка пароля + // Пример: + $db = Flight::db(); + $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); + + if ($user && password_verify($password, $user['password_hash'])) { + return (object) [ + 'id' => $user['id'], + 'username' => $user['username'], + 'role' => $user['role'] + ]; + } + return null; +} +``` + +### 2. Поток обновления токена + +Реализуйте систему обновления токена для долгоживущих сессий: + +```php +Flight::route('POST /api/login', function() { + // ... проверка учетных данных ... + + $secretKey = Flight::get('config')['jwt_secret']; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + // Короткоживущий access token (15 минут) + $accessToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + // Долгоживущий refresh token (7 дней) + $refreshToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'refresh', + 'iat' => time(), + 'exp' => time() + (7 * 24 * 60 * 60) + ], $refreshSecret, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'refresh_token' => $refreshToken, + 'expires_in' => 900 + ]); +}); + +Flight::route('POST /api/refresh', function() { + $refreshToken = Flight::request()->data->refresh_token ?? ''; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + try { + $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); + + // Проверка, что это refresh token + if ($decoded->type !== 'refresh') { + Flight::jsonHalt(['error' => 'Invalid token type'], 401); + } + + // Генерация нового access token + $secretKey = Flight::get('config')['jwt_secret']; + $accessToken = JWT::encode([ + 'user_id' => $decoded->user_id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'expires_in' => 900 + ]); + + } catch (Exception $e) { + Flight::jsonHalt(['error' => 'Invalid refresh token'], 401); + } +}); +``` + +### 3. Контроль доступа на основе ролей + +Расширьте ваш middleware для проверки ролей пользователя: + +```php +class JwtRoleMiddleware { + + protected Engine $app; + protected array $allowedRoles; + + public function __construct(Engine $app, array $allowedRoles = []) { + $this->app = $app; + $this->allowedRoles = $allowedRoles; + } + + public function before(array $params) { + // Предполагаем, что JwtMiddleware уже выполнился и установил данные пользователя + $user = $this->app->request()->data->user ?? null; + + if (!$user) { + $this->app->jsonHalt(['error' => 'Authentication required'], 401); + } + + // Проверка наличия требуемой роли у пользователя + if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { + $this->app->jsonHalt(['error' => 'Insufficient permissions'], 403); + } + } +} + +// Использование: маршрут только для админов +Flight::route('DELETE /api/users/@id', function($id) { + // Логика удаления пользователя +})->addMiddleware([ + JwtMiddleware::class, + new JwtRoleMiddleware(Flight::app(), ['admin']) +]); +``` + +### 4. Публичное API с ограничением скорости по пользователям + +Используйте JWT для отслеживания и ограничения скорости пользователей без сессий: + +```php +class RateLimitMiddleware { + + public function before(array $params) { + $user = Flight::request()->data->user ?? null; + $userId = $user ? $user->user_id : Flight::request()->ip; + + $cacheKey = "rate_limit:$userId"; + // Убедитесь, что вы настроили сервис кэша в app/config/services.php + $requests = Flight::cache()->get($cacheKey, 0); + + if ($requests >= 100) { // 100 запросов в час + Flight::jsonHalt(['error' => 'Rate limit exceeded'], 429); + } + + Flight::cache()->set($cacheKey, $requests + 1, 3600); + } +} +``` + +## Лучшие практики безопасности + +### 1. Используйте сильные секретные ключи + +```php +// Генерация безопасного секретного ключа (запустите один раз, сохраните в файл .env) +$secretKey = base64_encode(random_bytes(32)); +echo $secretKey; // Сохраните это в вашем файле .env! +``` + +### 2. Храните секреты в переменных окружения + +```php +// Никогда не коммитьте секреты в систему контроля версий! +// Используйте файл .env и библиотеку вроде vlucas/phpdotenv + +// Файл .env: +// JWT_SECRET=your-base64-encoded-secret-here +// JWT_REFRESH_SECRET=another-base64-encoded-secret-here + +// Вы также можете использовать файл app/config/config.php для хранения секретов +// просто убедитесь, что файл конфигурации не коммитится в систему контроля версий +// return [ +// 'jwt_secret' => 'your-base64-encoded-secret-here', +// 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', +// ]; + +// В вашем приложении: +$secretKey = getenv('JWT_SECRET'); +``` + +### 3. Устанавливайте подходящие сроки действия + +```php +// Хорошая практика: короткоживущие access tokens +'exp' => time() + (15 * 60) // 15 минут + +// Для refresh tokens: более длинный срок действия +'exp' => time() + (7 * 24 * 60 * 60) // 7 дней +``` + +### 4. Используйте HTTPS в производстве + +JWT должны **всегда** передаваться по HTTPS. Никогда не отправляйте токены по обычному HTTP в производстве! + +### 5. Проверяйте утверждения токена + +Всегда проверяйте утверждения, которые вас интересуют: + +```php +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + +// Проверка истечения срока действия обрабатывается библиотекой автоматически +// Но вы можете добавить пользовательские проверки: +if ($decoded->iat > time()) { + throw new Exception('Token used before it was issued'); +} + +if (isset($decoded->nbf) && $decoded->nbf > time()) { + throw new Exception('Token not yet valid'); +} +``` + +### 6. Рассмотрите черный список токенов для выхода + +Для дополнительной безопасности поддерживайте черный список недействительных токенов: + +```php +Flight::route('POST /api/logout', function() { + $authHeader = Flight::request()->getHeader('Authorization'); + preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches); + $jwt = $matches[1]; + + // Извлечение срока действия токена + $decoded = Flight::request()->data->user; + $ttl = $decoded->exp - time(); + + // Сохранение в кэше/redis до истечения срока действия + Flight::cache()->set("blacklist:$jwt", true, $ttl); + + Flight::json(['message' => 'Successfully logged out']); +}); + +// Добавьте в ваш JwtMiddleware: +public function before(array $params) { + // ... извлечение JWT ... + + // Проверка черного списка + if (Flight::cache()->get("blacklist:$jwt")) { + $this->app->jsonHalt(['error' => 'Token has been revoked'], 401); + } + + // ... проверка токена ... +} +``` + +## Алгоритмы и типы ключей + +Firebase JWT поддерживает несколько алгоритмов: + +### Симметричные алгоритмы (HMAC) +- **HS256** (Рекомендуется для большинства приложений): Использует один секретный ключ +- **HS384**, **HS512**: Более сильные варианты + +```php +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Асимметричные алгоритмы (RSA/ECDSA) +- **RS256**, **RS384**, **RS512**: Использует пары публичный/приватный ключ +- **ES256**, **ES384**, **ES512**: Варианты на основе эллиптических кривых + +```php +// Генерация ключей: openssl genrsa -out private.key 2048 +// openssl rsa -in private.key -pubout -out public.key + +$privateKey = file_get_contents('/path/to/private.key'); +$publicKey = file_get_contents('/path/to/public.key'); + +// Кодирование с приватным ключом +$jwt = JWT::encode($payload, $privateKey, 'RS256'); + +// Декодирование с публичным ключом +$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); +``` + +> **Когда использовать RSA**: Используйте RSA, когда нужно распространить публичный ключ для проверки (например, микросервисы, интеграции с третьими сторонами). Для одного приложения HS256 проще и достаточно. + +## Устранение неисправностей + +### Ошибка "Expired token" +Утверждение `exp` вашего токена в прошлом. Выдайте новый токен или реализуйте обновление токена. + +### "Signature verification failed" +- Вы используете другой секретный ключ для декодирования, чем для кодирования +- Токен был изменен +- Расхождение во времени между серверами (добавьте буфер leeway) + +```php +use Firebase\JWT\JWT; + +JWT::$leeway = 60; // Разрешить 60 секунд расхождения во времени +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Токен не отправляется в запросах +Убедитесь, что ваш клиент отправляет заголовок `Authorization`: + +```javascript +// Пример на JavaScript +fetch('/api/users', { + headers: { + 'Authorization': 'Bearer ' + token + } +}); +``` + +## Методы + +Библиотека Firebase JWT предоставляет эти основные методы: + +- `JWT::encode(array $payload, string $key, string $alg)`: Создает JWT из полезной нагрузки +- `JWT::decode(string $jwt, Key $key)`: Декодирует и проверяет JWT +- `JWT::urlsafeB64Encode(string $input)`: Base64-кодирование, безопасное для URL +- `JWT::urlsafeB64Decode(string $input)`: Base64-декодирование, безопасное для URL +- `JWT::$leeway`: Статическое свойство для установки временного leeway для валидации (в секундах) + +## Почему использовать эту библиотеку? + +- **Стандарт отрасли**: Firebase JWT — самая популярная и широко доверенная библиотека JWT для PHP +- **Активное обслуживание**: Поддерживается командой Google/Firebase +- **Фокус на безопасности**: Регулярные обновления и патчи безопасности +- **Простой API**: Легко понять и реализовать +- **Хорошо задокументировано**: Обширная документация и поддержка сообщества +- **Гибкость**: Поддерживает несколько алгоритмов и настраиваемые опции + +## См. также + +- [Репозиторий Firebase JWT на Github](https://github.com/firebase/php-jwt) +- [JWT.io](https://jwt.io/) - Отладка и декодирование JWT +- [RFC 7519](https://tools.ietf.org/html/rfc7519) - Официальная спецификация JWT +- [Документация по Middleware Flight](/learn/middleware) +- [Плагин сессий Flight](/awesome-plugins/session) - Для традиционной аутентификации на основе сессий + +## Лицензия + +Библиотека Firebase JWT лицензирована по лицензии BSD 3-Clause. См. [репозиторий на Github](https://github.com/firebase/php-jwt) для деталей. \ No newline at end of file diff --git a/content/v3/uk/awesome-plugins/awesome_plugins.md b/content/v3/uk/awesome-plugins/awesome_plugins.md index 1343b185..4897ce0c 100644 --- a/content/v3/uk/awesome-plugins/awesome_plugins.md +++ b/content/v3/uk/awesome-plugins/awesome_plugins.md @@ -4,93 +4,99 @@ Flight є надзвичайно розширюваним. Існує низка ## Документація API -Документація API є критичною для будь-якого API. Вона допомагає розробникам зрозуміти, як взаємодіяти з вашим API та що очікувати у відповідь. Існує кілька інструментів, доступних для генерації документації API для ваших проєктів Flight. +Документація API є критичною для будь-якого API. Вона допомагає розробникам зрозуміти, як взаємодіяти з вашим API та що очікувати натомість. Існує кілька інструментів, доступних для допомоги у генерації документації API для ваших проєктів Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Блог-пост, написаний Даніелем Шрайбером, про те, як використовувати специфікацію OpenAPI з FlightPHP для побудови вашого API з підходом API first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI є чудовим інструментом для генерації документації API для ваших проєктів Flight. Його дуже легко використовувати, і його можна налаштувати відповідно до ваших потреб. Це PHP-бібліотека для генерації документації Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Блог-пост, написаний Даніелем Шрайбером, про те, як використовувати специфікацію OpenAPI з FlightPHP для побудови вашого API з використанням підходу API first. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI є чудовим інструментом для допомоги у генерації документації API для ваших проєктів Flight. Його дуже легко використовувати, і його можна налаштувати відповідно до ваших потреб. Це PHP-бібліотека для допомоги у генерації документації Swagger. -## Моніторинг Продуктивності Додатків (APM) +## Моніторинг Продуктивності Застосунків (APM) -Моніторинг продуктивності додатків (APM) є критичним для будь-якого додатка. Він допомагає вам зрозуміти, як працює ваш додаток, і де знаходяться вузькі місця. Існує низка інструментів APM, які можна використовувати з Flight. -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM є простою бібліотекою APM, яка може використовуватися для моніторингу ваших додатків Flight. Її можна використовувати для моніторингу продуктивності вашого додатка та допомоги в ідентифікації вузьких місць. +Моніторинг продуктивності застосунків (APM) є критичним для будь-якої програми. Він допомагає вам зрозуміти, як працює ваша програма та де є вузькі місця. Існує низка інструментів APM, які можна використовувати з Flight. +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM є простою бібліотекою APM, яка може бути використана для моніторингу ваших програм Flight. Її можна використовувати для моніторингу продуктивності вашої програми та допомоги у виявленні вузьких місць. ## Асинхронність -Flight вже є швидким фреймворком, але додавання до нього турбо-двигуна робить все ще веселішим (і складнішим)! +Flight вже є швидким фреймворком, але додавання до нього турбо-двигуна робить все більш веселим (і складним)! -- [flightphp/async](/awesome-plugins/async) - Офіційна бібліотека Flight Async. Ця бібліотека є простим способом додати асинхронну обробку до вашого додатка. Вона використовує Swoole/Openswoole під капотом для надання простого та ефективного способу запуску завдань асинхронно. +- [flightphp/async](/awesome-plugins/async) - Офіційна бібліотека Flight Async. Ця бібліотека є простим способом додати асинхронну обробку до вашої програми. Вона використовує Swoole/Openswoole під капотом, щоб надати простий та ефективний спосіб запуску завдань асинхронно. ## Авторизація/Дозволи -Авторизація та дозволи є критичними для будь-якого додатка, який вимагає контролю за тим, хто може отримати доступ до чого. +Авторизація та дозволи є критичними для будь-якої програми, яка вимагає контролю за тим, хто може отримати доступ до чого. -- official [flightphp/permissions](/awesome-plugins/permissions) - Офіційна бібліотека Flight Permissions. Ця бібліотека є простим способом додати дозволи на рівні користувача та додатка до вашого додатка. +- official [flightphp/permissions](/awesome-plugins/permissions) - Офіційна бібліотека Flight Permissions. Ця бібліотека є простим способом додати дозволи на рівні користувача та програми до вашої програми. + +## Аутентифікація + +Аутентифікація є суттєвою для програм, які потребують перевірки ідентичності користувача та захисту кінцевих точок API. + +- [firebase/php-jwt](/awesome-plugins/jwt) - Бібліотека JSON Web Token (JWT) для PHP. Простий та безпечний спосіб реалізувати аутентифікацію на основі токенів у ваших програмах Flight. Ідеально для безстанної аутентифікації API, захисту маршрутів з middleware та реалізації потоків авторизації в стилі OAuth. ## Кешування -Кешування є чудовим способом прискорити ваш додаток. Існує низка бібліотек кешування, які можна використовувати з Flight. +Кешування є чудовим способом прискорити вашу програму. Існує низка бібліотек кешування, які можна використовувати з Flight. -- official [flightphp/cache](/awesome-plugins/php-file-cache) - Легка, проста та автономна PHP-клас для кешування в файлі +- official [flightphp/cache](/awesome-plugins/php-file-cache) - Легка, проста та автономна PHP-клас кешування в файлі ## CLI -CLI-додатки є чудовим способом взаємодіяти з вашим додатком. Ви можете використовувати їх для генерації контролерів, відображення всіх маршрутів та інше. +CLI-програми є чудовим способом взаємодіяти з вашою програмою. Ви можете використовувати їх для генерації контролерів, відображення всіх маршрутів та багато іншого. -- official [flightphp/runway](/awesome-plugins/runway) - Runway є CLI-додатком, який допомагає вам керувати вашими додатками Flight. +- official [flightphp/runway](/awesome-plugins/runway) - Runway є CLI-програмою, яка допомагає вам керувати вашими програмами Flight. -## Куки +## Кукі -Куки є чудовим способом зберігати невеликі обсяги даних на стороні клієнта. Їх можна використовувати для зберігання уподобань користувача, налаштувань додатка та інше. +Кукі є чудовим способом зберігати малі фрагменти даних на стороні клієнта. Їх можна використовувати для зберігання уподобань користувача, налаштувань програми та багато іншого. -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie є PHP-бібліотекою, яка надає простий та ефективний спосіб керування куками. +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie є PHP-бібліотекою, яка надає простий та ефективний спосіб керування кукі. ## Налагодження Налагодження є критичним, коли ви розробляєте у локальному середовищі. Існує кілька плагінів, які можуть покращити ваш досвід налагодження. -- [tracy/tracy](/awesome-plugins/tracy) - Це повнофункціональний обробник помилок, який можна використовувати з Flight. Він має низку панелей, які можуть допомогти вам налагоджувати ваш додаток. Його також дуже легко розширювати та додавати власні панелі. -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Використовується з обробником помилок [Tracy](/awesome-plugins/tracy), цей плагін додає кілька додаткових панелей для допомоги в налагодженні спеціально для проєктів Flight. +- [tracy/tracy](/awesome-plugins/tracy) - Це повнофункціональний обробник помилок, який можна використовувати з Flight. Він має низку панелей, які можуть допомогти вам налагоджувати вашу програму. Його також дуже легко розширювати та додавати власні панелі. +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Використовується з обробником помилок [Tracy](/awesome-plugins/tracy), цей плагін додає кілька додаткових панелей для допомоги з налагодженням спеціально для проєктів Flight. ## Бази Даних -Бази даних є основою для більшості додатків. Це спосіб зберігати та отримувати дані. Деякі бібліотеки баз даних є просто обгортками для написання запитів, а деякі є повноцінними ORM. +Бази даних є основою для більшості програм. Це спосіб зберігати та отримувати дані. Деякі бібліотеки баз даних є просто обгортками для написання запитів, а деякі є повноцінними ORM. -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Офіційний обгорт Flight PDO Wrapper, який є частиною ядра. Це проста обгортка для спрощення процесу написання запитів та їх виконання. Це не ORM. -- official [flightphp/active-record](/awesome-plugins/active-record) - Офіційний ORM/Mapper Flight ActiveRecord. Чудова маленька бібліотека для легкого отримання та зберігання даних у вашій базі даних. +- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Офіційна обгортка Flight PDO, яка є частиною ядра. Це проста обгортка для спрощення процесу написання запитів та їх виконання. Це не ORM. +- official [flightphp/active-record](/awesome-plugins/active-record) - Офіційна ORM/Mapper Flight ActiveRecord. Чудова маленька бібліотека для легкого отримання та зберігання даних у вашій базі даних. - [byjg/php-migration](/awesome-plugins/migrations) - Плагін для відстеження всіх змін бази даних для вашого проєкту. ## Шифрування -Шифрування є критичним для будь-якого додатка, який зберігає чутливі дані. Шифрування та дешифрування даних не є надто складним, але правильне зберігання ключа шифрування [може](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [бути](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [складним](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Найважливіше — ніколи не зберігати ключ шифрування в публічній директорії або комітити його до вашого репозиторію коду. +Шифрування є критичним для будь-якої програми, яка зберігає чутливі дані. Шифрування та дешифрування даних не є надто складним, але правильне зберігання ключа шифрування [може](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [бути](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [складним](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Найважливіше — ніколи не зберігати ключ шифрування в публічній директорії або комітити його до вашого репозиторію коду. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Це бібліотека, яка може використовуватися для шифрування та дешифрування даних. Запуск та налагодження є досить простим для початку шифрування та дешифрування даних. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - Це бібліотека, яка може бути використана для шифрування та дешифрування даних. Запуск та налаштування є досить простим для початку шифрування та дешифрування даних. ## Черга Завдань -Черги завдань дійсно корисні для асинхронної обробки завдань. Це може бути відправка електронних листів, обробка зображень або будь-що, що не потребує виконання в реальному часі. +Черги завдань є дуже корисними для асинхронної обробки завдань. Це може бути надсилання email, обробка зображень або будь-що, що не потребує реального часу. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue є бібліотекою, яка може використовуватися для асинхронної обробки завдань. Її можна використовувати з beanstalkd, MySQL/MariaDB, SQLite та PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue є бібліотекою, яка може бути використана для асинхронної обробки завдань. Її можна використовувати з beanstalkd, MySQL/MariaDB, SQLite та PostgreSQL. ## Сесії -Сесії не дуже корисні для API, але для побудови веб-додатка сесії можуть бути критичними для підтримки стану та інформації про вхід. +Сесії не є особливо корисними для API, але для побудови веб-програми сесії можуть бути критичними для підтримки стану та інформації про вхід. -- official [flightphp/session](/awesome-plugins/session) - Офіційна бібліотека Flight Session. Це проста бібліотека сесій, яка може використовуватися для зберігання та отримання даних сесії. Вона використовує вбудоване керування сесіями PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (неблокуючий, flash, сегмент, шифрування сесій). Використовує PHP open_ssl для опціонального шифрування/дешифрування даних сесії. +- official [flightphp/session](/awesome-plugins/session) - Офіційна бібліотека Flight Session. Це проста бібліотека сесій, яка може бути використана для зберігання та отримання даних сесії. Вона використовує вбудоване керування сесіями PHP. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (неблокуючий, flash, сегмент, шифрування сесії). Використовує PHP open_ssl для опціонального шифрування/дешифрування даних сесії. ## Шаблонізація -Шаблонізація є основою для будь-якого веб-додатка з UI. Існує низка рушіїв шаблонізації, які можна використовувати з Flight. +Шаблонізація є основою для будь-якої веб-програми з UI. Існує низка рушіїв шаблонізації, які можна використовувати з Flight. - deprecated [flightphp/core View](/learn#views) - Це дуже базовий рушій шаблонізації, який є частиною ядра. Не рекомендується використовувати, якщо у вашому проєкті більше кількох сторінок. - [latte/latte](/awesome-plugins/latte) - Latte є повнофункціональним рушієм шаблонізації, який дуже легко використовувати та відчувається ближчим до синтаксису PHP, ніж Twig чи Smarty. Його також дуже легко розширювати та додавати власні фільтри та функції. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate є потужним PHP-рушієм шаблонів з компіляцією активів, успадкуванням шаблонів та обробкою змінних. Підтримує автоматичне мініфікацію CSS/JS, кешування, кодування Base64 та опціональну інтеграцію з фреймворком Flight PHP. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate є потужним PHP-рушієм шаблонів з компіляцією активів, успадкуванням шаблонів та обробкою змінних. Має автоматичне мініфікацію CSS/JS, кешування, кодування Base64 та опціональну інтеграцію з фреймворком Flight PHP. ## Інтеграція з WordPress Хочете використовувати Flight у вашому проєкті WordPress? Є зручний плагін для цього! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Цей плагін WordPress дозволяє запускати Flight поруч з WordPress. Він ідеальний для додавання кастомних API, мікросервісів або навіть повних додатків до вашого сайту WordPress з використанням фреймворку Flight. Надзвичайно корисний, якщо ви хочете найкраще з обох світів! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Цей плагін WordPress дозволяє запускати Flight поруч з WordPress. Він ідеальний для додавання кастомних API, мікросервісів або навіть повноцінних програм до вашого сайту WordPress з використанням фреймворку Flight. Надзвичайно корисний, якщо ви хочете найкраще з обох світів! ## Внесок diff --git a/content/v3/uk/awesome-plugins/jwt.md b/content/v3/uk/awesome-plugins/jwt.md new file mode 100644 index 00000000..fdcd4dc1 --- /dev/null +++ b/content/v3/uk/awesome-plugins/jwt.md @@ -0,0 +1,532 @@ +# Firebase JWT - Аутентифікація JSON Web Token для Flight + +JWT (JSON Web Tokens) — це компактний, безпечний для URL спосіб представлення тверджень між вашим додатком і клієнтом. Вони ідеальні для безстанційної аутентифікації API — немає потреби в зберіганні сесій на сервері! Цей посібник показує, як інтегрувати [Firebase JWT](https://github.com/firebase/php-jwt) з Flight для безпечної аутентифікації на основі токенів. + +Відвідайте [репозиторій на Github](https://github.com/firebase/php-jwt) для повної документації та деталей. + +## Що таке JWT? + +JSON Web Token — це рядок, що містить три частини: +1. **Заголовок**: Метадані про токен (алгоритм, тип) +2. **Навантаження**: Ваші дані (ID користувача, ролі, термін дії тощо) +3. **Підпис**: Криптографічний підпис для перевірки автентичності + +Приклад JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (виглядає як нісенітниця, але це структуровані дані!) + +### Чому використовувати JWT? + +- **Безстанційний**: Не потрібно зберігати сесії на сервері — ідеально для мікросервісів і API +- **Масштабованість**: Добре працює з балансувальниками навантаження, оскільки немає вимоги до афінності сесій +- **Крос-доменний**: Можна використовувати між різними доменами та сервісами +- **Дружній до мобільних**: Чудово для мобільних додатків, де куки можуть не працювати добре +- **Стандартизований**: Стандарт галузі (RFC 7519) + +## Встановлення + +Встановіть через Composer: + +```bash +composer require firebase/php-jwt +``` + +## Основне використання + +Ось швидкий приклад створення та перевірки JWT: + +```php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; + +// Ваш секретний ключ (ЗБЕРІГАЙТЕ ЦЕ БЕЗПЕЧНО!) +$secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; + +// Створення токена +$payload = [ + 'user_id' => 123, + 'username' => 'johndoe', + 'role' => 'admin', + 'iat' => time(), // Виданий о + 'exp' => time() + 3600 // Термін дії 1 година +]; + +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +echo "Token: " . $jwt; + +// Перевірка та декодування токена +try { + $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + echo "User ID: " . $decoded->user_id; +} catch (Exception $e) { + echo "Invalid token: " . $e->getMessage(); +} +``` + +## Middleware JWT для Flight (Рекомендований підхід) + +Найпоширеніший і корисний спосіб використання JWT з Flight — як **middleware** для захисту маршрутів API. Ось повний, готовий до виробництва приклад: + +### Крок 1: Створення класу JWT Middleware + +```php +// app/middleware/JwtMiddleware.php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; +use Firebase\JWT\ExpiredException; +use Firebase\JWT\SignatureInvalidException; +use flight\Engine; + +class JwtMiddleware { + + protected Engine $app; + protected string $secretKey; + + public function __construct(Engine $app) { + $this->app = $app; + // Зберігайте свій секретний ключ у app/config/config.php, НЕ жорстко закодований! + $this->secretKey = $app->get('config')['jwt_secret']; + } + + public function before(array $params) { + $authHeader = $this->app->request()->getHeader('Authorization'); + + // Перевірка існування заголовка Authorization + if (empty($authHeader)) { + $this->app->jsonHalt(['error' => 'No authorization token provided'], 401); + } + + // Витягнення токена з формату "Bearer " + if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { + $this->app->jsonHalt(['error' => 'Invalid authorization format. Use: Bearer '], 401); + } + + $jwt = $matches[1]; + + try { + // Декодування та перевірка токена + $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); + + // Збереження даних користувача в запиті для використання в обробниках маршрутів + $this->app->request()->data->user = $decoded; + + } catch (ExpiredException $e) { + $this->app->jsonHalt(['error' => 'Token has expired'], 401); + } catch (SignatureInvalidException $e) { + $this->app->jsonHalt(['error' => 'Invalid token signature'], 401); + } catch (Exception $e) { + $this->app->jsonHalt(['error' => 'Invalid token: ' . $e->getMessage()], 401); + } + } +} +``` + +### Крок 2: Реєстрація JWT Secret у вашій конфігурації + +```php +// app/config/config.php +return [ + 'jwt_secret' => getenv('JWT_SECRET') ?: 'your-fallback-secret-for-development' +]; + +// app/config/bootstrap.php або index.php +// переконайтеся, що додали цей рядок, якщо хочете надати доступ до конфігурації додатку +$app->set('config', $config); +``` + +> **Примітка щодо безпеки**: Ніколи не жорстко кодуйте свій секретний ключ! Використовуйте змінні середовища в продакшені. + +### Крок 3: Захист ваших маршрутів за допомогою Middleware + +```php +// Захист одного маршруту +Flight::route('GET /api/user/profile', function() { + $user = Flight::request()->data->user; // Встановлено middleware + Flight::json([ + 'user_id' => $user->user_id, + 'username' => $user->username, + 'role' => $user->role + ]); +})->addMiddleware( JwtMiddleware::class); + +// Захист цілої групи маршрутів (поширеніше!) +Flight::group('/api', function() { + Flight::route('GET /users', function() { /* ... */ }); + Flight::route('GET /posts', function() { /* ... */ }); + Flight::route('POST /posts', function() { /* ... */ }); + Flight::route('DELETE /posts/@id', function($id) { /* ... */ }); +}, [ JwtMiddleware::class ]); // Усі маршрути в цій групі захищені! +``` + +Для отримання детальнішої інформації про middleware дивіться [документацію middleware](/learn/middleware). + +## Поширені випадки використання + +### 1. Endpoint входу (Генерація токена) + +Створіть маршрут, який генерує JWT після успішної аутентифікації: + +```php +Flight::route('POST /api/login', function() { + $data = Flight::request()->data; + $username = $data->username ?? ''; + $password = $data->password ?? ''; + + // Перевірка облікових даних (приклад — використовуйте свою логіку!) + $user = validateUserCredentials($username, $password); + + if (!$user) { + Flight::jsonHalt(['error' => 'Invalid credentials'], 401); + } + + // Генерація JWT + $secretKey = Flight::get('config')['jwt_secret']; + $payload = [ + 'user_id' => $user->id, + 'username' => $user->username, + 'role' => $user->role, + 'iat' => time(), + 'exp' => time() + (60 * 60) // Термін дії 1 година + ]; + + $jwt = JWT::encode($payload, $secretKey, 'HS256'); + + Flight::json([ + 'success' => true, + 'token' => $jwt, + 'expires_in' => 3600 + ]); +}); + +function validateUserCredentials($username, $password) { + // Ваш пошук у базі даних та перевірка пароля тут + // Приклад: + $db = Flight::db(); + $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); + + if ($user && password_verify($password, $user['password_hash'])) { + return (object) [ + 'id' => $user['id'], + 'username' => $user['username'], + 'role' => $user['role'] + ]; + } + return null; +} +``` + +### 2. Потік оновлення токена + +Реалізуйте систему токенів оновлення для довготривалих сесій: + +```php +Flight::route('POST /api/login', function() { + // ... перевірка облікових даних ... + + $secretKey = Flight::get('config')['jwt_secret']; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + // Короткочасний токен доступу (15 хвилин) + $accessToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + // Довготривалий токен оновлення (7 днів) + $refreshToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'refresh', + 'iat' => time(), + 'exp' => time() + (7 * 24 * 60 * 60) + ], $refreshSecret, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'refresh_token' => $refreshToken, + 'expires_in' => 900 + ]); +}); + +Flight::route('POST /api/refresh', function() { + $refreshToken = Flight::request()->data->refresh_token ?? ''; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + try { + $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); + + // Перевірка, що це токен оновлення + if ($decoded->type !== 'refresh') { + Flight::jsonHalt(['error' => 'Invalid token type'], 401); + } + + // Генерація нового токена доступу + $secretKey = Flight::get('config')['jwt_secret']; + $accessToken = JWT::encode([ + 'user_id' => $decoded->user_id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'expires_in' => 900 + ]); + + } catch (Exception $e) { + Flight::jsonHalt(['error' => 'Invalid refresh token'], 401); + } +}); +``` + +### 3. Контроль доступу на основі ролей + +Розширте свій middleware для перевірки ролей користувача: + +```php +class JwtRoleMiddleware { + + protected Engine $app; + protected array $allowedRoles; + + public function __construct(Engine $app, array $allowedRoles = []) { + $this->app = $app; + $this->allowedRoles = $allowedRoles; + } + + public function before(array $params) { + // Припустимо, що JwtMiddleware вже запустився та встановив дані користувача + $user = $this->app->request()->data->user ?? null; + + if (!$user) { + $this->app->jsonHalt(['error' => 'Authentication required'], 401); + } + + // Перевірка, чи має користувач необхідну роль + if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { + $this->app->jsonHalt(['error' => 'Insufficient permissions'], 403); + } + } +} + +// Використання: Маршрут тільки для адміністраторів +Flight::route('DELETE /api/users/@id', function($id) { + // Логіка видалення користувача +})->addMiddleware([ + JwtMiddleware::class, + new JwtRoleMiddleware(Flight::app(), ['admin']) +]); +``` + +### 4. Публічний API з обмеженням швидкості за користувачем + +Використовуйте JWT для відстеження та обмеження швидкості користувачів без сесій: + +```php +class RateLimitMiddleware { + + public function before(array $params) { + $user = Flight::request()->data->user ?? null; + $userId = $user ? $user->user_id : Flight::request()->ip; + + $cacheKey = "rate_limit:$userId"; + // Переконайтеся, що налаштували сервіс кешу в app/config/services.php + $requests = Flight::cache()->get($cacheKey, 0); + + if ($requests >= 100) { // 100 запитів на годину + Flight::jsonHalt(['error' => 'Rate limit exceeded'], 429); + } + + Flight::cache()->set($cacheKey, $requests + 1, 3600); + } +} +``` + +## Найкращі практики безпеки + +### 1. Використовуйте сильні секретні ключі + +```php +// Генерація безпечного секретного ключа (запустіть один раз, збережіть у .env файл) +$secretKey = base64_encode(random_bytes(32)); +echo $secretKey; // Збережіть це у вашому .env файлі! +``` + +### 2. Зберігайте секрети в змінних середовища + +```php +// Ніколи не комітьте секрети до контролю версій! +// Використовуйте .env файл та бібліотеку, як vlucas/phpdotenv + +// .env файл: +// JWT_SECRET=your-base64-encoded-secret-here +// JWT_REFRESH_SECRET=another-base64-encoded-secret-here + +// Ви також можете використовувати файл app/config/config.php для зберігання секретів +// просто переконайтеся, що файл конфігурації не комітиться до контролю версій +// return [ +// 'jwt_secret' => 'your-base64-encoded-secret-here', +// 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', +// ]; + +// У вашому додатку: +$secretKey = getenv('JWT_SECRET'); +``` + +### 3. Встановіть відповідні терміни дії + +```php +// Хороша практика: короткочасні токени доступу +'exp' => time() + (15 * 60) // 15 хвилин + +// Для токенів оновлення: довший термін дії +'exp' => time() + (7 * 24 * 60 * 60) // 7 днів +``` + +### 4. Використовуйте HTTPS у продакшені + +JWT **завжди** повинні передаватися через HTTPS. Ніколи не надсилайте токени через звичайний HTTP у продакшені! + +### 5. Перевіряйте твердження токена + +Завжди перевіряйте твердження, які вас цікавлять: + +```php +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + +// Перевірка терміну дії обробляється автоматично бібліотекою +// Але ви можете додати власні перевірки: +if ($decoded->iat > time()) { + throw new Exception('Token used before it was issued'); +} + +if (isset($decoded->nbf) && $decoded->nbf > time()) { + throw new Exception('Token not yet valid'); +} +``` + +### 6. Розгляньте чорний список токенів для виходу + +Для додаткової безпеки підтримуйте чорний список анульованих токенів: + +```php +Flight::route('POST /api/logout', function() { + $authHeader = Flight::request()->getHeader('Authorization'); + preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches); + $jwt = $matches[1]; + + // Витягнення терміну дії токена + $decoded = Flight::request()->data->user; + $ttl = $decoded->exp - time(); + + // Збереження в кеші/redis до терміну дії + Flight::cache()->set("blacklist:$jwt", true, $ttl); + + Flight::json(['message' => 'Successfully logged out']); +}); + +// Додайте до вашого JwtMiddleware: +public function before(array $params) { + // ... витягнення JWT ... + + // Перевірка чорного списку + if (Flight::cache()->get("blacklist:$jwt")) { + $this->app->jsonHalt(['error' => 'Token has been revoked'], 401); + } + + // ... перевірка токена ... +} +``` + +## Алгоритми та типи ключів + +Firebase JWT підтримує кілька алгоритмів: + +### Симетричні алгоритми (HMAC) +- **HS256** (Рекомендовано для більшості додатків): Використовує один секретний ключ +- **HS384**, **HS512**: Сильніші варіанти + +```php +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Асиметричні алгоритми (RSA/ECDSA) +- **RS256**, **RS384**, **RS512**: Використовує пари публічний/приватний ключ +- **ES256**, **ES384**, **ES512**: Варіанти на еліптичних кривих + +```php +// Генерація ключів: openssl genrsa -out private.key 2048 +// openssl rsa -in private.key -pubout -out public.key + +$privateKey = file_get_contents('/path/to/private.key'); +$publicKey = file_get_contents('/path/to/public.key'); + +// Кодування з приватним ключем +$jwt = JWT::encode($payload, $privateKey, 'RS256'); + +// Декодування з публічним ключем +$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); +``` + +> **Коли використовувати RSA**: Використовуйте RSA, коли потрібно розповсюджувати публічний ключ для перевірки (наприклад, мікросервіси, інтеграції з третіми сторонами). Для одного додатка HS256 простіший і достатній. + +## Вирішення проблем + +### Помилка "Expired token" +Твердження `exp` вашого токена в минулому. Видайте новий токен або реалізуйте оновлення токена. + +### "Signature verification failed" +- Ви використовуєте інший секретний ключ для декодування, ніж для кодування +- Токен був змінений +- Розбіжність годинників між серверами (додайте буфер leeway) + +```php +use Firebase\JWT\JWT; + +JWT::$leeway = 60; // Дозволити 60 секунд розбіжності годинників +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### Токен не надсилається в запитах +Переконайтеся, що ваш клієнт надсилає заголовок `Authorization`: + +```javascript +// Приклад JavaScript +fetch('/api/users', { + headers: { + 'Authorization': 'Bearer ' + token + } +}); +``` + +## Методи + +Бібліотека Firebase JWT надає ці основні методи: + +- `JWT::encode(array $payload, string $key, string $alg)`: Створює JWT з навантаження +- `JWT::decode(string $jwt, Key $key)`: Декодує та перевіряє JWT +- `JWT::urlsafeB64Encode(string $input)`: Кодування Base64 безпечне для URL +- `JWT::urlsafeB64Decode(string $input)`: Декодування Base64 безпечне для URL +- `JWT::$leeway`: Статична властивість для встановлення leeway часу для перевірки (у секундах) + +## Чому використовувати цю бібліотеку? + +- **Стандарт галузі**: Firebase JWT — найпопулярніша та широко довірена JWT бібліотека для PHP +- **Активне обслуговування**: Підтримується командою Google/Firebase +- **Фокус на безпеці**: Регулярні оновлення та патчі безпеки +- **Простий API**: Легко зрозуміти та реалізувати +- **Добре документована**: Розгорнута документація та підтримка спільноти +- **Гнучка**: Підтримує кілька алгоритмів та конфігурованих опцій + +## Дивіться також + +- [Репозиторій Firebase JWT на Github](https://github.com/firebase/php-jwt) +- [JWT.io](https://jwt.io/) - Налагодження та декодування JWT +- [RFC 7519](https://tools.ietf.org/html/rfc7519) - Офіційна специфікація JWT +- [Документація Middleware Flight](/learn/middleware) +- [Плагін Session Flight](/awesome-plugins/session) - Для традиційної аутентифікації на основі сесій + +## Ліцензія + +Бібліотека Firebase JWT ліцензована за BSD 3-Clause License. Дивіться [репозиторій на Github](https://github.com/firebase/php-jwt) для деталей. \ No newline at end of file diff --git a/content/v3/zh/awesome-plugins/awesome_plugins.md b/content/v3/zh/awesome-plugins/awesome_plugins.md index e832fcf3..2e69bbde 100644 --- a/content/v3/zh/awesome-plugins/awesome_plugins.md +++ b/content/v3/zh/awesome-plugins/awesome_plugins.md @@ -1,97 +1,103 @@ -# 精彩插件 +# 优秀的插件 -Flight 极具扩展性。有许多插件可用于为您的 Flight 应用程序添加功能。其中一些由 Flight 团队官方支持,其他则是微型/轻量级库,帮助您快速上手。 +Flight 具有极强的可扩展性。有许多插件可以用来为您的 Flight 应用程序添加功能。其中一些由 Flight 团队官方支持,其他是一些微型/轻量级库,帮助您快速上手。 ## API 文档 -API 文档对任何 API 都至关重要。它帮助开发者了解如何与您的 API 交互以及预期返回结果。有几个工具可用于帮助您为 Flight 项目生成 API 文档。 +API 文档对于任何 API 都至关重要。它帮助开发者理解如何与您的 API 交互以及期望返回什么。有几个工具可用于帮助您为 Flight 项目生成 API 文档。 - [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - 由 Daniel Schreiber 撰写的博客文章,介绍如何使用 OpenAPI 规范与 FlightPHP 结合,采用 API 优先方法构建您的 API。 -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI 是一个优秀的工具,可帮助您为 Flight 项目生成 API 文档。它非常易用,并可自定义以满足您的需求。这是用于生成 Swagger 文档的 PHP 库。 +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI 是一个优秀的工具,可帮助您为 Flight 项目生成 API 文档。它非常易用,并且可以自定义以满足您的需求。这是用于生成 Swagger 文档的 PHP 库。 ## 应用程序性能监控 (APM) -应用程序性能监控 (APM) 对任何应用程序都至关重要。它帮助您了解应用程序的性能表现以及瓶颈所在。有许多 APM 工具可与 Flight 一起使用。 +应用程序性能监控 (APM) 对于任何应用程序都至关重要。它帮助您了解应用程序的性能表现以及瓶颈所在。有许多 APM 工具可与 Flight 一起使用。 - official [flightphp/apm](/awesome-plugins/apm) - Flight APM 是一个简单的 APM 库,可用于监控您的 Flight 应用程序。它可用于监控应用程序性能并帮助您识别瓶颈。 ## 异步 -Flight 已经是一个快速的框架,但为其添加涡轮引擎会让一切变得更有趣(且更具挑战性)! +Flight 已经是一个快速的框架,但为其添加涡轮引擎会让一切变得更有趣(也更具挑战性)! -- [flightphp/async](/awesome-plugins/async) - 官方 Flight Async 库。此库提供了一种简单的方式,为您的应用程序添加异步处理。它在底层使用 Swoole/Openswoole,提供简单有效的异步运行任务的方法。 +- [flightphp/async](/awesome-plugins/async) - 官方 Flight Async 库。该库是一种简单的方式,为您的应用程序添加异步处理。它在底层使用 Swoole/Openswoole,提供简单有效的方式异步运行任务。 ## 授权/权限 -授权和权限对任何需要控制访问权限的应用程序都至关重要。 +授权和权限对于任何需要控制访问权限的应用程序都至关重要。 -- official [flightphp/permissions](/awesome-plugins/permissions) - 官方 Flight Permissions 库。此库提供了一种简单的方式,为您的应用程序添加用户和应用程序级别的权限。 +- official [flightphp/permissions](/awesome-plugins/permissions) - 官方 Flight Permissions 库。该库是一种简单的方式,为您的应用程序添加用户和应用程序级别的权限。 + +## 认证 + +认证对于需要验证用户身份并保护 API 端点的应用程序至关重要。 + +- [firebase/php-jwt](/awesome-plugins/jwt) - PHP 的 JSON Web Token (JWT) 库。这是一种简单且安全的实现基于令牌认证的方式,适用于您的 Flight 应用程序。非常适合无状态 API 认证、使用中间件保护路由以及实现 OAuth 风格的授权流程。 ## 缓存 -缓存是加速应用程序的绝佳方式。有许多缓存库可与 Flight 一起使用。 +缓存是一种加速应用程序的绝佳方式。有许多缓存库可与 Flight 一起使用。 - official [flightphp/cache](/awesome-plugins/php-file-cache) - 轻量、简单且独立的 PHP 文件内缓存类 ## CLI -CLI 应用程序是与您的应用程序交互的绝佳方式。您可以使用它们生成控制器、显示所有路由等。 +CLI 应用程序是一种与您的应用程序交互的绝佳方式。您可以使用它们生成控制器、显示所有路由等。 - official [flightphp/runway](/awesome-plugins/runway) - Runway 是一个 CLI 应用程序,帮助您管理 Flight 应用程序。 ## Cookie -Cookie 是存储客户端小量数据的绝佳方式。它们可用于存储用户偏好、应用程序设置等。 +Cookie 是一种在客户端存储少量数据的绝佳方式。它们可用于存储用户偏好、应用程序设置等。 -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie 是一个 PHP 库,提供简单有效的 Cookie 管理方式。 +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie 是一个 PHP 库,提供简单有效的方式管理 Cookie。 ## 调试 在本地环境中开发时,调试至关重要。有几个插件可以提升您的调试体验。 - [tracy/tracy](/awesome-plugins/tracy) - 这是一个功能齐全的错误处理器,可与 Flight 一起使用。它有多个面板可帮助您调试应用程序。它也非常易于扩展并添加您自己的面板。 -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - 与 [Tracy](/awesome-plugins/tracy) 错误处理器一起使用,此插件添加了一些额外面板,专门帮助调试 Flight 项目。 +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - 与 [Tracy](/awesome-plugins/tracy) 错误处理器一起使用,此插件添加了一些额外的面板,专门帮助调试 Flight 项目。 ## 数据库 -数据库是大多数应用程序的核心。这是存储和检索数据的方式。有些数据库库只是查询的包装器,有些则是完整的 ORM。 +数据库是大多数应用程序的核心。这是存储和检索数据的方式。有些数据库库只是用于编写查询的包装器,有些则是功能齐全的 ORM。 - official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 官方 Flight PDO 包装器,是核心的一部分。这是一个简单的包装器,帮助简化编写和执行查询的过程。它不是 ORM。 -- official [flightphp/active-record](/awesome-plugins/active-record) - 官方 Flight ActiveRecord ORM/映射器。用于轻松检索和存储数据库数据的出色小库。 -- [byjg/php-migration](/awesome-plugins/migrations) - 用于跟踪项目中所有数据库变更的插件。 +- official [flightphp/active-record](/awesome-plugins/active-record) - 官方 Flight ActiveRecord ORM/映射器。一个优秀的库,便于轻松检索和存储数据库中的数据。 +- [byjg/php-migration](/awesome-plugins/migrations) - 用于跟踪项目中所有数据库更改的插件。 ## 加密 -加密对任何存储敏感数据的应用程序都至关重要。加密和解密数据并不难,但正确存储加密密钥 [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [很](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [困难](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)。最重要的是,切勿将加密密钥存储在公共目录中或提交到代码仓库。 +加密对于任何存储敏感数据的应用程序都至关重要。加密和解密数据并不难,但正确存储加密密钥 [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [会](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [很困难](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)。最重要的是,切勿将加密密钥存储在公共目录中或提交到您的代码仓库。 - [defuse/php-encryption](/awesome-plugins/php-encryption) - 这是一个可用于加密和解密数据的库。启动并运行非常简单,即可开始加密和解密数据。 ## 作业队列 -作业队列对于异步处理任务非常有帮助。这可以是发送电子邮件、处理图像,或任何不需要实时完成的任务。 +作业队列对于异步处理任务非常有用。这可以是发送电子邮件、处理图像,或任何不需要实时完成的任务。 - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue 是一个可用于异步处理作业的库。它可与 beanstalkd、MySQL/MariaDB、SQLite 和 PostgreSQL 一起使用。 ## 会话 -会话对 API 不是很有用,但对于构建 Web 应用程序,会话对于维护状态和登录信息至关重要。 +会话对于 API 并不太有用,但对于构建 Web 应用程序,会话对于维护状态和登录信息至关重要。 - official [flightphp/session](/awesome-plugins/session) - 官方 Flight Session 库。这是一个简单的会话库,可用于存储和检索会话数据。它使用 PHP 内置的会话处理。 - [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 会话管理器(非阻塞、闪存、分段、会话加密)。使用 PHP open_ssl 可选加密/解密会话数据。 ## 模板 -模板是任何带 UI 的 Web 应用程序的核心。有许多模板引擎可与 Flight 一起使用。 +模板是任何具有 UI 的 Web 应用程序的核心。有许多模板引擎可与 Flight 一起使用。 -- deprecated [flightphp/core View](/learn#views) - 这是一个非常基本的模板引擎,是核心的一部分。如果您的项目超过几页,不推荐使用。 +- deprecated [flightphp/core View](/learn#views) - 这是一个非常基本的模板引擎,是核心的一部分。如果您的项目有多个页面,不推荐使用。 - [latte/latte](/awesome-plugins/latte) - Latte 是一个功能齐全的模板引擎,非常易用,其语法比 Twig 或 Smarty 更接近 PHP。它也非常易于扩展并添加您自己的过滤器和函数。 -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate 是一个强大的 PHP 模板引擎,支持资产生成、模板继承和变量处理。具有自动 CSS/JS 压缩、缓存、Base64 编码,以及可选的 Flight PHP 框架集成。 +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate 是一个强大的 PHP 模板引擎,支持资产生成、模板继承和变量处理。具有自动 CSS/JS 压缩、缓存、Base64 编码以及可选的 Flight PHP 框架集成。 ## WordPress 集成 -想在您的 WordPress 项目中使用 Flight 吗?有一个方便的插件! +想在您的 WordPress 项目中使用 Flight?有一个方便的插件! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 此 WordPress 插件允许您在 WordPress 旁边运行 Flight。它非常适合使用 Flight 框架为您的 WordPress 站点添加自定义 API、微服务,甚至完整应用程序。如果您想兼得两者的优点,这超级有用! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 这个 WordPress 插件允许您在 WordPress 旁边运行 Flight。它非常适合使用 Flight 框架为您的 WordPress 站点添加自定义 API、微服务,甚至完整的应用程序。如果您想兼得两者的优点,这超级有用! ## 贡献 -有一个您想分享的插件吗?提交拉取请求将其添加到列表中! \ No newline at end of file +有一个您想分享的插件?提交拉取请求将其添加到列表中! \ No newline at end of file diff --git a/content/v3/zh/awesome-plugins/jwt.md b/content/v3/zh/awesome-plugins/jwt.md new file mode 100644 index 00000000..154b82ad --- /dev/null +++ b/content/v3/zh/awesome-plugins/jwt.md @@ -0,0 +1,532 @@ +# Firebase JWT - JSON Web Token Authentication for Flight + +JWT(JSON Web Tokens)是一种紧凑的、URL 安全的表示应用程序与客户端之间声明的方式。它们非常适合无状态 API 认证——无需服务器端会话存储!本指南将向您展示如何将 [Firebase JWT](https://github.com/firebase/php-jwt) 与 Flight 集成,以实现安全的基于令牌的认证。 + +访问 [Github 仓库](https://github.com/firebase/php-jwt) 以获取完整文档和详细信息。 + +## 什么是 JWT? + +JSON Web Token 是一个包含三个部分的字符串: +1. **Header**:关于令牌的元数据(算法、类型) +2. **Payload**:您的数据(用户 ID、角色、过期时间等) +3. **Signature**:用于验证真实性的加密签名 + +示例 JWT:`eyJ0eXAiOiJKV1QiLCJhbGc...`(看起来像乱码,但它是结构化数据!) + +### 为什么使用 JWT? + +- **无状态**:无需服务器端会话存储——非常适合微服务和 API +- **可扩展**:与负载均衡器配合良好,因为没有会话亲和性要求 +- **跨域**:可用于不同域和服务之间 +- **移动友好**:非常适合移动应用,在 cookie 可能无法正常工作的情况下 +- **标准化**:行业标准方法(RFC 7519) + +## 安装 + +通过 Composer 安装: + +```bash +composer require firebase/php-jwt +``` + +## 基本用法 + +这是一个创建和验证 JWT 的快速示例: + +```php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; + +// 您的密钥(请保持安全!) +$secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; + +// 创建令牌 +$payload = [ + 'user_id' => 123, + 'username' => 'johndoe', + 'role' => 'admin', + 'iat' => time(), // 发行时间 + 'exp' => time() + 3600 // 1 小时后过期 +]; + +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +echo "Token: " . $jwt; + +// 验证并解码令牌 +try { + $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + echo "User ID: " . $decoded->user_id; +} catch (Exception $e) { + echo "Invalid token: " . $e->getMessage(); +} +``` + +## Flight 的 JWT 中间件(推荐方法) + +使用 JWT 与 Flight 的最常见且最有用的方式是作为 **middleware** 来保护您的 API 路由。以下是一个完整的、生产就绪的示例: + +### 步骤 1:创建 JWT 中间件类 + +```php +// app/middleware/JwtMiddleware.php +use Firebase\JWT\JWT; +use Firebase\JWT\Key; +use Firebase\JWT\ExpiredException; +use Firebase\JWT\SignatureInvalidException; +use flight\Engine; + +class JwtMiddleware { + + protected Engine $app; + protected string $secretKey; + + public function __construct(Engine $app) { + $this->app = $app; + // 将您的密钥存储在 app/config/config.php 中,不要硬编码! + $this->secretKey = $app->get('config')['jwt_secret']; + } + + public function before(array $params) { + $authHeader = $this->app->request()->getHeader('Authorization'); + + // 检查 Authorization 标头是否存在 + if (empty($authHeader)) { + $this->app->jsonHalt(['error' => 'No authorization token provided'], 401); + } + + // 从 "Bearer " 格式中提取令牌 + if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { + $this->app->jsonHalt(['error' => 'Invalid authorization format. Use: Bearer '], 401); + } + + $jwt = $matches[1]; + + try { + // 解码并验证令牌 + $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); + + // 在请求中存储用户数据,以供路由处理程序使用 + $this->app->request()->data->user = $decoded; + + } catch (ExpiredException $e) { + $this->app->jsonHalt(['error' => 'Token has expired'], 401); + } catch (SignatureInvalidException $e) { + $this->app->jsonHalt(['error' => 'Invalid token signature'], 401); + } catch (Exception $e) { + $this->app->jsonHalt(['error' => 'Invalid token: ' . $e->getMessage()], 401); + } + } +} +``` + +### 步骤 2:在您的配置中注册 JWT 密钥 + +```php +// app/config/config.php +return [ + 'jwt_secret' => getenv('JWT_SECRET') ?: 'your-fallback-secret-for-development' +]; + +// app/config/bootstrap.php 或 index.php +// 如果您想将配置暴露给应用,请确保添加此行 +$app->set('config', $config); +``` + +> **安全注意**:切勿硬编码您的密钥!在生产环境中使用环境变量。 + +### 步骤 3:使用中间件保护您的路由 + +```php +// 保护单个路由 +Flight::route('GET /api/user/profile', function() { + $user = Flight::request()->data->user; // 由中间件设置 + Flight::json([ + 'user_id' => $user->user_id, + 'username' => $user->username, + 'role' => $user->role + ]); +})->addMiddleware( JwtMiddleware::class); + +// 保护一组路由(更常见!) +Flight::group('/api', function() { + Flight::route('GET /users', function() { /* ... */ }); + Flight::route('GET /posts', function() { /* ... */ }); + Flight::route('POST /posts', function() { /* ... */ }); + Flight::route('DELETE /posts/@id', function($id) { /* ... */ }); +}, [ JwtMiddleware::class ]); // 该组中的所有路由都受保护! +``` + +有关中间件的更多详细信息,请参阅 [middleware 文档](/learn/middleware)。 + +## 常见用例 + +### 1. 登录端点(令牌生成) + +创建一个在成功认证后生成 JWT 的路由: + +```php +Flight::route('POST /api/login', function() { + $data = Flight::request()->data; + $username = $data->username ?? ''; + $password = $data->password ?? ''; + + // 验证凭据(示例 - 使用您自己的逻辑!) + $user = validateUserCredentials($username, $password); + + if (!$user) { + Flight::jsonHalt(['error' => 'Invalid credentials'], 401); + } + + // 生成 JWT + $secretKey = Flight::get('config')['jwt_secret']; + $payload = [ + 'user_id' => $user->id, + 'username' => $user->username, + 'role' => $user->role, + 'iat' => time(), + 'exp' => time() + (60 * 60) // 1 小时过期 + ]; + + $jwt = JWT::encode($payload, $secretKey, 'HS256'); + + Flight::json([ + 'success' => true, + 'token' => $jwt, + 'expires_in' => 3600 + ]); +}); + +function validateUserCredentials($username, $password) { + // 在这里进行数据库查找和密码验证 + // 示例: + $db = Flight::db(); + $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); + + if ($user && password_verify($password, $user['password_hash'])) { + return (object) [ + 'id' => $user['id'], + 'username' => $user['username'], + 'role' => $user['role'] + ]; + } + return null; +} +``` + +### 2. 令牌刷新流程 + +为长寿命会话实现刷新令牌系统: + +```php +Flight::route('POST /api/login', function() { + // ... 验证凭据 ... + + $secretKey = Flight::get('config')['jwt_secret']; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + // 短寿命访问令牌(15 分钟) + $accessToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + // 长寿命刷新令牌(7 天) + $refreshToken = JWT::encode([ + 'user_id' => $user->id, + 'type' => 'refresh', + 'iat' => time(), + 'exp' => time() + (7 * 24 * 60 * 60) + ], $refreshSecret, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'refresh_token' => $refreshToken, + 'expires_in' => 900 + ]); +}); + +Flight::route('POST /api/refresh', function() { + $refreshToken = Flight::request()->data->refresh_token ?? ''; + $refreshSecret = Flight::get('config')['jwt_refresh_secret']; + + try { + $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); + + // 验证这是一个刷新令牌 + if ($decoded->type !== 'refresh') { + Flight::jsonHalt(['error' => 'Invalid token type'], 401); + } + + // 生成新的访问令牌 + $secretKey = Flight::get('config')['jwt_secret']; + $accessToken = JWT::encode([ + 'user_id' => $decoded->user_id, + 'type' => 'access', + 'iat' => time(), + 'exp' => time() + (15 * 60) + ], $secretKey, 'HS256'); + + Flight::json([ + 'access_token' => $accessToken, + 'expires_in' => 900 + ]); + + } catch (Exception $e) { + Flight::jsonHalt(['error' => 'Invalid refresh token'], 401); + } +}); +``` + +### 3. 基于角色的访问控制 + +扩展您的中间件以检查用户角色: + +```php +class JwtRoleMiddleware { + + protected Engine $app; + protected array $allowedRoles; + + public function __construct(Engine $app, array $allowedRoles = []) { + $this->app = $app; + $this->allowedRoles = $allowedRoles; + } + + public function before(array $params) { + // 假设 JwtMiddleware 已经运行并设置了用户数据 + $user = $this->app->request()->data->user ?? null; + + if (!$user) { + $this->app->jsonHalt(['error' => 'Authentication required'], 401); + } + + // 检查用户是否具有所需角色 + if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { + $this->app->jsonHalt(['error' => 'Insufficient permissions'], 403); + } + } +} + +// 用法:仅管理员路由 +Flight::route('DELETE /api/users/@id', function($id) { + // 删除用户逻辑 +})->addMiddleware([ + JwtMiddleware::class, + new JwtRoleMiddleware(Flight::app(), ['admin']) +]); +``` + +### 4. 公共 API 按用户限流 + +使用 JWT 在没有会话的情况下跟踪和限流用户: + +```php +class RateLimitMiddleware { + + public function before(array $params) { + $user = Flight::request()->data->user ?? null; + $userId = $user ? $user->user_id : Flight::request()->ip; + + $cacheKey = "rate_limit:$userId"; + // 确保在 app/config/services.php 中设置缓存服务 + $requests = Flight::cache()->get($cacheKey, 0); + + if ($requests >= 100) { // 每小时 100 个请求 + Flight::jsonHalt(['error' => 'Rate limit exceeded'], 429); + } + + Flight::cache()->set($cacheKey, $requests + 1, 3600); + } +} +``` + +## 安全最佳实践 + +### 1. 使用强密钥 + +```php +// 生成安全的密钥(运行一次,保存到 .env 文件) +$secretKey = base64_encode(random_bytes(32)); +echo $secretKey; // 将其存储在您的 .env 文件中! +``` + +### 2. 将密钥存储在环境变量中 + +```php +// 切勿将密钥提交到版本控制! +// 使用 .env 文件和像 vlucas/phpdotenv 这样的库 + +// .env 文件: +// JWT_SECRET=your-base64-encoded-secret-here +// JWT_REFRESH_SECRET=another-base64-encoded-secret-here + +// 您也可以使用 app/config/config.php 文件来存储密钥 +// 只是确保配置文件未提交到版本控制 +// return [ +// 'jwt_secret' => 'your-base64-encoded-secret-here', +// 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', +// ]; + +// 在您的应用中: +$secretKey = getenv('JWT_SECRET'); +``` + +### 3. 设置适当的过期时间 + +```php +// 良好实践:短寿命访问令牌 +'exp' => time() + (15 * 60) // 15 分钟 + +// 对于刷新令牌:更长的过期时间 +'exp' => time() + (7 * 24 * 60 * 60) // 7 天 +``` + +### 4. 在生产环境中使用 HTTPS + +JWT 应 **始终** 通过 HTTPS 传输。在生产环境中切勿通过纯 HTTP 发送令牌! + +### 5. 验证令牌声明 + +始终验证您关心的声明: + +```php +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); + +// 过期检查由库自动处理 +// 但您可以添加自定义验证: +if ($decoded->iat > time()) { + throw new Exception('Token used before it was issued'); +} + +if (isset($decoded->nbf) && $decoded->nbf > time()) { + throw new Exception('Token not yet valid'); +} +``` + +### 6. 为注销考虑令牌黑名单 + +为额外安全,维护无效令牌的黑名单: + +```php +Flight::route('POST /api/logout', function() { + $authHeader = Flight::request()->getHeader('Authorization'); + preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches); + $jwt = $matches[1]; + + // 提取令牌的过期时间 + $decoded = Flight::request()->data->user; + $ttl = $decoded->exp - time(); + + // 在缓存/Redis 中存储直到过期 + Flight::cache()->set("blacklist:$jwt", true, $ttl); + + Flight::json(['message' => 'Successfully logged out']); +}); + +// 添加到您的 JwtMiddleware: +public function before(array $params) { + // ... 提取 JWT ... + + // 检查黑名单 + if (Flight::cache()->get("blacklist:$jwt")) { + $this->app->jsonHalt(['error' => 'Token has been revoked'], 401); + } + + // ... 验证令牌 ... +} +``` + +## 算法和密钥类型 + +Firebase JWT 支持多种算法: + +### 对称算法 (HMAC) +- **HS256**(推荐用于大多数应用):使用单个密钥 +- **HS384**、**HS512**:更强的变体 + +```php +$jwt = JWT::encode($payload, $secretKey, 'HS256'); +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### 非对称算法 (RSA/ECDSA) +- **RS256**、**RS384**、**RS512**:使用公钥/私钥对 +- **ES256**、**ES384**、**ES512**:椭圆曲线变体 + +```php +// 生成密钥:openssl genrsa -out private.key 2048 +// openssl rsa -in private.key -pubout -out public.key + +$privateKey = file_get_contents('/path/to/private.key'); +$publicKey = file_get_contents('/path/to/public.key'); + +// 使用私钥编码 +$jwt = JWT::encode($payload, $privateKey, 'RS256'); + +// 使用公钥解码 +$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); +``` + +> **何时使用 RSA**:当您需要分发公钥进行验证时使用 RSA(例如,微服务、第三方集成)。对于单个应用,HS256 更简单且足够。 + +## 故障排除 + +### “过期令牌”错误 +您的令牌的 `exp` 声明已过去。颁发新令牌或实现令牌刷新。 + +### “签名验证失败” +- 您使用不同的密钥解码,而非用于编码的密钥 +- 令牌已被篡改 +- 服务器之间时钟偏差(添加宽限缓冲) + +```php +use Firebase\JWT\JWT; + +JWT::$leeway = 60; // 允许 60 秒时钟偏差 +$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); +``` + +### 请求中未发送令牌 +确保您的客户端发送 `Authorization` 标头: + +```javascript +// JavaScript 示例 +fetch('/api/users', { + headers: { + 'Authorization': 'Bearer ' + token + } +}); +``` + +## 方法 + +Firebase JWT 库提供这些核心方法: + +- `JWT::encode(array $payload, string $key, string $alg)`:从负载创建 JWT +- `JWT::decode(string $jwt, Key $key)`:解码并验证 JWT +- `JWT::urlsafeB64Encode(string $input)`:Base64 URL 安全编码 +- `JWT::urlsafeB64Decode(string $input)`:Base64 URL 安全解码 +- `JWT::$leeway`:用于验证的时间宽限静态属性(以秒为单位) + +## 为什么使用此库? + +- **行业标准**:Firebase JWT 是 PHP 中最流行和最受信任的 JWT 库 +- **积极维护**:由 Google/Firebase 团队维护 +- **安全焦点**:定期更新和安全补丁 +- **简单 API**:易于理解和实现 +- **文档完善**:广泛的文档和社区支持 +- **灵活**:支持多种算法和可配置选项 + +## 另请参阅 + +- [Firebase JWT Github 仓库](https://github.com/firebase/php-jwt) +- [JWT.io](https://jwt.io/) - 调试和解码 JWT +- [RFC 7519](https://tools.ietf.org/html/rfc7519) - 官方 JWT 规范 +- [Flight 中间件文档](/learn/middleware) +- [Flight 会话插件](/awesome-plugins/session) - 用于传统基于会话的认证 + +## 许可证 + +Firebase JWT 库采用 BSD 3-Clause 许可证。有关详细信息,请参阅 [Github 仓库](https://github.com/firebase/php-jwt)。 \ No newline at end of file From d57ade00ffa0f48064f75b21611c2d8349aa9e2d Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Thu, 1 Jan 2026 21:22:32 -0700 Subject: [PATCH 30/36] corrected jwt title --- content/v3/en/awesome-plugins/jwt.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/v3/en/awesome-plugins/jwt.md b/content/v3/en/awesome-plugins/jwt.md index ae5ea89e..df1c3391 100644 --- a/content/v3/en/awesome-plugins/jwt.md +++ b/content/v3/en/awesome-plugins/jwt.md @@ -1,4 +1,4 @@ -# Firebase JWT - JSON Web Token Authentication for Flight +# Firebase JWT - JSON Web Token Authentication JWT (JSON Web Tokens) are a compact, URL-safe way to represent claims between your application and a client. They're perfect for stateless API authentication—no need for server-side session storage! This guide shows you how to integrate [Firebase JWT](https://github.com/firebase/php-jwt) with Flight for secure, token-based authentication. From aaf0162a9676891712ef89572ded0b76a86f0e8b Mon Sep 17 00:00:00 2001 From: Falco Nogatz Date: Mon, 12 Jan 2026 17:33:16 +0100 Subject: [PATCH 31/36] Correct minor typos --- content/v3/en/learn/autoloading.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/v3/en/learn/autoloading.md b/content/v3/en/learn/autoloading.md index 37362809..8790c8e5 100644 --- a/content/v3/en/learn/autoloading.md +++ b/content/v3/en/learn/autoloading.md @@ -2,11 +2,11 @@ ## Overview -Autoloading is a concept in PHP where you specific a directory or directories to load classes from. This is much more beneficial than using `require` or `include` to load classes. It is also a requirement for using Composer packages. +Autoloading is a concept in PHP where you specify a directory or directories to load classes from. This is much more beneficial than using `require` or `include` to load classes. It is also a requirement for using Composer packages. ## Understanding -By default any `Flight` class is autoloaded for your automatically thanks to composer. However, if you want to autoload your own classes, you can use the `Flight::path()` method to specify a directory to load classes from. +By default, any `Flight` class is autoloaded for you automatically thanks to composer. However, if you want to autoload your own classes, you can use the `Flight::path()` method to specify a directory to load classes from. Using an autoloader can help simplify your code in a significant way. Instead of having files start with a myriad of `include` or `require` statements at the top to capture all classes that are used in that file, you can instead dynamically call your classes and they will be included automatically. @@ -201,4 +201,4 @@ Flight::path(__DIR__.'/../'); ## Changelog - v3.7.2 - You can use Pascal_Snake_Case for your class names by running `Loader::setV2ClassLoading(false);` -- v2.0 - Autoload functionality added. \ No newline at end of file +- v2.0 - Autoload functionality added. From 8f0ac1e2f1615c4e27c764795a589e044111753f Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Wed, 14 Jan 2026 17:36:26 -0700 Subject: [PATCH 32/36] added simplepdo and translated --- app/utils/DocsLogic.php | 3 +- .../v3/de/awesome-plugins/awesome_plugins.md | 47 +-- content/v3/de/awesome-plugins/jwt.md | 88 ++--- content/v3/de/awesome-plugins/runway.md | 58 ++-- content/v3/de/learn/autoloading.md | 58 ++-- content/v3/de/learn/learn.md | 40 ++- content/v3/de/learn/pdo_wrapper.md | 34 +- content/v3/de/learn/simple_pdo.md | 320 ++++++++++++++++++ .../v3/en/awesome-plugins/awesome_plugins.md | 3 +- content/v3/en/learn/learn.md | 8 +- content/v3/en/learn/pdo_wrapper.md | 4 + content/v3/en/learn/simple_pdo.md | 320 ++++++++++++++++++ .../v3/es/awesome-plugins/awesome_plugins.md | 35 +- content/v3/es/awesome-plugins/jwt.md | 66 ++-- content/v3/es/awesome-plugins/runway.md | 56 +-- content/v3/es/learn/autoloading.md | 86 ++--- content/v3/es/learn/learn.md | 62 ++-- content/v3/es/learn/pdo_wrapper.md | 10 +- content/v3/es/learn/simple_pdo.md | 320 ++++++++++++++++++ .../v3/fr/awesome-plugins/awesome_plugins.md | 29 +- content/v3/fr/awesome-plugins/jwt.md | 74 ++-- content/v3/fr/awesome-plugins/runway.md | 38 +-- content/v3/fr/learn/autoloading.md | 30 +- content/v3/fr/learn/learn.md | 62 ++-- content/v3/fr/learn/pdo_wrapper.md | 44 +-- content/v3/fr/learn/simple_pdo.md | 320 ++++++++++++++++++ .../v3/id/awesome-plugins/awesome_plugins.md | 35 +- content/v3/id/awesome-plugins/jwt.md | 64 ++-- content/v3/id/awesome-plugins/runway.md | 24 +- content/v3/id/learn/autoloading.md | 40 +-- content/v3/id/learn/learn.md | 28 +- content/v3/id/learn/pdo_wrapper.md | 24 +- content/v3/id/learn/simple_pdo.md | 320 ++++++++++++++++++ .../v3/ja/awesome-plugins/awesome_plugins.md | 61 ++-- content/v3/ja/awesome-plugins/jwt.md | 152 ++++----- content/v3/ja/awesome-plugins/runway.md | 58 ++-- content/v3/ja/learn/autoloading.md | 82 ++--- content/v3/ja/learn/learn.md | 72 ++-- content/v3/ja/learn/pdo_wrapper.md | 40 ++- content/v3/ja/learn/simple_pdo.md | 320 ++++++++++++++++++ .../v3/ko/awesome-plugins/awesome_plugins.md | 55 +-- content/v3/ko/awesome-plugins/jwt.md | 98 +++--- content/v3/ko/awesome-plugins/runway.md | 134 ++++---- content/v3/ko/learn/autoloading.md | 71 ++-- content/v3/ko/learn/learn.md | 32 +- content/v3/ko/learn/pdo_wrapper.md | 40 ++- content/v3/ko/learn/simple_pdo.md | 320 ++++++++++++++++++ .../v3/lv/awesome-plugins/awesome_plugins.md | 75 ++-- content/v3/lv/awesome-plugins/jwt.md | 130 +++---- content/v3/lv/awesome-plugins/runway.md | 66 ++-- content/v3/lv/learn/autoloading.md | 86 ++--- content/v3/lv/learn/learn.md | 30 +- content/v3/lv/learn/pdo_wrapper.md | 62 ++-- content/v3/lv/learn/simple_pdo.md | 320 ++++++++++++++++++ .../v3/pt/awesome-plugins/awesome_plugins.md | 39 +-- content/v3/pt/awesome-plugins/jwt.md | 84 ++--- content/v3/pt/awesome-plugins/runway.md | 46 +-- content/v3/pt/learn/autoloading.md | 18 +- content/v3/pt/learn/learn.md | 30 +- content/v3/pt/learn/pdo_wrapper.md | 20 +- content/v3/pt/learn/simple_pdo.md | 320 ++++++++++++++++++ .../v3/ru/awesome-plugins/awesome_plugins.md | 65 ++-- content/v3/ru/awesome-plugins/jwt.md | 106 +++--- content/v3/ru/awesome-plugins/runway.md | 26 +- content/v3/ru/learn/autoloading.md | 56 +-- content/v3/ru/learn/learn.md | 20 +- content/v3/ru/learn/pdo_wrapper.md | 34 +- content/v3/ru/learn/simple_pdo.md | 320 ++++++++++++++++++ .../v3/uk/awesome-plugins/awesome_plugins.md | 69 ++-- content/v3/uk/awesome-plugins/jwt.md | 72 ++-- content/v3/uk/awesome-plugins/runway.md | 56 +-- content/v3/uk/learn/autoloading.md | 28 +- content/v3/uk/learn/learn.md | 34 +- content/v3/uk/learn/pdo_wrapper.md | 56 +-- content/v3/uk/learn/simple_pdo.md | 320 ++++++++++++++++++ .../v3/zh/awesome-plugins/awesome_plugins.md | 47 +-- content/v3/zh/awesome-plugins/jwt.md | 70 ++-- content/v3/zh/awesome-plugins/runway.md | 36 +- content/v3/zh/learn/autoloading.md | 44 +-- content/v3/zh/learn/learn.md | 42 +-- content/v3/zh/learn/pdo_wrapper.md | 32 +- content/v3/zh/learn/simple_pdo.md | 320 ++++++++++++++++++ 82 files changed, 5706 insertions(+), 1758 deletions(-) create mode 100644 content/v3/de/learn/simple_pdo.md create mode 100644 content/v3/en/learn/simple_pdo.md create mode 100644 content/v3/es/learn/simple_pdo.md create mode 100644 content/v3/fr/learn/simple_pdo.md create mode 100644 content/v3/id/learn/simple_pdo.md create mode 100644 content/v3/ja/learn/simple_pdo.md create mode 100644 content/v3/ko/learn/simple_pdo.md create mode 100644 content/v3/lv/learn/simple_pdo.md create mode 100644 content/v3/pt/learn/simple_pdo.md create mode 100644 content/v3/ru/learn/simple_pdo.md create mode 100644 content/v3/uk/learn/simple_pdo.md create mode 100644 content/v3/zh/learn/simple_pdo.md diff --git a/app/utils/DocsLogic.php b/app/utils/DocsLogic.php index bd3fde69..d1b12744 100644 --- a/app/utils/DocsLogic.php +++ b/app/utils/DocsLogic.php @@ -61,7 +61,8 @@ public function getLearnSectionNames(): array { 'Utility Classes' => [ ['url' => '/learn/collections', 'title' => 'Collections'], ['url' => '/learn/json', 'title' => 'JSON Wrapper'], - ['url' => '/learn/pdo-wrapper', 'title' => 'PDO Wrapper'], + ['url' => '/learn/pdo-wrapper', 'title' => 'PdoWrapper'], + ['url' => '/learn/simple-pdo', 'title' => 'SimplePdo'], ['url' => '/learn/uploaded-file', 'title' => 'Uploaded File Handler'], ], 'Important Concepts' => [ diff --git a/content/v3/de/awesome-plugins/awesome_plugins.md b/content/v3/de/awesome-plugins/awesome_plugins.md index 20b0aadd..2ade0256 100644 --- a/content/v3/de/awesome-plugins/awesome_plugins.md +++ b/content/v3/de/awesome-plugins/awesome_plugins.md @@ -1,4 +1,4 @@ -# Tolle Plugins +# Awesome 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 und andere sind Micro/Lite-Bibliotheken, um Ihnen den Einstieg zu erleichtern. @@ -12,7 +12,7 @@ API-Dokumentation ist entscheidend für jede API. Sie hilft Entwicklern zu verst ## Application Performance Monitoring (APM) Application Performance Monitoring (APM) ist entscheidend für jede Anwendung. Es hilft Ihnen zu verstehen, wie Ihre Anwendung performt und wo die Engpässe liegen. Es gibt eine Reihe von APM-Tools, die mit Flight verwendet werden können. -- offiziell [flightphp/apm](/awesome-plugins/apm) - Flight APM ist eine einfache APM-Bibliothek, die verwendet werden kann, um Ihre Flight-Anwendungen zu überwachen. Sie kann verwendet werden, um die Leistung Ihrer Anwendung zu überwachen und Ihnen zu helfen, Engpässe zu identifizieren. +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM ist eine einfache APM-Bibliothek, die verwendet werden kann, um Ihre Flight-Anwendungen zu überwachen. Sie kann verwendet werden, um die Performance Ihrer Anwendung zu überwachen und Ihnen zu helfen, Engpässe zu identifizieren. ## Async @@ -20,29 +20,29 @@ Flight ist bereits ein schnelles Framework, aber es mit einem Turbo-Motor auszus - [flightphp/async](/awesome-plugins/async) - Offizielle Flight Async-Bibliothek. Diese Bibliothek ist eine einfache Möglichkeit, asynchrone Verarbeitung zu Ihrer Anwendung hinzuzufügen. Sie verwendet Swoole/Openswoole im Hintergrund, um eine einfache und effektive Möglichkeit zu bieten, Aufgaben asynchron auszuführen. -## Autorisierung/Berechtigungen +## Authorization/Permissions -Autorisierung und Berechtigungen sind entscheidend für jede Anwendung, die Steuerelemente benötigt, um festzulegen, wer auf was zugreifen kann. +Autorisierung und Berechtigungen sind entscheidend für jede Anwendung, die Steuerelemente benötigt, um zu definieren, wer auf was zugreifen kann. -- offiziell [flightphp/permissions](/awesome-plugins/permissions) - Offizielle Flight Permissions-Bibliothek. Diese Bibliothek ist eine einfache Möglichkeit, Benutzer- und Anwendungsebenen-Berechtigungen zu Ihrer Anwendung hinzuzufügen. +- official [flightphp/permissions](/awesome-plugins/permissions) - Offizielle Flight Permissions-Bibliothek. Diese Bibliothek ist eine einfache Möglichkeit, Benutzer- und Anwendungsebene-Berechtigungen zu Ihrer Anwendung hinzuzufügen. -## Authentifizierung +## Authentication Authentifizierung ist essenziell für Anwendungen, die die Benutzeridentität überprüfen und API-Endpunkte sichern müssen. -- [firebase/php-jwt](/awesome-plugins/jwt) - JSON Web Token (JWT)-Bibliothek für PHP. Eine einfache und sichere Möglichkeit, tokenbasierte Authentifizierung in Ihren Flight-Anwendungen zu implementieren. Perfekt für stateless API-Authentifizierung, Schutz von Routen mit Middleware und Implementierung von OAuth-ähnlichen Autorisierungsflüssen. +- [firebase/php-jwt](/awesome-plugins/jwt) - JSON Web Token (JWT)-Bibliothek für PHP. Eine einfache und sichere Möglichkeit, tokenbasierte Authentifizierung in Ihren Flight-Anwendungen zu implementieren. Perfekt für stateless API-Authentifizierung, Schutz von Routen mit Middleware und Implementierung von OAuth-ähnlichen Autorisierungsabläufen. ## Caching Caching ist eine großartige Möglichkeit, Ihre Anwendung zu beschleunigen. Es gibt eine Reihe von Caching-Bibliotheken, die mit Flight verwendet werden können. -- offiziell [flightphp/cache](/awesome-plugins/php-file-cache) - Leichte, einfache und eigenständige PHP-In-Datei-Caching-Klasse +- official [flightphp/cache](/awesome-plugins/php-file-cache) - Leichte, einfache und eigenständige PHP-In-File-Caching-Klasse ## CLI CLI-Anwendungen sind eine großartige Möglichkeit, mit Ihrer Anwendung zu interagieren. Sie können sie verwenden, um Controller zu generieren, alle Routen anzuzeigen und mehr. -- offiziell [flightphp/runway](/awesome-plugins/runway) - Runway ist eine CLI-Anwendung, die Ihnen hilft, Ihre Flight-Anwendungen zu verwalten. +- official [flightphp/runway](/awesome-plugins/runway) - Runway ist eine CLI-Anwendung, die Ihnen hilft, Ihre Flight-Anwendungen zu verwalten. ## Cookies @@ -55,19 +55,20 @@ Cookies sind eine großartige Möglichkeit, kleine Datenmengen auf der Client-Se Debugging ist entscheidend, wenn Sie in Ihrer lokalen Umgebung entwickeln. Es gibt ein paar Plugins, die Ihr Debugging-Erlebnis verbessern können. - [tracy/tracy](/awesome-plugins/tracy) - Dies ist ein vollständiges Fehlerbehandlungs-Tool, das mit Flight verwendet werden kann. Es hat eine Reihe von Panels, die Ihnen helfen können, Ihre Anwendung zu debuggen. Es ist auch sehr einfach zu erweitern und eigene Panels hinzuzufügen. -- offiziell [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Wird mit dem [Tracy](/awesome-plugins/tracy) Fehlerbehandlungs-Tool verwendet, fügt dieses Plugin ein paar zusätzliche Panels hinzu, um das Debugging speziell für Flight-Projekte zu erleichtern. +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Wird mit dem [Tracy](/awesome-plugins/tracy) Fehlerbehandlungs-Tool verwendet, fügt dieses Plugin ein paar zusätzliche Panels hinzu, um das Debugging speziell für Flight-Projekte zu erleichtern. -## Datenbanken +## Databases Datenbanken sind der Kern der meisten Anwendungen. So speichern und rufen Sie Daten ab. Einige Datenbank-Bibliotheken sind einfach Wrapper, um Abfragen zu schreiben, und einige sind vollwertige ORMs. -- offiziell [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Offizieller Flight PDO-Wrapper, der zum Kern gehört. Dies ist ein einfacher Wrapper, der hilft, den Prozess des Schreibens und Ausführens von Abfragen zu vereinfachen. Es handelt sich nicht um ein ORM. -- offiziell [flightphp/active-record](/awesome-plugins/active-record) - Offizielles Flight ActiveRecord ORM/Mapper. Tolle kleine Bibliothek, um Daten einfach in Ihrer Datenbank abzurufen und zu speichern. +- official [flightphp/core SimplePdo](/learn/simple-pdo) - Offizieller Flight PDO-Helfer, der zum Kern gehört. Dies ist ein moderner Wrapper mit bequemen Helfermethoden wie `insert()`, `update()`, `delete()` und `transaction()`, um Datenbankoperationen zu vereinfachen. Alle Ergebnisse werden als Collections zurückgegeben für flexiblen Array/Objekt-Zugriff. Kein ORM, nur eine bessere Möglichkeit, mit PDO zu arbeiten. +- deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Offizieller Flight PDO-Wrapper, der zum Kern gehört (veraltet ab v3.18.0). Verwenden Sie stattdessen SimplePdo. +- official [flightphp/active-record](/awesome-plugins/active-record) - Offizielles Flight ActiveRecord ORM/Mapper. Tolle kleine Bibliothek, um Daten einfach in Ihrer Datenbank abzurufen und zu speichern. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin, um alle Datenbankänderungen für Ihr Projekt zu verfolgen. -## Verschlüsselung +## Encryption -Verschlüsselung ist entscheidend für jede Anwendung, die sensible Daten speichert. Das Verschlüsseln und Entschlüsseln der Daten ist nicht besonders schwierig, aber das ordnungsgemäße Speichern des Verschlüsselungsschlüssels [kann](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [sein](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [schwierig](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Das Wichtigste ist, Ihren Verschlüsselungsschlüssel nie in einem öffentlichen Verzeichnis zu speichern oder ihn in Ihr Code-Repository zu committen. +Verschlüsselung ist entscheidend für jede Anwendung, die sensible Daten speichert. Das Verschlüsseln und Entschlüsseln der Daten ist nicht allzu schwer, aber das ordnungsgemäße Speichern des Verschlüsselungsschlüssels [kann](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [sein](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [schwierig](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Das Wichtigste ist, Ihren Verschlüsselungsschlüssel niemals in einem öffentlichen Verzeichnis zu speichern oder ihn in Ihr Code-Repository zu committen. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Dies ist eine Bibliothek, die verwendet werden kann, um Daten zu verschlüsseln und zu entschlüsseln. Der Einstieg ist ziemlich einfach, um mit dem Verschlüsseln und Entschlüsseln von Daten zu beginnen. @@ -79,25 +80,25 @@ Job-Warteschlangen sind wirklich hilfreich, um Aufgaben asynchron zu verarbeiten ## Session -Sessions sind für APIs nicht wirklich nützlich, aber beim Aufbau einer Web-Anwendung können Sessions entscheidend sein, um Zustände und Login-Informationen aufrechtzuerhalten. +Sitzungen sind für APIs nicht wirklich nützlich, aber für den Aufbau einer Web-Anwendung können Sitzungen entscheidend sein, um Zustände und Anmeldeinformationen zu erhalten. -- offiziell [flightphp/session](/awesome-plugins/session) - Offizielle Flight Session-Bibliothek. Dies ist eine einfache Session-Bibliothek, die verwendet werden kann, um Session-Daten zu speichern und abzurufen. Sie verwendet die integrierte Session-Behandlung von PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session-Manager (nicht-blockierend, Flash, Segment, Session-Verschlüsselung). Verwendet PHP open_ssl für optionale Verschlüsselung/Entschlüsselung von Session-Daten. +- official [flightphp/session](/awesome-plugins/session) - Offizielle Flight Session-Bibliothek. Dies ist eine einfache Session-Bibliothek, die verwendet werden kann, um Session-Daten zu speichern und abzurufen. Sie verwendet die integrierte Session-Behandlung von PHP. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (nicht-blockierend, Flash, Segment, Session-Verschlüsselung). Verwendet PHP open_ssl für optionale Verschlüsselung/Entschlüsselung von Session-Daten. ## Templating Templating ist der Kern jeder Web-Anwendung mit einer UI. Es gibt eine Reihe von Templating-Engines, die mit Flight verwendet werden können. -- veraltet [flightphp/core View](/learn#views) - Dies ist eine sehr grundlegende Templating-Engine, die zum Kern gehört. Es wird nicht empfohlen, sie zu verwenden, wenn Sie mehr als ein paar Seiten in Ihrem Projekt haben. -- [latte/latte](/awesome-plugins/latte) - Latte ist eine vollständige Templating-Engine, die sehr einfach zu bedienen ist und näher an der PHP-Syntax liegt als Twig oder Smarty. Sie ist auch sehr einfach zu erweitern und eigene Filter und Funktionen hinzuzufügen. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate ist ein leistungsstarkes PHP-Template-Engine mit Asset-Kompilierung, Template-Vererbung und Variablenverarbeitung. Features automatisierte CSS/JS-Minifizierung, Caching, Base64-Codierung und optionale Integration mit dem Flight PHP-Framework. +- deprecated [flightphp/core View](/learn#views) - Dies ist eine sehr grundlegende Templating-Engine, die zum Kern gehört. Es wird nicht empfohlen, sie zu verwenden, wenn Ihr Projekt mehr als ein paar Seiten hat. +- [latte/latte](/awesome-plugins/latte) - Latte ist eine vollständige Templating-Engine, die sehr einfach zu bedienen ist und sich näher an der PHP-Syntax anfühlt als Twig oder Smarty. Sie ist auch sehr einfach zu erweitern und eigene Filter und Funktionen hinzuzufügen. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate ist eine leistungsstarke PHP-Template-Engine mit Asset-Kompilierung, Template-Vererbung und Variablenverarbeitung. Features automatisches CSS/JS-Minifizieren, Caching, Base64-Encoding und optionale Integration mit dem Flight PHP-Framework. -## WordPress-Integration +## WordPress Integration Möchten Sie Flight in Ihrem WordPress-Projekt verwenden? Es gibt ein praktisches Plugin dafür! - [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Dieses WordPress-Plugin ermöglicht es Ihnen, Flight direkt neben WordPress auszuführen. Es ist perfekt, um benutzerdefinierte APIs, Microservices oder sogar vollständige Apps zu Ihrer WordPress-Site mit dem Flight-Framework hinzuzufügen. Super nützlich, wenn Sie das Beste aus beiden Welten wollen! -## Mitwirkung +## Contributing Haben Sie ein Plugin, das Sie teilen möchten? Reichen Sie einen Pull Request ein, um es zur Liste hinzuzufügen! \ No newline at end of file diff --git a/content/v3/de/awesome-plugins/jwt.md b/content/v3/de/awesome-plugins/jwt.md index 08e81939..1c51fbf5 100644 --- a/content/v3/de/awesome-plugins/jwt.md +++ b/content/v3/de/awesome-plugins/jwt.md @@ -1,21 +1,21 @@ -# Firebase JWT - JSON Web Token Authentifizierung für Flight +# Firebase JWT - JSON Web Token Authentifizierung -JWT (JSON Web Tokens) sind eine kompakte, URL-sichere Methode, um Ansprüche zwischen Ihrer Anwendung und einem Client darzustellen. Sie eignen sich perfekt für stateless API-Authentifizierung – kein Bedarf an serverseitiger Sitzungsspeicherung! Diese Anleitung zeigt Ihnen, wie Sie [Firebase JWT](https://github.com/firebase/php-jwt) mit Flight für sichere, tokenbasierte Authentifizierung integrieren. +JWT (JSON Web Tokens) sind eine kompakte, URL-sichere Methode, um Ansprüche zwischen Ihrer Anwendung und einem Client darzustellen. Sie eignen sich perfekt für zustandslose API-Authentifizierung – kein Bedarf an serverseitiger Sitzungsspeicherung! Diese Anleitung zeigt Ihnen, wie Sie [Firebase JWT](https://github.com/firebase/php-jwt) mit Flight für sichere, tokenbasierte Authentifizierung integrieren. Besuchen Sie das [Github-Repository](https://github.com/firebase/php-jwt) für die vollständige Dokumentation und Details. ## Was ist JWT? Ein JSON Web Token ist eine Zeichenkette, die aus drei Teilen besteht: -1. **Header**: Metadaten über das Token (Algorithmus, Typ) -2. **Payload**: Ihre Daten (Benutzer-ID, Rollen, Ablauf usw.) +1. **Header**: Metadaten über den Token (Algorithmus, Typ) +2. **Payload**: Ihre Daten (Benutzer-ID, Rollen, Ablaufdatum usw.) 3. **Signature**: Kryptografische Signatur zur Überprüfung der Authentizität Beispiel-JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (sieht aus wie Kauderwelsch, ist aber strukturierte Daten!) ### Warum JWT verwenden? -- **Stateless**: Keine serverseitige Sitzungsspeicherung erforderlich – perfekt für Microservices und APIs +- **Zustandslos**: Keine serverseitige Sitzungsspeicherung erforderlich – perfekt für Microservices und APIs - **Skalierbar**: Funktioniert hervorragend mit Load Balancern, da keine Sitzungsaffinität erforderlich ist - **Cross-Domain**: Kann über verschiedene Domains und Dienste hinweg verwendet werden - **Mobile-freundlich**: Ideal für Mobile-Apps, wo Cookies möglicherweise nicht gut funktionieren @@ -31,7 +31,7 @@ composer require firebase/php-jwt ## Grundlegende Verwendung -Hier ist ein schnelles Beispiel für die Erstellung und Überprüfung eines JWT: +Hier ist ein schnelles Beispiel zum Erstellen und Überprüfen eines JWT: ```php use Firebase\JWT\JWT; @@ -40,7 +40,7 @@ use Firebase\JWT\Key; // Ihr geheimer Schlüssel (HALTEN SIE DAS SICHER!) $secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; -// Erstellen eines Tokens +// Einen Token erstellen $payload = [ 'user_id' => 123, 'username' => 'johndoe', @@ -52,18 +52,18 @@ $payload = [ $jwt = JWT::encode($payload, $secretKey, 'HS256'); echo "Token: " . $jwt; -// Überprüfen und Dekodieren eines Tokens +// Einen Token überprüfen und dekodieren try { $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); echo "User ID: " . $decoded->user_id; } catch (Exception $e) { - echo "Ungültiges Token: " . $e->getMessage(); + echo "Ungültiger Token: " . $e->getMessage(); } ``` ## JWT-Middleware für Flight (Empfohlener Ansatz) -Der gängigste und nützlichste Weg, JWT mit Flight zu verwenden, ist als **Middleware**, um Ihre API-Routen zu schützen. Hier ist ein vollständiges, produktionsreifes Beispiel: +Die gängigste und nützlichste Methode, JWT mit Flight zu verwenden, ist als **Middleware**, um Ihre API-Routen zu schützen. Hier ist ein vollständiges, produktionsreifes Beispiel: ### Schritt 1: Erstellen einer JWT-Middleware-Klasse @@ -89,7 +89,7 @@ class JwtMiddleware { public function before(array $params) { $authHeader = $this->app->request()->getHeader('Authorization'); - // Überprüfen, ob der Authorization-Header vorhanden ist + // Überprüfen, ob der Authorization-Header existiert if (empty($authHeader)) { $this->app->jsonHalt(['error' => 'Kein Autorisierungstoken bereitgestellt'], 401); } @@ -102,10 +102,10 @@ class JwtMiddleware { $jwt = $matches[1]; try { - // Das Token dekodieren und überprüfen + // Den Token dekodieren und überprüfen $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); - // Benutzerdaten in der Anfrage für die Verwendung in Routen-Handlern speichern + // Benutzerdaten in der Anfrage speichern, um sie in Routen-Handlern zu verwenden $this->app->request()->data->user = $decoded; } catch (ExpiredException $e) { @@ -113,13 +113,13 @@ class JwtMiddleware { } catch (SignatureInvalidException $e) { $this->app->jsonHalt(['error' => 'Ungültige Token-Signatur'], 401); } catch (Exception $e) { - $this->app->jsonHalt(['error' => 'Ungültiges Token: ' . $e->getMessage()], 401); + $this->app->jsonHalt(['error' => 'Ungültiger Token: ' . $e->getMessage()], 401); } } } ``` -### Schritt 2: JWT-Geheimnis in Ihrer Konfiguration registrieren +### Schritt 2: JWT-Geheimschlüssel in Ihrer Konfiguration registrieren ```php // app/config/config.php @@ -132,20 +132,20 @@ return [ $app->set('config', $config); ``` -> **Sicherheitshinweis**: Kodieren Sie Ihren geheimen Schlüssel niemals hart! Verwenden Sie Umgebungsvariablen in der Produktion. +> **Sicherheitshinweis**: Codieren Sie Ihren geheimen Schlüssel niemals hart! Verwenden Sie Umgebungsvariablen in der Produktion. ### Schritt 3: Ihre Routen mit Middleware schützen ```php // Eine einzelne Route schützen Flight::route('GET /api/user/profile', function() { - $user = Flight::request()->data->user; // Von Middleware gesetzt + $user = Flight::request()->data->user; // Von der Middleware gesetzt Flight::json([ 'user_id' => $user->user_id, 'username' => $user->username, 'role' => $user->role ]); -})->addMiddleware( JwtMiddleware::class); +})->addMiddleware(JwtMiddleware::class); // Eine gesamte Gruppe von Routen schützen (häufiger!) Flight::group('/api', function() { @@ -279,7 +279,7 @@ Flight::route('POST /api/refresh', function() { }); ``` -### 3. Rollengestützte Zugriffssteuerung +### 3. Rollenbasierte Zugriffssteuerung Erweitern Sie Ihre Middleware, um Benutzerrollen zu überprüfen: @@ -295,7 +295,7 @@ class JwtRoleMiddleware { } public function before(array $params) { - // Annahme: JwtMiddleware hat bereits ausgeführt und Benutzerdaten gesetzt + // Angenommen, JwtMiddleware hat bereits ausgeführt und Benutzerdaten gesetzt $user = $this->app->request()->data->user ?? null; if (!$user) { @@ -330,7 +330,7 @@ class RateLimitMiddleware { $userId = $user ? $user->user_id : Flight::request()->ip; $cacheKey = "rate_limit:$userId"; - // Stellen Sie sicher, dass Sie einen Cache-Dienst in app/config/services.php einrichten + // Stellen Sie sicher, dass Sie einen Cache-Dienst in app/config/services.php eingerichtet haben $requests = Flight::cache()->get($cacheKey, 0); if ($requests >= 100) { // 100 Anfragen pro Stunde @@ -355,7 +355,7 @@ echo $secretKey; // Speichern Sie das in Ihrer .env-Datei! ### 2. Geheimnisse in Umgebungsvariablen speichern ```php -// Geheimnisse niemals in die Versionskontrolle committen! +// Commiten Sie Geheimnisse niemals in die Versionskontrolle! // Verwenden Sie eine .env-Datei und eine Bibliothek wie vlucas/phpdotenv // .env-Datei: @@ -363,7 +363,7 @@ echo $secretKey; // Speichern Sie das in Ihrer .env-Datei! // JWT_REFRESH_SECRET=another-base64-encoded-secret-here // Sie können auch die app/config/config.php-Datei verwenden, um Ihre Geheimnisse zu speichern -// Stellen Sie nur sicher, dass die Konfigurationsdatei nicht in die Versionskontrolle committet wird +// stellen Sie nur sicher, dass die Konfigurationsdatei nicht in die Versionskontrolle committed wird // return [ // 'jwt_secret' => 'your-base64-encoded-secret-here', // 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', @@ -385,7 +385,7 @@ $secretKey = getenv('JWT_SECRET'); ### 4. HTTPS in der Produktion verwenden -JWTs sollten **immer** über HTTPS übertragen werden. Senden Sie Tokens niemals über einfaches HTTP in der Produktion! +JWTs sollten **immer** über HTTPS übertragen werden. Senden Sie Tokens in der Produktion niemals über einfaches HTTP! ### 5. Token-Ansprüche validieren @@ -397,7 +397,7 @@ $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); // Überprüfung des Ablaufs wird automatisch von der Bibliothek gehandhabt // Aber Sie können benutzerdefinierte Validierungen hinzufügen: if ($decoded->iat > time()) { - throw new Exception('Token verwendet, bevor es ausgestellt wurde'); + throw new Exception('Token vor Ausstellung verwendet'); } if (isset($decoded->nbf) && $decoded->nbf > time()) { @@ -407,7 +407,7 @@ if (isset($decoded->nbf) && $decoded->nbf > time()) { ### 6. Token-Blacklisting für Logout in Betracht ziehen -Für zusätzliche Sicherheit eine Blacklist ungültiger Tokens pflegen: +Für zusätzliche Sicherheit eine Blacklist ungültiger Tokens führen: ```php Flight::route('POST /api/logout', function() { @@ -415,7 +415,7 @@ Flight::route('POST /api/logout', function() { preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches); $jwt = $matches[1]; - // Den Ablauf des Tokens extrahieren + // Ablauf des Tokens extrahieren $decoded = Flight::request()->data->user; $ttl = $decoded->exp - time(); @@ -452,7 +452,7 @@ $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); ``` ### Asymmetrische Algorithmen (RSA/ECDSA) -- **RS256**, **RS384**, **RS512**: Verwendet öffentliche/privaten Schlüsselpaare +- **RS256**, **RS384**, **RS512**: Verwendet Public/Private-Key-Paare - **ES256**, **ES384**, **ES512**: Elliptische-Kurven-Varianten ```php @@ -469,26 +469,26 @@ $jwt = JWT::encode($payload, $privateKey, 'RS256'); $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); ``` -> **Wann RSA verwenden**: Verwenden Sie RSA, wenn Sie den öffentlichen Schlüssel für die Überprüfung verteilen müssen (z. B. Microservices, Drittanbieter-Integrationen). Für eine einzelne Anwendung ist HS256 einfacher und ausreichend. +> **Wann RSA verwenden**: Verwenden Sie RSA, wenn Sie den öffentlichen Schlüssel für die Verifizierung verteilen müssen (z. B. Microservices, Drittanbieter-Integrationen). Für eine einzelne Anwendung ist HS256 einfacher und ausreichend. ## Fehlerbehebung -### "Abgelaufenes Token"-Fehler -Der `exp`-Anspruch Ihres Tokens liegt in der Vergangenheit. Stellen Sie ein neues Token aus oder implementieren Sie Token-Refresh. +### "Expired token" Fehler +Der `exp`-Anspruch Ihres Tokens liegt in der Vergangenheit. Geben Sie ein neues Token aus oder implementieren Sie Token-Refresh. -### "Signaturüberprüfung fehlgeschlagen" +### "Signature verification failed" - Sie verwenden einen anderen geheimen Schlüssel zum Dekodieren als zum Kodieren -- Das Token wurde manipuliert -- Uhrzeitskew zwischen Servern (fügen Sie einen Leeway-Puffer hinzu) +- Der Token wurde manipuliert +- Uhrzeitänderung zwischen Servern (fügen Sie einen Leeway-Puffer hinzu) ```php use Firebase\JWT\JWT; -JWT::$leeway = 60; // 60 Sekunden Uhrzeitskew erlauben +JWT::$leeway = 60; // 60 Sekunden Uhrzeitänderung erlauben $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); ``` -### Token wird nicht in Anfragen gesendet +### Token wird in Anfragen nicht gesendet Stellen Sie sicher, dass Ihr Client den `Authorization`-Header sendet: ```javascript @@ -502,31 +502,31 @@ fetch('/api/users', { ## Methoden -Die Firebase JWT-Bibliothek stellt diese Kernmethoden bereit: +Die Firebase-JWT-Bibliothek stellt diese Kernmethoden zur Verfügung: - `JWT::encode(array $payload, string $key, string $alg)`: Erstellt ein JWT aus einem Payload - `JWT::decode(string $jwt, Key $key)`: Dekodiert und überprüft ein JWT - `JWT::urlsafeB64Encode(string $input)`: Base64 URL-sichere Kodierung - `JWT::urlsafeB64Decode(string $input)`: Base64 URL-sichere Dekodierung -- `JWT::$leeway`: Statische Eigenschaft zum Festlegen der Zeit-Leeway für Validierung (in Sekunden) +- `JWT::$leeway`: Statische Eigenschaft, um Zeit-Leeway für die Validierung festzulegen (in Sekunden) ## Warum diese Bibliothek verwenden? - **Branchenstandard**: Firebase JWT ist die beliebteste und am weitesten vertrauenswürdige JWT-Bibliothek für PHP -- **Aktive Wartung**: Wird vom Google/Firebase-Team gepflegt +- **Aktive Wartung**: Gepflegt vom Google/Firebase-Team - **Sicherheitsfokussiert**: Regelmäßige Updates und Sicherheits-Patches - **Einfache API**: Leicht zu verstehen und zu implementieren -- **Gut dokumentiert**: Umfangreiche Dokumentation und Community-Support +- **Gut dokumentiert**: Umfangreiche Dokumentation und Community-Unterstützung - **Flexibel**: Unterstützt mehrere Algorithmen und konfigurierbare Optionen ## Siehe auch -- [Firebase JWT Github-Repository](https://github.com/firebase/php-jwt) +- [Firebase JWT Github Repository](https://github.com/firebase/php-jwt) - [JWT.io](https://jwt.io/) - JWTs debuggen und dekodieren - [RFC 7519](https://tools.ietf.org/html/rfc7519) - Offizielle JWT-Spezifikation -- [Flight Middleware-Dokumentation](/learn/middleware) -- [Flight Session-Plugin](/awesome-plugins/session) - Für traditionelle sitzungsbasierte Authentifizierung +- [Flight Middleware Dokumentation](/learn/middleware) +- [Flight Session Plugin](/awesome-plugins/session) - Für traditionelle sitzungsbasierte Authentifizierung ## Lizenz -Die Firebase JWT-Bibliothek ist unter der BSD 3-Clause License lizenziert. Siehe das [Github-Repository](https://github.com/firebase/php-jwt) für Details. \ No newline at end of file +Die Firebase-JWT-Bibliothek ist unter der BSD 3-Clause License lizenziert. Details finden Sie im [Github-Repository](https://github.com/firebase/php-jwt). \ No newline at end of file diff --git a/content/v3/de/awesome-plugins/runway.md b/content/v3/de/awesome-plugins/runway.md index 283bcf58..c011a45d 100644 --- a/content/v3/de/awesome-plugins/runway.md +++ b/content/v3/de/awesome-plugins/runway.md @@ -14,7 +14,7 @@ composer require flightphp/runway ## Basis-Konfiguration -Beim ersten Ausführen von Runway versucht es, eine `runway`-Konfiguration in `app/config/config.php` über den Schlüssel `'runway'` zu finden. +Beim ersten Ausführen von Runway sucht es nach einer `runway`-Konfiguration in `app/config/config.php` über den Schlüssel `'runway'`. ```php argument('', 'Der Name des lustigen GIFs'); } @@ -178,7 +178,7 @@ class ExampleCommand extends AbstractBaseCommand } ``` -Lesen Sie die [adhocore/php-cli-Dokumentation](https://github.com/adhocore/php-cli), um mehr darüber zu erfahren, wie Sie eigene benutzerdefinierte Befehle in Ihre Flight-Anwendung einbauen! +Sehen Sie sich die [adhocore/php-cli-Dokumentation](https://github.com/adhocore/php-cli) für weitere Informationen an, wie Sie eigene benutzerdefinierte Befehle in Ihre Flight-Anwendung einbauen können! ## Konfigurationsverwaltung @@ -194,7 +194,7 @@ php runway config:migrate ### Konfigurationswert setzen -Sie können einen Konfigurationswert mit dem `config:set`-Befehl setzen. Dies ist nützlich, wenn Sie einen Konfigurationswert aktualisieren möchten, ohne die Datei zu öffnen. +Sie können einen Konfigurationswert mit dem Befehl `config:set` setzen. Dies ist nützlich, wenn Sie einen Konfigurationswert aktualisieren möchten, ohne die Datei zu öffnen. ```bash php runway config:set app_root "app/" @@ -202,7 +202,7 @@ php runway config:set app_root "app/" ### Konfigurationswert abrufen -Sie können einen Konfigurationswert mit dem `config:get`-Befehl abrufen. +Sie können einen Konfigurationswert mit dem Befehl `config:get` abrufen. ```bash php runway config:get app_root @@ -210,7 +210,7 @@ php runway config:get app_root ## Alle Runway-Konfigurationen -Wenn Sie die Konfiguration für Runway anpassen müssen, können Sie diese Werte in `app/config/config.php` setzen. Nachfolgend sind einige zusätzliche Konfigurationen, die Sie setzen können: +Wenn Sie die Konfiguration für Runway anpassen müssen, können Sie diese Werte in `app/config/config.php` setzen. Unten sind einige zusätzliche Konfigurationen, die Sie setzen können: ```php [ - // Hier befindet sich Ihr Anwendungsverzeichnis + // Hier liegt Ihr Anwendungsverzeichnis 'app_root' => 'app/', // Dies ist das Verzeichnis, in dem sich Ihre Root-Index-Datei befindet @@ -231,9 +231,9 @@ return [ '/var/www/another-project' ], - // Basis-Pfade müssen wahrscheinlich nicht konfiguriert werden, aber es ist hier, falls Sie es möchten + // Basis-Pfade müssen wahrscheinlich nicht konfiguriert werden, aber es ist hier, falls Sie es wollen 'base_paths' => [ - '/includes/libs/vendor', // wenn Sie einen wirklich einzigartigen Pfad für Ihr Vendor-Verzeichnis haben oder so + '/includes/libs/vendor', // falls Sie einen wirklich einzigartigen Pfad für Ihr Vendor-Verzeichnis haben oder so ], // Finale Pfade sind Orte innerhalb eines Projekts, um nach Befehlsdateien zu suchen @@ -254,17 +254,17 @@ return [ ### Zugriff auf Konfiguration -Wenn Sie die Konfigurationswerte effektiv abrufen müssen, können Sie sie über die `__construct`-Methode oder die `app()`-Methode abrufen. Es ist auch wichtig zu beachten, dass, wenn Sie eine `app/config/services.php`-Datei haben, diese Dienste ebenfalls für Ihren Befehl verfügbar sind. +Wenn Sie die Konfigurationswerte effektiv abrufen müssen, können Sie sie über die `__construct`-Methode oder die `app()`-Methode abrufen. Es ist auch wichtig zu beachten, dass, wenn Sie eine Datei `app/config/services.php` haben, diese Dienste auch für Ihren Befehl verfügbar sind. ```php public function execute() { $io = $this->app()->io(); - // Zugriff auf Konfiguration + // Konfiguration abrufen $app_root = $this->config['runway']['app_root']; - // Zugriff auf Dienste wie vielleicht eine Datenbankverbindung + // Dienste abrufen, wie vielleicht eine Datenbankverbindung $database = $this->config['database'] // ... @@ -273,12 +273,12 @@ public function execute() ## AI-Hilfs-Wrapper -Runway hat einige Hilfs-Wrapper, die es einfacher machen, für KI Befehle zu generieren. Sie können `addOption` und `addArgument` auf eine Weise verwenden, die ähnlich wie Symfony Console wirkt. Dies ist hilfreich, wenn Sie KI-Tools verwenden, um Ihre Befehle zu generieren. +Runway hat einige Hilfs-Wrapper, die es AI einfacher machen, Befehle zu generieren. Sie können `addOption` und `addArgument` auf eine Weise verwenden, die ähnlich wie bei Symfony Console wirkt. Dies ist hilfreich, wenn Sie AI-Tools verwenden, um Ihre Befehle zu generieren. ```php public function __construct(array $config) { - parent::__construct('make:example', 'Erstelle ein Beispiel für die Dokumentation', $config); + parent::__construct('make:example', 'Erstellt ein Beispiel für die Dokumentation', $config); // Der Name-Argument ist nullable und standardmäßig vollständig optional $this->addOption('name', 'Der Name des Beispiels', null); diff --git a/content/v3/de/learn/autoloading.md b/content/v3/de/learn/autoloading.md index 986ecd59..aac52224 100644 --- a/content/v3/de/learn/autoloading.md +++ b/content/v3/de/learn/autoloading.md @@ -6,13 +6,13 @@ Autoloading ist ein Konzept in PHP, bei dem Sie ein Verzeichnis oder Verzeichnis ## Verständnis -Standardmäßig wird jede `Flight`-Klasse automatisch für Sie autogeladen dank Composer. Wenn Sie jedoch Ihre eigenen Klassen autoladen möchten, können Sie die Methode `Flight::path()` verwenden, um ein Verzeichnis anzugeben, aus dem Klassen geladen werden. +Standardmäßig wird jede `Flight`-Klasse dank Composer automatisch für Sie autoloaded. Wenn Sie jedoch Ihre eigenen Klassen autoloaden möchten, können Sie die Methode `Flight::path()` verwenden, um ein Verzeichnis anzugeben, aus dem Klassen geladen werden. -Die Verwendung eines Autoloaders kann Ihren Code auf erhebliche Weise vereinfachen. Anstatt dass Dateien mit einer Vielzahl von `include`- oder `require`-Anweisungen am Anfang beginnen, um alle in dieser Datei verwendeten Klassen zu erfassen, können Sie stattdessen Ihre Klassen dynamisch aufrufen, und sie werden automatisch eingeschlossen. +Die Verwendung eines Autoloaders kann Ihren Code auf erhebliche Weise vereinfachen. Statt dass Dateien mit einer Vielzahl von `include`- oder `require`-Anweisungen am Anfang beginnen, um alle in dieser Datei verwendeten Klassen zu erfassen, können Sie Ihre Klassen stattdessen dynamisch aufrufen, und sie werden automatisch eingeschlossen. ## Grundlegende Verwendung -Nehmen wir an, wir haben eine Verzeichnisstruktur wie die folgende: +Nehmen wir an, wir haben einen Verzeichnisbaum wie den folgenden: ```text # Beispielpfad @@ -40,7 +40,7 @@ Sie können jedes Verzeichnis zum Laden wie folgt angeben: * public/index.php */ -// Einen Pfad zum Autoloader hinzufügen +// Fügen Sie einen Pfad zum Autoloader hinzu Flight::path(__DIR__.'/../app/controllers/'); Flight::path(__DIR__.'/../app/utils/'); @@ -49,9 +49,9 @@ Flight::path(__DIR__.'/../app/utils/'); * app/controllers/MyController.php */ -// Kein Namespacing erforderlich +// Keine Namensräume erforderlich -// Alle autogeladenen Klassen sollten im Pascal Case sein (jedes Wort großgeschrieben, keine Leerzeichen) +// Alle autoloaded Klassen sollten im Pascal Case sein (jedes Wort großgeschrieben, keine Leerzeichen) class MyController { public function index() { @@ -60,9 +60,9 @@ class MyController { } ``` -## Namespaces +## Namensräume -Wenn Sie Namespaces haben, wird es tatsächlich sehr einfach, dies zu implementieren. Sie sollten die Methode `Flight::path()` verwenden, um das Stammverzeichnis (nicht das Dokumentenroot oder das `public/`-Verzeichnis) Ihrer Anwendung anzugeben. +Wenn Sie Namensräume haben, wird es tatsächlich sehr einfach, dies zu implementieren. Sie sollten die Methode `Flight::path()` verwenden, um das Stammverzeichnis (nicht das Dokumentenroot oder den `public/`-Ordner) Ihrer Anwendung anzugeben. ```php @@ -70,24 +70,24 @@ Wenn Sie Namespaces haben, wird es tatsächlich sehr einfach, dies zu implementi * public/index.php */ -// Einen Pfad zum Autoloader hinzufügen +// Fügen Sie einen Pfad zum Autoloader hinzu Flight::path(__DIR__.'/../'); ``` -Nun könnte Ihr Controller so aussehen. Schauen Sie sich das Beispiel unten an, aber achten Sie auf die Kommentare für wichtige Informationen. +Nun sieht Ihr Controller so aus. Schauen Sie sich das Beispiel unten an, aber achten Sie auf die Kommentare für wichtige Informationen. ```php /** * app/controllers/MyController.php */ -// Namespaces sind erforderlich -// Namespaces sind identisch mit der Verzeichnisstruktur -// Namespaces müssen die gleiche Schreibweise wie die Verzeichnisstruktur haben -// Namespaces und Verzeichnisse dürfen keine Unterstriche enthalten (es sei denn, Loader::setV2ClassLoading(false) ist gesetzt) +// Namensräume sind erforderlich +// Namensräume sind identisch mit der Verzeichnisstruktur +// Namensräume müssen dem gleichen Groß-/Kleinschreibungsstil der Verzeichnisstruktur folgen +// Namensräume und Verzeichnisse dürfen keine Unterstriche enthalten (es sei denn, Loader::setV2ClassLoading(false) ist gesetzt) namespace app\controllers; -// Alle autogeladenen Klassen sollten im Pascal Case sein (jedes Wort großgeschrieben, keine Leerzeichen) +// Alle autoloaded Klassen sollten im Pascal Case sein (jedes Wort großgeschrieben, keine Leerzeichen) // Ab 3.7.2 können Sie Pascal_Snake_Case für Ihre Klassennamen verwenden, indem Sie Loader::setV2ClassLoading(false) ausführen; class MyController { @@ -97,7 +97,7 @@ class MyController { } ``` -Und wenn Sie eine Klasse in Ihrem utils-Verzeichnis autoladen möchten, würden Sie im Wesentlichen dasselbe tun: +Und wenn Sie eine Klasse in Ihrem utils-Verzeichnis autoloaden möchten, würden Sie im Wesentlichen dasselbe tun: ```php @@ -105,7 +105,7 @@ Und wenn Sie eine Klasse in Ihrem utils-Verzeichnis autoladen möchten, würden * app/UTILS/ArrayHelperUtil.php */ -// Namespace muss der Verzeichnisstruktur und Schreibweise entsprechen (beachten Sie, dass das UTILS-Verzeichnis in Großbuchstaben ist +// Der Namensraum muss der Verzeichnisstruktur und dem Groß-/Kleinschreibungsstil entsprechen (beachten Sie, dass das UTILS-Verzeichnis in Großbuchstaben ist // wie im Dateibaum oben) namespace app\UTILS; @@ -120,7 +120,7 @@ class ArrayHelperUtil { ## Unterstriche in Klassennamen Ab 3.7.2 können Sie Pascal_Snake_Case für Ihre Klassennamen verwenden, indem Sie `Loader::setV2ClassLoading(false);` ausführen. -Dies ermöglicht die Verwendung von Unterstrichen in Ihren Klassennamen. +Dies ermöglicht es Ihnen, Unterstriche in Ihren Klassennamen zu verwenden. Dies wird nicht empfohlen, ist aber für diejenigen verfügbar, die es benötigen. ```php @@ -130,7 +130,7 @@ use flight\core\Loader; * public/index.php */ -// Einen Pfad zum Autoloader hinzufügen +// Fügen Sie einen Pfad zum Autoloader hinzu Flight::path(__DIR__.'/../app/controllers/'); Flight::path(__DIR__.'/../app/utils/'); Loader::setV2ClassLoading(false); @@ -139,7 +139,7 @@ Loader::setV2ClassLoading(false); * app/controllers/My_Controller.php */ -// Kein Namespacing erforderlich +// Keine Namensräume erforderlich class My_Controller { @@ -150,15 +150,15 @@ class My_Controller { ``` ## Siehe auch -- [Routing](/learn/routing) - Wie man Routen zu Controllern abbildet und Views rendert. +- [Routing](/learn/routing) - Wie man Routen zu Controllern zuweist und Views rendert. - [Warum ein Framework?](/learn/why-frameworks) - Das Verständnis der Vorteile der Verwendung eines Frameworks wie Flight. ## Fehlerbehebung -- Wenn Sie nicht herausfinden können, warum Ihre namespaced Klassen nicht gefunden werden, erinnern Sie sich daran, `Flight::path()` zum Stammverzeichnis in Ihrem Projekt zu verwenden, nicht zu Ihrem `app/`- oder `src/`-Verzeichnis oder Äquivalent. +- Wenn Sie nicht herausfinden können, warum Ihre namespaced Klassen nicht gefunden werden, denken Sie daran, `Flight::path()` zum Stammverzeichnis in Ihrem Projekt zu verwenden, nicht zu Ihrem `app/`- oder `src/`-Verzeichnis oder Äquivalent. ### Klasse nicht gefunden (Autoloading funktioniert nicht) -Es könnte ein paar Gründe dafür geben, dass dies nicht passiert. Unten sind einige Beispiele, aber stellen Sie sicher, dass Sie auch den Abschnitt [autoloading](/learn/autoloading) überprüfen. +Es könnte ein paar Gründe dafür geben, dass dies nicht passiert. Unten sind einige Beispiele, aber stellen Sie sicher, dass Sie auch den [Autoloading](/learn/autoloading)-Abschnitt überprüfen. #### Falscher Dateiname Der häufigste Grund ist, dass der Klassenname nicht zum Dateinamen passt. @@ -166,14 +166,14 @@ Der häufigste Grund ist, dass der Klassenname nicht zum Dateinamen passt. Wenn Sie eine Klasse namens `MyClass` haben, sollte die Datei `MyClass.php` heißen. Wenn Sie eine Klasse namens `MyClass` haben und die Datei `myclass.php` heißt, kann der Autoloader sie nicht finden. -#### Falscher Namespace -Wenn Sie Namespaces verwenden, sollte der Namespace der Verzeichnisstruktur entsprechen. +#### Falscher Namensraum +Wenn Sie Namensräume verwenden, sollte der Namensraum zur Verzeichnisstruktur passen. ```php // ...code... -// wenn Ihr MyController im app/controllers-Verzeichnis ist und namespaced -// das wird nicht funktionieren. +// Wenn Ihr MyController im app/controllers-Verzeichnis ist und namespaced +// Dies wird nicht funktionieren. Flight::route('/hello', 'MyController->hello'); // Sie müssen eine dieser Optionen wählen @@ -191,10 +191,10 @@ Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); #### `path()` nicht definiert -In der Skeleton-App wird dies in der `config.php`-Datei definiert, aber damit Ihre Klassen gefunden werden, müssen Sie sicherstellen, dass die `path()`-Methode definiert ist (wahrscheinlich zum Stammverzeichnis Ihres Verzeichnisses), bevor Sie sie verwenden. +In der Skeleton-App ist dies in der `config.php`-Datei definiert, aber damit Ihre Klassen gefunden werden, müssen Sie sicherstellen, dass die `path()`-Methode definiert ist (wahrscheinlich zum Stammverzeichnis Ihres Verzeichnisses), bevor Sie sie verwenden. ```php -// Einen Pfad zum Autoloader hinzufügen +// Fügen Sie einen Pfad zum Autoloader hinzu Flight::path(__DIR__.'/../'); ``` diff --git a/content/v3/de/learn/learn.md b/content/v3/de/learn/learn.md index 58d2ac58..a97f813d 100644 --- a/content/v3/de/learn/learn.md +++ b/content/v3/de/learn/learn.md @@ -1,15 +1,15 @@ -# Über Flight lernen +# Lernen Sie Flight kennen -Flight ist ein schnelles, einfaches, erweiterbares Framework für PHP. Es ist sehr vielseitig und kann für die Erstellung aller Arten von Webanwendungen verwendet werden. -Es ist mit dem Gedanken an Einfachheit gebaut und auf eine Weise geschrieben, die leicht zu verstehen und zu verwenden ist. +Flight ist ein schnelles, einfaches, erweiterbares Framework für PHP. Es ist sehr vielseitig und kann für die Erstellung aller Arten von Web-Anwendungen verwendet werden. +Es wurde mit dem Gedanken an Einfachheit entwickelt und so geschrieben, dass es leicht zu verstehen und zu verwenden ist. -> **Hinweis:** Sie werden Beispiele sehen, die `Flight::` als statische Variable verwenden, und einige, die das Engine-Objekt `$app->` verwenden. Beide funktionieren austauschbar mit dem anderen. `$app` und `$this->app` in einem Controller/Middleware ist der empfohlene Ansatz vom Flight-Team. +> **Hinweis:** Sie werden Beispiele sehen, die `Flight::` als statische Variable verwenden und einige, die das Engine-Objekt `$app->` verwenden. Beide funktionieren austauschbar mit dem anderen. `$app` und `$this->app` in einem Controller/Middleware ist der empfohlene Ansatz vom Flight-Team. ## Kernkomponenten ### [Routing](/learn/routing) -Lernen Sie, wie Sie Routen für Ihre Webanwendung verwalten. Dies umfasst auch das Gruppieren von Routen, Routenparameter und Middleware. +Lernen Sie, wie Sie Routen für Ihre Web-Anwendung verwalten. Dies umfasst auch das Gruppieren von Routen, Routenparameter und Middleware. ### [Middleware](/learn/middleware) @@ -45,7 +45,7 @@ Lernen Sie, wie Sie das Event-System verwenden, um benutzerdefinierte Events zu ### [Extending Flight](/learn/extending) -Lernen Sie, wie Sie das Framework erweitern, indem Sie eigene Methoden und Klassen hinzufügen. +Lernen Sie, wie Sie das Framework erweitern, indem Sie Ihre eigenen Methoden und Klassen hinzufügen. ### [Method Hooks and Filtering](/learn/filtering) @@ -55,19 +55,23 @@ Lernen Sie, wie Sie Event-Hooks zu Ihren Methoden und internen Framework-Methode Lernen Sie, wie Sie Dependency-Injection-Container (DIC) verwenden, um die Abhängigkeiten Ihrer Anwendung zu verwalten. -## Utility-Klassen +## Utility Classes ### [Collections](/learn/collections) -Collections werden verwendet, um Daten zu speichern und sie als Array oder als Objekt zugänglich zu machen, um die Bedienung zu erleichtern. +Collections werden verwendet, um Daten zu speichern und sie als Array oder als Objekt zugänglich zu machen, um die Nutzung zu erleichtern. ### [JSON Wrapper](/learn/json) -Dies bietet einige einfache Funktionen, um das Encodieren und Decodieren von JSON konsistent zu gestalten. +Dies bietet einige einfache Funktionen, um das Encodieren und Decodieren Ihres JSON konsistent zu machen. -### [PDO Wrapper](/learn/pdo-wrapper) +### [SimplePdo](/learn/simple-pdo) -PDO kann manchmal mehr Kopfschmerzen verursachen als notwendig. Diese einfache Wrapper-Klasse kann die Interaktion mit Ihrer Datenbank erheblich erleichtern. +PDO kann manchmal mehr Kopfschmerzen verursachen als notwendig. SimplePdo ist eine moderne PDO-Hilfsklasse mit bequemen Methoden wie `insert()`, `update()`, `delete()` und `transaction()`, um Datenbankoperationen viel einfacher zu machen. + +### [PdoWrapper](/learn/pdo-wrapper) (Deprecated) + +Der ursprüngliche PDO-Wrapper ist ab v3.18.0 veraltet. Bitte verwenden Sie stattdessen [SimplePdo](/learn/simple-pdo). ### [Uploaded File Handler](/learn/uploaded-file) @@ -75,28 +79,28 @@ Eine einfache Klasse, die hilft, hochgeladene Dateien zu verwalten und sie an ei ## Wichtige Konzepte -### [Warum ein Framework?](/learn/why-frameworks) +### [Why a Framework?](/learn/why-frameworks) 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 einsetzen. Zusätzlich wurde ein exzellentes Tutorial von [@lubiana](https://git.php.fail/lubiana) erstellt. Obwohl es nicht insbesondere auf Flight eingeht, -hilft diese Anleitung Ihnen, einige der wichtigsten Konzepte rund um ein Framework zu verstehen und warum sie nützlich sind. +hilft diese Anleitung Ihnen, einige der wichtigsten Konzepte rund um ein Framework zu verstehen und warum sie vorteilhaft sind. Sie finden das Tutorial [hier](https://git.php.fail/lubiana/no-framework-tutorial/src/branch/master/README.md). -### [Flight im Vergleich zu anderen Frameworks](/learn/flight-vs-another-framework) +### [Flight Compared to Other Frameworks](/learn/flight-vs-another-framework) -Wenn Sie von einem anderen Framework wie Laravel, Slim, Fat-Free oder Symfony zu Flight migrieren, hilft diese Seite Ihnen, die Unterschiede zwischen den beiden zu verstehen. +Wenn Sie von einem anderen Framework wie Laravel, Slim, Fat-Free oder Symfony zu Flight migrieren, hilft Ihnen diese Seite, die Unterschiede zwischen den beiden zu verstehen. ## Andere Themen ### [Unit Testing](/learn/unit-testing) -Folgen Sie dieser Anleitung, um zu lernen, wie Sie Ihren Flight-Code mit Unit-Tests robust machen. +Folgen Sie dieser Anleitung, um zu lernen, wie Sie Ihren Flight-Code unit-testen, um ihn robust zu machen. ### [AI & Developer Experience](/learn/ai) -Lernen Sie, wie Flight mit AI-Tools und modernen Developer-Workflows zusammenarbeitet, um Ihnen zu helfen, schneller und smarter zu coden. +Lernen Sie, wie Flight mit AI-Tools und modernen Entwickler-Workflows zusammenarbeitet, um Ihnen zu helfen, schneller und smarter zu coden. ### [Migrating v2 -> v3](/learn/migrating-to-v3) -Rückwärtskompatibilität wurde größtenteils beibehalten, aber es gibt einige Änderungen, die Sie bei der Migration von v2 zu v3 beachten sollten. \ No newline at end of file +Rückwärtskompatibilität wurde größtenteils beibehalten, aber es gibt einige Änderungen, die Sie beim Migrieren von v2 zu v3 beachten sollten. \ No newline at end of file diff --git a/content/v3/de/learn/pdo_wrapper.md b/content/v3/de/learn/pdo_wrapper.md index 1803e027..0f3792ee 100644 --- a/content/v3/de/learn/pdo_wrapper.md +++ b/content/v3/de/learn/pdo_wrapper.md @@ -1,18 +1,22 @@ # PdoWrapper PDO-Hilfsklasse +> **WARNUNG** +> +> **Veraltet:** `PdoWrapper` ist veraltet ab Flight v3.18.0. Es wird in einer zukünftigen Version nicht entfernt, aber nur für Abwärtskompatibilität gewartet. Bitte verwenden Sie stattdessen [SimplePdo](/learn/simple-pdo), das die gleiche Funktionalität plus zusätzliche Hilfsmethoden für gängige Datenbankoperationen bietet. + ## Überblick -Die `PdoWrapper`-Klasse in Flight ist eine benutzerfreundliche Hilfsklasse für die Arbeit mit Datenbanken unter Verwendung von PDO. Sie vereinfacht gängige Datenbankaufgaben, fügt nützliche Methoden zum Abrufen von Ergebnissen hinzu und gibt Ergebnisse als [Collections](/learn/collections) zurück, um einen einfachen Zugriff zu ermöglichen. Sie unterstützt außerdem Protokollierung von Abfragen und Überwachung der Anwendungsleistung (APM) für fortgeschrittene Anwendungsfälle. +Die `PdoWrapper`-Klasse in Flight ist ein freundlicher Helfer für die Arbeit mit Datenbanken unter Verwendung von PDO. Sie vereinfacht gängige Datenbankaufgaben, fügt einige nützliche Methoden zum Abrufen von Ergebnissen hinzu und gibt Ergebnisse als [Collections](/learn/collections) zurück, um einen einfachen Zugriff zu ermöglichen. Sie unterstützt auch Query-Logging und Application Performance Monitoring (APM) für fortgeschrittene Anwendungsfälle. ## Verständnis -Die Arbeit mit Datenbanken in PHP kann etwas umständlich sein, insbesondere bei der direkten Verwendung von PDO. `PdoWrapper` erweitert PDO und fügt Methoden hinzu, die das Abfragen, Abrufen und Behandeln von Ergebnissen erheblich erleichtern. Statt mit vorbereiteten Anweisungen und Abrufmodi zu jonglieren, erhalten Sie einfache Methoden für gängige Aufgaben, und jede Zeile wird als Collection zurückgegeben, sodass Sie Array- oder Objektnotation verwenden können. +Die Arbeit mit Datenbanken in PHP kann etwas umständlich sein, insbesondere bei der direkten Verwendung von PDO. `PdoWrapper` erweitert PDO und fügt Methoden hinzu, die Abfragen, Abrufen und Behandeln von Ergebnissen viel einfacher machen. Statt mit Prepared Statements und Fetch-Modi zu jonglieren, erhalten Sie einfache Methoden für gängige Aufgaben, und jede Zeile wird als Collection zurückgegeben, sodass Sie Array- oder Objekt-Notation verwenden können. -Sie können `PdoWrapper` als geteilten Dienst in Flight registrieren und es dann überall in Ihrer App über `Flight::db()` verwenden. +Sie können `PdoWrapper` als geteilten Service in Flight registrieren und es dann überall in Ihrer App über `Flight::db()` verwenden. ## Grundlegende Verwendung -### Registrieren der PDO-Hilfsklasse +### Registrieren des PDO-Helpers Zuerst registrieren Sie die `PdoWrapper`-Klasse bei Flight: @@ -56,7 +60,7 @@ $db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]); `function fetchField(string $sql, array $params = []): mixed` -Einen einzelnen Wert aus der Datenbank abrufen: +Holen Sie einen einzelnen Wert aus der Datenbank: ```php $count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']); @@ -66,7 +70,7 @@ $count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", `function fetchRow(string $sql, array $params = []): Collection` -Eine einzelne Zeile als Collection (Array-/Objektzugriff) abrufen: +Holen Sie eine einzelne Zeile als Collection (Array/Objekt-Zugriff): ```php $user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); @@ -79,7 +83,7 @@ echo $user->name; `function fetchAll(string $sql, array $params = []): array` -Alle Zeilen als Array von Collections abrufen: +Holen Sie alle Zeilen als Array von Collections: ```php $users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); @@ -92,7 +96,7 @@ foreach ($users as $user) { ### Verwendung von `IN()`-Platzhaltern -Sie können einen einzelnen `?`-Platzhalter in einer `IN()`-Klausel verwenden und ein Array oder einen komma-getrennten String übergeben: +Sie können ein einzelnes `?` in einer `IN()`-Klausel verwenden und ein Array oder einen komma-separierten String übergeben: ```php $ids = [1, 2, 3]; @@ -103,9 +107,9 @@ $users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", ['1,2,3'] ## Fortgeschrittene Verwendung -### Abfrageprotokollierung & APM +### Query-Logging & APM -Wenn Sie die Abfrageleistung verfolgen möchten, aktivieren Sie die APM-Überwachung bei der Registrierung: +Wenn Sie die Query-Leistung verfolgen möchten, aktivieren Sie das APM-Tracking bei der Registrierung: ```php Flight::register('db', \flight\database\PdoWrapper::class, [ @@ -113,13 +117,13 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ ]); ``` -Nach dem Ausführen von Abfragen können Sie sie manuell protokollieren, aber das APM protokolliert sie automatisch, wenn es aktiviert ist: +Nach dem Ausführen von Abfragen können Sie sie manuell loggen, aber das APM loggt sie automatisch, wenn aktiviert: ```php Flight::db()->logQueries(); ``` -Dies löst ein Ereignis (`flight.db.queries`) mit Verbindungs- und Abfragemetriken aus, das Sie mit dem Ereignissystem von Flight abhören können. +Dies löst ein Event (`flight.db.queries`) mit Verbindungs- und Query-Metriken aus, das Sie mit Flights Event-System abhören können. ### Vollständiges Beispiel @@ -162,14 +166,14 @@ Flight::route('/users', function () { ## Siehe auch -- [Collections](/learn/collections) - Erfahren Sie, wie Sie die Collection-Klasse für einen einfachen Datenzugriff verwenden. +- [Collections](/learn/collections) - Lernen Sie, wie Sie die Collection-Klasse für einfachen Datenzugriff verwenden. ## Fehlerbehebung - Wenn Sie einen Fehler bezüglich der Datenbankverbindung erhalten, überprüfen Sie Ihre DSN, Benutzername, Passwort und Optionen. - Alle Zeilen werden als Collections zurückgegeben – wenn Sie ein einfaches Array benötigen, verwenden Sie `$collection->getData()`. -- Für `IN (?)`-Abfragen stellen Sie sicher, dass Sie ein Array oder einen komma-getrennten String übergeben. +- Für `IN (?)`-Abfragen stellen Sie sicher, dass Sie ein Array oder einen komma-separierten String übergeben. ## Änderungsprotokoll -- v3.2.0 - Erste Veröffentlichung von PdoWrapper mit grundlegenden Abfrage- und Abrufmethoden. \ No newline at end of file +- v3.2.0 - Erste Veröffentlichung von PdoWrapper mit grundlegenden Query- und Fetch-Methoden. \ No newline at end of file diff --git a/content/v3/de/learn/simple_pdo.md b/content/v3/de/learn/simple_pdo.md new file mode 100644 index 00000000..b3ac2be7 --- /dev/null +++ b/content/v3/de/learn/simple_pdo.md @@ -0,0 +1,320 @@ +# SimplePdo PDO-Hilfsklasse + +## Überblick + +Die `SimplePdo`-Klasse in Flight ist eine moderne, funktionsreiche Hilfsklasse für die Arbeit mit Datenbanken unter Verwendung von PDO. Sie erweitert `PdoWrapper` und fügt bequeme Hilfsmethoden für gängige Datenbankoperationen wie `insert()`, `update()`, `delete()` und Transaktionen hinzu. Sie vereinfacht Datenbankaufgaben, gibt Ergebnisse als [Collections](/learn/collections) zurück für einfachen Zugriff und unterstützt Abfrageprotokollierung und Anwendungsleistungsüberwachung (APM) für fortgeschrittene Anwendungsfälle. + +## Verständnis + +Die `SimplePdo`-Klasse ist so konzipiert, dass die Arbeit mit Datenbanken in PHP viel einfacher wird. Statt mit vorbereiteten Anweisungen, Abrufmodi und ausführlichen SQL-Operationen zu jonglieren, erhalten Sie saubere, einfache Methoden für gängige Aufgaben. Jede Zeile wird als Collection zurückgegeben, sodass Sie sowohl Array-Notation (`$row['name']`) als auch Objekt-Notation (`$row->name`) verwenden können. + +Diese Klasse ist eine Übersetzung von `PdoWrapper`, was bedeutet, dass sie alle Funktionen von `PdoWrapper` plus zusätzliche Hilfsmethoden enthält, die Ihren Code sauberer und wartbarer machen. Wenn Sie derzeit `PdoWrapper` verwenden, ist das Upgrade auf `SimplePdo` unkompliziert, da es `PdoWrapper` erweitert. + +Sie können `SimplePdo` als geteilten Dienst in Flight registrieren und es dann überall in Ihrer App über `Flight::db()` verwenden. + +## Grundlegende Verwendung + +### Registrierung von SimplePdo + +Registrieren Sie zuerst die `SimplePdo`-Klasse bei Flight: + +```php +Flight::register('db', \flight\database\SimplePdo::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 + ] +]); +``` + +> **HINWEIS** +> +> Wenn Sie `PDO::ATTR_DEFAULT_FETCH_MODE` nicht angeben, setzt `SimplePdo` es automatisch auf `PDO::FETCH_ASSOC` für Sie. + +Nun können Sie `Flight::db()` überall verwenden, um Ihre Datenbankverbindung zu erhalten. + +### Ausführen von Abfragen + +#### `runQuery()` + +`function runQuery(string $sql, array $params = []): PDOStatement` + +Verwenden Sie dies für INSERTs, UPDATEs oder wenn Sie Ergebnisse manuell abrufen möchten: + +```php +$db = Flight::db(); +$statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']); +while ($row = $statement->fetch()) { + // $row is an array +} +``` + +Sie können es auch für Schreibvorgänge verwenden: + +```php +$db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); +$db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]); +``` + +#### `fetchField()` + +`function fetchField(string $sql, array $params = []): mixed` + +Einen einzelnen Wert aus der Datenbank abrufen: + +```php +$count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']); +``` + +#### `fetchRow()` + +`function fetchRow(string $sql, array $params = []): ?Collection` + +Eine einzelne Zeile als Collection (Array-/Objektzugriff) abrufen: + +```php +$user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); +echo $user['name']; +// or +echo $user->name; +``` + +> **TIP** +> +> `SimplePdo` fügt automatisch `LIMIT 1` zu `fetchRow()`-Abfragen hinzu, falls es noch nicht vorhanden ist, was Ihre Abfragen effizienter macht. + +#### `fetchAll()` + +`function fetchAll(string $sql, array $params = []): array` + +Alle Zeilen als Array von Collections abrufen: + +```php +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); +foreach ($users as $user) { + echo $user['name']; + // or + echo $user->name; +} +``` + +#### `fetchColumn()` + +`function fetchColumn(string $sql, array $params = []): array` + +Eine einzelne Spalte als Array abrufen: + +```php +$ids = Flight::db()->fetchColumn("SELECT id FROM users WHERE active = ?", [1]); +// Returns: [1, 2, 3, 4, 5] +``` + +#### `fetchPairs()` + +`function fetchPairs(string $sql, array $params = []): array` + +Ergebnisse als Schlüssel-Wert-Paare abrufen (erste Spalte als Schlüssel, zweite als Wert): + +```php +$userNames = Flight::db()->fetchPairs("SELECT id, name FROM users"); +// Returns: [1 => 'John', 2 => 'Jane', 3 => 'Bob'] +``` + +### Verwendung von `IN()`-Platzhaltern + +Sie können einen einzelnen `?` in einer `IN()`-Klausel verwenden und ein Array übergeben: + +```php +$ids = [1, 2, 3]; +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); +``` + +## Hilfsmethoden + +Einer der Hauptvorteile von `SimplePdo` gegenüber `PdoWrapper` ist die Hinzufügung bequemer Hilfsmethoden für gängige Datenbankoperationen. + +### `insert()` + +`function insert(string $table, array $data): string` + +Eine oder mehrere Zeilen einfügen und die letzte Einfüge-ID zurückgeben. + +**Einzelner Einfügevorgang:** + +```php +$id = Flight::db()->insert('users', [ + 'name' => 'John', + 'email' => 'john@example.com' +]); +``` + +**Massen-Einfügevorgang:** + +```php +$id = Flight::db()->insert('users', [ + ['name' => 'John', 'email' => 'john@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'], +]); +``` + +### `update()` + +`function update(string $table, array $data, string $where, array $whereParams = []): int` + +Zeilen aktualisieren und die Anzahl der betroffenen Zeilen zurückgeben: + +```php +$affected = Flight::db()->update( + 'users', + ['name' => 'Jane', 'email' => 'jane@example.com'], + 'id = ?', + [1] +); +``` + +> **HINWEIS** +> +> SQLite's `rowCount()` gibt die Anzahl der Zeilen zurück, in denen Daten tatsächlich geändert wurden. Wenn Sie eine Zeile mit denselben Werten aktualisieren, die sie bereits hat, gibt `rowCount()` 0 zurück. Dies unterscheidet sich vom Verhalten von MySQL bei der Verwendung von `PDO::MYSQL_ATTR_FOUND_ROWS`. + +### `delete()` + +`function delete(string $table, string $where, array $whereParams = []): int` + +Zeilen löschen und die Anzahl der gelöschten Zeilen zurückgeben: + +```php +$deleted = Flight::db()->delete('users', 'id = ?', [1]); +``` + +### `transaction()` + +`function transaction(callable $callback): mixed` + +Einen Callback innerhalb einer Transaktion ausführen. Die Transaktion wird automatisch bei Erfolg committet oder bei Fehler zurückgerollt: + +```php +$result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John']); + $db->insert('logs', ['action' => 'user_created']); + return $db->lastInsertId(); +}); +``` + +Wenn innerhalb des Callbacks eine Ausnahme geworfen wird, wird die Transaktion automatisch zurückgerollt und die Ausnahme erneut geworfen. + +## Fortgeschrittene Verwendung + +### Abfrageprotokollierung & APM + +Wenn Sie die Abfrageleistung verfolgen möchten, aktivieren Sie die APM-Verfolgung bei der Registrierung: + +```php +Flight::register('db', \flight\database\SimplePdo::class, [ + 'mysql:host=localhost;dbname=cool_db_name', + 'user', + 'pass', + [/* PDO options */], + [ + 'trackApmQueries' => true, + 'maxQueryMetrics' => 1000 + ] +]); +``` + +Nach dem Ausführen von Abfragen können Sie sie manuell protokollieren, aber das APM protokolliert sie automatisch, wenn aktiviert: + +```php +Flight::db()->logQueries(); +``` + +Dies löst ein Ereignis (`flight.db.queries`) mit Verbindungs- und Abfragemetriken aus, das Sie mit Flights Ereignissystem abhören können. + +### Vollständiges Beispiel + +```php +Flight::route('/users', function () { + // Get all users + $users = Flight::db()->fetchAll('SELECT * FROM users'); + + // Stream all users + $statement = Flight::db()->runQuery('SELECT * FROM users'); + while ($user = $statement->fetch()) { + echo $user['name']; + } + + // Get a single user + $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); + + // Get a single value + $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); + + // Get a single column + $ids = Flight::db()->fetchColumn('SELECT id FROM users'); + + // Get key-value pairs + $userNames = Flight::db()->fetchPairs('SELECT id, name FROM users'); + + // Special IN() syntax + $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); + + // Insert a new user + $id = Flight::db()->insert('users', [ + 'name' => 'Bob', + 'email' => 'bob@example.com' + ]); + + // Bulk insert users + Flight::db()->insert('users', [ + ['name' => 'Bob', 'email' => 'bob@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'] + ]); + + // Update a user + $affected = Flight::db()->update('users', ['name' => 'Bob'], 'id = ?', [123]); + + // Delete a user + $deleted = Flight::db()->delete('users', 'id = ?', [123]); + + // Use a transaction + $result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John', 'email' => 'john@example.com']); + $db->insert('audit_log', ['action' => 'user_created']); + return $db->lastInsertId(); + }); +}); +``` + +## Migration von PdoWrapper + +Wenn Sie derzeit `PdoWrapper` verwenden, ist die Migration zu `SimplePdo` unkompliziert: + +1. **Aktualisieren Sie Ihre Registrierung:** + ```php + // Old + Flight::register('db', \flight\database\PdoWrapper::class, [ /* ... */ ]); + + // New + Flight::register('db', \flight\database\SimplePdo::class, [ /* ... */ ]); + ``` + +2. **Alle bestehenden `PdoWrapper`-Methoden funktionieren in `SimplePdo`** - Es gibt keine Breaking Changes. Ihr bestehender Code wird weiterhin funktionieren. + +3. **Optional die neuen Hilfsmethoden verwenden** - Beginnen Sie mit `insert()`, `update()`, `delete()` und `transaction()`, um Ihren Code zu vereinfachen. + +## Siehe auch + +- [Collections](/learn/collections) - Erfahren Sie, wie Sie die Collection-Klasse für einfachen Datenzugriff verwenden. +- [PdoWrapper](/learn/pdo-wrapper) - Die veraltete PDO-Hilfsklasse (deprecated). + +## Fehlerbehebung + +- Wenn Sie einen Fehler bezüglich der Datenbankverbindung erhalten, überprüfen Sie Ihre DSN, Benutzername, Passwort und Optionen. +- Alle Zeilen werden als Collections zurückgegeben – wenn Sie ein einfaches Array benötigen, verwenden Sie `$collection->getData()`. +- Für `IN (?)`-Abfragen stellen Sie sicher, dass Sie ein Array übergeben. +- Wenn Sie Speicherprobleme mit der Abfrageprotokollierung in lang laufenden Prozessen haben, passen Sie die `maxQueryMetrics`-Option an. + +## Changelog + +- v3.18.0 - Erste Veröffentlichung von SimplePdo mit Hilfsmethoden für insert, update, delete und Transaktionen. \ No newline at end of file diff --git a/content/v3/en/awesome-plugins/awesome_plugins.md b/content/v3/en/awesome-plugins/awesome_plugins.md index 8756e026..63a24edc 100644 --- a/content/v3/en/awesome-plugins/awesome_plugins.md +++ b/content/v3/en/awesome-plugins/awesome_plugins.md @@ -61,7 +61,8 @@ Debugging is crucial when you are developing in your local environment. There ar Databases are the core to most applications. This is how you store and retrieve data. Some database libraries are simply wrappers to write queries and some are full fledged ORMs. -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Official Flight PDO Wrapper that's part of the core. This is a simple wrapper to help simplify the process of writing queries and executing them. It is not an ORM. +- official [flightphp/core SimplePdo](/learn/simple-pdo) - Official Flight PDO Helper that's part of the core. This is a modern wrapper with convenient helper methods like `insert()`, `update()`, `delete()`, and `transaction()` to simplify database operations. All results are returned as Collections for flexible array/object access. Not an ORM, just a better way to work with PDO. +- deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Official Flight PDO Wrapper that's part of the core (deprecated as of v3.18.0). Use SimplePdo instead. - official [flightphp/active-record](/awesome-plugins/active-record) - Official Flight ActiveRecord ORM/Mapper. Great little library for easily retrieving and storing data in your database. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin to keep track of all database changes for your project. diff --git a/content/v3/en/learn/learn.md b/content/v3/en/learn/learn.md index 75576a55..a61f5c0b 100644 --- a/content/v3/en/learn/learn.md +++ b/content/v3/en/learn/learn.md @@ -65,9 +65,13 @@ Collections are used to hold data and be accessible as an array or as an object This has a few simple functions to make encoding and decoding your JSON consistent. -### [PDO Wrapper](/learn/pdo-wrapper) +### [SimplePdo](/learn/simple-pdo) -PDO at times can add more headache than necessary. This simple wrapper class can make it significantly easier to interact with your database. +PDO at times can add more headache than necessary. SimplePdo is a modern PDO helper class with convenient methods like `insert()`, `update()`, `delete()`, and `transaction()` to make database operations much easier. + +### [PdoWrapper](/learn/pdo-wrapper) (Deprecated) + +The original PDO wrapper is deprecated as of v3.18.0. Please use [SimplePdo](/learn/simple-pdo) instead. ### [Uploaded File Handler](/learn/uploaded-file) diff --git a/content/v3/en/learn/pdo_wrapper.md b/content/v3/en/learn/pdo_wrapper.md index af16812c..92783918 100644 --- a/content/v3/en/learn/pdo_wrapper.md +++ b/content/v3/en/learn/pdo_wrapper.md @@ -1,5 +1,9 @@ # PdoWrapper PDO Helper Class +> **WARNING** +> +> **Deprecated:** `PdoWrapper` is deprecated as of Flight v3.18.0. It will not be removed in a future version, but will be maintained for backward compatibility. Please use [SimplePdo](/learn/simple-pdo) instead, which offers the same functionality plus additional helper methods for common database operations. + ## Overview The `PdoWrapper` class in Flight is a friendly helper for working with databases using PDO. It simplifies common database tasks, adds some handy methods for fetching results, and returns results as [Collections](/learn/collections) for easy access. It also supports query logging and application performance monitoring (APM) for advanced use cases. diff --git a/content/v3/en/learn/simple_pdo.md b/content/v3/en/learn/simple_pdo.md new file mode 100644 index 00000000..7bc73903 --- /dev/null +++ b/content/v3/en/learn/simple_pdo.md @@ -0,0 +1,320 @@ +# SimplePdo PDO Helper Class + +## Overview + +The `SimplePdo` class in Flight is a modern, feature-rich helper for working with databases using PDO. It extends `PdoWrapper` and adds convenient helper methods for common database operations like `insert()`, `update()`, `delete()`, and transactions. It simplifies database tasks, returns results as [Collections](/learn/collections) for easy access, and supports query logging and application performance monitoring (APM) for advanced use cases. + +## Understanding + +The `SimplePdo` class is designed to make working with databases in PHP much easier. Instead of juggling prepared statements, fetch modes, and verbose SQL operations, you get clean, simple methods for common tasks. Every row is returned as a Collection, so you can use both array notation (`$row['name']`) and object notation (`$row->name`). + +This class is a superset of `PdoWrapper`, meaning it includes all the functionality of `PdoWrapper` plus additional helper methods that make your code cleaner and more maintainable. If you're currently using `PdoWrapper`, upgrading to `SimplePdo` is straightforward since it extends `PdoWrapper`. + +You can register `SimplePdo` as a shared service in Flight, and then use it anywhere in your app via `Flight::db()`. + +## Basic Usage + +### Registering SimplePdo + +First, register the `SimplePdo` class with Flight: + +```php +Flight::register('db', \flight\database\SimplePdo::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 + ] +]); +``` + +> **NOTE** +> +> If you don't specify `PDO::ATTR_DEFAULT_FETCH_MODE`, `SimplePdo` will automatically set it to `PDO::FETCH_ASSOC` for you. + +Now you can use `Flight::db()` anywhere to get your database connection. + +### Running Queries + +#### `runQuery()` + +`function runQuery(string $sql, array $params = []): PDOStatement` + +Use this for INSERTs, UPDATEs, or when you want to fetch results manually: + +```php +$db = Flight::db(); +$statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']); +while ($row = $statement->fetch()) { + // $row is an array +} +``` + +You can also use it for writes: + +```php +$db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); +$db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]); +``` + +#### `fetchField()` + +`function fetchField(string $sql, array $params = []): mixed` + +Get a single value from the database: + +```php +$count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']); +``` + +#### `fetchRow()` + +`function fetchRow(string $sql, array $params = []): ?Collection` + +Get a single row as a Collection (array/object access): + +```php +$user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); +echo $user['name']; +// or +echo $user->name; +``` + +> **TIP** +> +> `SimplePdo` automatically adds `LIMIT 1` to `fetchRow()` queries if it's not already present, making your queries more efficient. + +#### `fetchAll()` + +`function fetchAll(string $sql, array $params = []): array` + +Get all rows as an array of Collections: + +```php +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); +foreach ($users as $user) { + echo $user['name']; + // or + echo $user->name; +} +``` + +#### `fetchColumn()` + +`function fetchColumn(string $sql, array $params = []): array` + +Fetch a single column as an array: + +```php +$ids = Flight::db()->fetchColumn("SELECT id FROM users WHERE active = ?", [1]); +// Returns: [1, 2, 3, 4, 5] +``` + +#### `fetchPairs()` + +`function fetchPairs(string $sql, array $params = []): array` + +Fetch results as key-value pairs (first column as key, second as value): + +```php +$userNames = Flight::db()->fetchPairs("SELECT id, name FROM users"); +// Returns: [1 => 'John', 2 => 'Jane', 3 => 'Bob'] +``` + +### Using `IN()` Placeholders + +You can use a single `?` in an `IN()` clause and pass an array: + +```php +$ids = [1, 2, 3]; +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); +``` + +## Helper Methods + +One of the main advantages of `SimplePdo` over `PdoWrapper` is the addition of convenient helper methods for common database operations. + +### `insert()` + +`function insert(string $table, array $data): string` + +Insert one or more rows and return the last insert ID. + +**Single insert:** + +```php +$id = Flight::db()->insert('users', [ + 'name' => 'John', + 'email' => 'john@example.com' +]); +``` + +**Bulk insert:** + +```php +$id = Flight::db()->insert('users', [ + ['name' => 'John', 'email' => 'john@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'], +]); +``` + +### `update()` + +`function update(string $table, array $data, string $where, array $whereParams = []): int` + +Update rows and return the number of affected rows: + +```php +$affected = Flight::db()->update( + 'users', + ['name' => 'Jane', 'email' => 'jane@example.com'], + 'id = ?', + [1] +); +``` + +> **NOTE** +> +> SQLite's `rowCount()` returns the number of rows where data actually changed. If you update a row with the same values it already has, `rowCount()` will return 0. This differs from MySQL's behavior when using `PDO::MYSQL_ATTR_FOUND_ROWS`. + +### `delete()` + +`function delete(string $table, string $where, array $whereParams = []): int` + +Delete rows and return the number of deleted rows: + +```php +$deleted = Flight::db()->delete('users', 'id = ?', [1]); +``` + +### `transaction()` + +`function transaction(callable $callback): mixed` + +Execute a callback within a transaction. The transaction automatically commits on success or rolls back on error: + +```php +$result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John']); + $db->insert('logs', ['action' => 'user_created']); + return $db->lastInsertId(); +}); +``` + +If any exception is thrown within the callback, the transaction is automatically rolled back and the exception is re-thrown. + +## Advanced Usage + +### Query Logging & APM + +If you want to track query performance, enable APM tracking when registering: + +```php +Flight::register('db', \flight\database\SimplePdo::class, [ + 'mysql:host=localhost;dbname=cool_db_name', + 'user', + 'pass', + [/* PDO options */], + [ + 'trackApmQueries' => true, + 'maxQueryMetrics' => 1000 + ] +]); +``` + +After running queries, you can log them manually, but the APM will log them automatically if enabled: + +```php +Flight::db()->logQueries(); +``` + +This will trigger an event (`flight.db.queries`) with connection and query metrics, which you can listen for using Flight's event system. + +### Full Example + +```php +Flight::route('/users', function () { + // Get all users + $users = Flight::db()->fetchAll('SELECT * FROM users'); + + // Stream all users + $statement = Flight::db()->runQuery('SELECT * FROM users'); + while ($user = $statement->fetch()) { + echo $user['name']; + } + + // Get a single user + $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); + + // Get a single value + $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); + + // Get a single column + $ids = Flight::db()->fetchColumn('SELECT id FROM users'); + + // Get key-value pairs + $userNames = Flight::db()->fetchPairs('SELECT id, name FROM users'); + + // Special IN() syntax + $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); + + // Insert a new user + $id = Flight::db()->insert('users', [ + 'name' => 'Bob', + 'email' => 'bob@example.com' + ]); + + // Bulk insert users + Flight::db()->insert('users', [ + ['name' => 'Bob', 'email' => 'bob@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'] + ]); + + // Update a user + $affected = Flight::db()->update('users', ['name' => 'Bob'], 'id = ?', [123]); + + // Delete a user + $deleted = Flight::db()->delete('users', 'id = ?', [123]); + + // Use a transaction + $result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John', 'email' => 'john@example.com']); + $db->insert('audit_log', ['action' => 'user_created']); + return $db->lastInsertId(); + }); +}); +``` + +## Migrating from PdoWrapper + +If you're currently using `PdoWrapper`, migrating to `SimplePdo` is straightforward: + +1. **Update your registration:** + ```php + // Old + Flight::register('db', \flight\database\PdoWrapper::class, [ /* ... */ ]); + + // New + Flight::register('db', \flight\database\SimplePdo::class, [ /* ... */ ]); + ``` + +2. **All existing `PdoWrapper` methods work in `SimplePdo`** - There are no breaking changes. Your existing code will continue to work. + +3. **Optionally use the new helper methods** - Start using `insert()`, `update()`, `delete()`, and `transaction()` to simplify your code. + +## See Also + +- [Collections](/learn/collections) - Learn how to use the Collection class for easy data access. +- [PdoWrapper](/learn/pdo-wrapper) - The legacy PDO helper class (deprecated). + +## Troubleshooting + +- If you get an error about database connection, check your DSN, username, password, and options. +- All rows are returned as Collections—if you need a plain array, use `$collection->getData()`. +- For `IN (?)` queries, make sure to pass an array. +- If you're experiencing memory issues with query logging in long-running processes, adjust the `maxQueryMetrics` option. + +## Changelog + +- v3.18.0 - Initial release of SimplePdo with helper methods for insert, update, delete, and transactions. diff --git a/content/v3/es/awesome-plugins/awesome_plugins.md b/content/v3/es/awesome-plugins/awesome_plugins.md index e5c9030a..c9791739 100644 --- a/content/v3/es/awesome-plugins/awesome_plugins.md +++ b/content/v3/es/awesome-plugins/awesome_plugins.md @@ -1,4 +1,4 @@ -# Plugins Geniales +# Plugins Impresionantes Flight es increíblemente extensible. Hay una serie de plugins que se pueden usar para agregar funcionalidad a tu aplicación Flight. Algunos son soportados oficialmente por el Equipo de Flight y otros son bibliotecas micro/lite para ayudarte a comenzar. @@ -6,7 +6,7 @@ Flight es increíblemente extensible. Hay una serie de plugins que se pueden usa La documentación de API es crucial para cualquier API. Ayuda a los desarrolladores a entender cómo interactuar con tu API y qué esperar a cambio. Hay un par de herramientas disponibles para ayudarte a generar documentación de API para tus Proyectos Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Publicación de blog escrita por Daniel Schreiber sobre cómo usar la Especificación OpenAPI con FlightPHP para construir tu API utilizando un enfoque API first. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Publicación de blog escrita por Daniel Schreiber sobre cómo usar la Especificación OpenAPI con FlightPHP para construir tu API utilizando un enfoque API-first. - [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI es una gran herramienta para ayudarte a generar documentación de API para tus proyectos Flight. Es muy fácil de usar y se puede personalizar para adaptarse a tus necesidades. Esta es la biblioteca PHP para ayudarte a generar la documentación Swagger. ## Monitoreo de Rendimiento de Aplicaciones (APM) @@ -22,48 +22,49 @@ Flight ya es un framework rápido, pero agregarle un motor turbo lo hace todo m ## Autorización/Permisos -La autorización y los permisos son cruciales para cualquier aplicación que requiera controles en su lugar para quién puede acceder a qué. +La autorización y los permisos son cruciales para cualquier aplicación que requiera controles para determinar quién puede acceder a qué. - oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca oficial de Permisos de Flight. Esta biblioteca es una forma simple de agregar permisos a nivel de usuario y aplicación a tu aplicación. ## Autenticación -La autenticación es esencial para las aplicaciones que necesitan verificar la identidad del usuario y asegurar endpoints de API. +La autenticación es esencial para aplicaciones que necesitan verificar la identidad del usuario y asegurar endpoints de API. - [firebase/php-jwt](/awesome-plugins/jwt) - Biblioteca de JSON Web Token (JWT) para PHP. Una forma simple y segura de implementar autenticación basada en tokens en tus aplicaciones Flight. Perfecta para autenticación de API sin estado, protección de rutas con middleware e implementación de flujos de autorización estilo OAuth. ## Caché -El caché es una gran manera de acelerar tu aplicación. Hay una serie de bibliotecas de caché que se pueden usar con Flight. +El caché es una gran forma de acelerar tu aplicación. Hay una serie de bibliotecas de caché que se pueden usar con Flight. - oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Clase ligera, simple y standalone de caché en archivo PHP ## CLI -Las aplicaciones CLI son una gran manera de interactuar con tu aplicación. Puedes usarlas para generar controladores, mostrar todas las rutas y más. +Las aplicaciones CLI son una gran forma de interactuar con tu aplicación. Puedes usarlas para generar controladores, mostrar todas las rutas y más. - oficial [flightphp/runway](/awesome-plugins/runway) - Runway es una aplicación CLI que te ayuda a gestionar tus aplicaciones Flight. ## Cookies -Las cookies son una gran manera de almacenar pequeños fragmentos de datos en el lado del cliente. Se pueden usar para almacenar preferencias de usuario, configuraciones de aplicación y más. +Las cookies son una gran forma de almacenar pequeños bits de datos en el lado del cliente. Se pueden usar para almacenar preferencias de usuario, configuraciones de aplicación y más. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie es una biblioteca PHP que proporciona una forma simple y efectiva de gestionar cookies. ## Depuración -La depuración es crucial cuando estás desarrollando en tu entorno local. Hay algunos plugins que pueden elevar tu experiencia de depuración. +La depuración es crucial cuando estás desarrollando en tu entorno local. Hay unos pocos plugins que pueden elevar tu experiencia de depuración. - [tracy/tracy](/awesome-plugins/tracy) - Este es un manejador de errores completo que se puede usar con Flight. Tiene una serie de paneles que pueden ayudarte a depurar tu aplicación. También es muy fácil de extender y agregar tus propios paneles. -- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado con el manejador de errores [Tracy](/awesome-plugins/tracy), este plugin agrega algunos paneles extra para ayudar con la depuración específicamente para proyectos Flight. +- oficial [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Usado con el manejador de errores [Tracy](/awesome-plugins/tracy), este plugin agrega unos pocos paneles extra para ayudar con la depuración específicamente para proyectos Flight. ## Bases de Datos -Las bases de datos son el núcleo de la mayoría de las aplicaciones. Así es como almacenas y recuperas datos. Algunas bibliotecas de base de datos son simplemente envoltorios para escribir consultas y algunas son ORMs completos. +Las bases de datos son el núcleo de la mayoría de las aplicaciones. Así es como almacenas y recuperas datos. Algunas bibliotecas de bases de datos son simplemente wrappers para escribir consultas y otras son ORMs completos. -- oficial [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Envoltorio oficial de PDO de Flight que forma parte del núcleo. Este es un envoltorio simple para ayudar a simplificar el proceso de escribir consultas y ejecutarlas. No es un ORM. +- oficial [flightphp/core SimplePdo](/learn/simple-pdo) - Ayudante oficial de PDO de Flight que forma parte del núcleo. Este es un wrapper moderno con métodos de ayuda convenientes como `insert()`, `update()`, `delete()` y `transaction()` para simplificar las operaciones de base de datos. Todos los resultados se devuelven como Collections para un acceso flexible a arrays/objetos. No es un ORM, solo una mejor forma de trabajar con PDO. +- deprecado [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper oficial de PDO de Flight que forma parte del núcleo (deprecado a partir de v3.18.0). Usa SimplePdo en su lugar. - oficial [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper oficial de ActiveRecord de Flight. Gran biblioteca pequeña para recuperar y almacenar datos fácilmente en tu base de datos. -- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para mantener un registro de todos los cambios de base de datos para tu proyecto. +- [byjg/php-migration](/awesome-plugins/migrations) - Plugin para rastrear todos los cambios de base de datos para tu proyecto. ## Encriptación @@ -71,9 +72,9 @@ La encriptación es crucial para cualquier aplicación que almacene datos sensib - [defuse/php-encryption](/awesome-plugins/php-encryption) - Esta es una biblioteca que se puede usar para encriptar y desencriptar datos. Ponerse en marcha es bastante simple para comenzar a encriptar y desencriptar datos. -## Cola de Trabajos +## Cola de Tareas -Las colas de trabajos son realmente útiles para procesar tareas de manera asíncrona. Esto puede ser enviar correos electrónicos, procesar imágenes o cualquier cosa que no necesite hacerse en tiempo real. +Las colas de tareas son realmente útiles para procesar tareas de manera asíncrona. Esto puede ser enviar correos electrónicos, procesar imágenes o cualquier cosa que no necesite hacerse en tiempo real. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue es una biblioteca que se puede usar para procesar trabajos de manera asíncrona. Se puede usar con beanstalkd, MySQL/MariaDB, SQLite y PostgreSQL. @@ -82,11 +83,11 @@ Las colas de trabajos son realmente útiles para procesar tareas de manera asín Las sesiones no son realmente útiles para las API, pero para construir una aplicación web, las sesiones pueden ser cruciales para mantener el estado e información de inicio de sesión. - oficial [flightphp/session](/awesome-plugins/session) - Biblioteca oficial de Sesión de Flight. Esta es una biblioteca de sesión simple que se puede usar para almacenar y recuperar datos de sesión. Usa el manejo de sesiones integrado de PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - Gestor de Sesiones PHP (no bloqueante, flash, segmento, encriptación de sesión). Usa PHP open_ssl para encriptación/desencriptación opcional de datos de sesión. +- [Ghostff/Session](/awesome-plugins/ghost-session) - Administrador de Sesiones PHP (no bloqueante, flash, segmento, encriptación de sesión). Usa PHP open_ssl para encriptación/desencriptación opcional de datos de sesión. ## Plantillas -La plantillas son el núcleo de cualquier aplicación web con una UI. Hay una serie de motores de plantillas que se pueden usar con Flight. +La plantillación es el núcleo de cualquier aplicación web con una UI. Hay una serie de motores de plantillas que se pueden usar con Flight. - deprecado [flightphp/core View](/learn#views) - Este es un motor de plantillas muy básico que forma parte del núcleo. No se recomienda usarlo si tienes más de un par de páginas en tu proyecto. - [latte/latte](/awesome-plugins/latte) - Latte es un motor de plantillas completo que es muy fácil de usar y se siente más cercano a la sintaxis PHP que Twig o Smarty. También es muy fácil de extender y agregar tus propios filtros y funciones. @@ -98,6 +99,6 @@ La plantillas son el núcleo de cualquier aplicación web con una UI. Hay una se - [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Este plugin de WordPress te permite ejecutar Flight junto a WordPress. Es perfecto para agregar APIs personalizadas, microservicios o incluso aplicaciones completas a tu sitio WordPress usando el framework Flight. ¡Súper útil si quieres lo mejor de ambos mundos! -## Contribuyendo +## Contribución ¿Tienes un plugin que te gustaría compartir? ¡Envía una solicitud de pull para agregarlo a la lista! \ No newline at end of file diff --git a/content/v3/es/awesome-plugins/jwt.md b/content/v3/es/awesome-plugins/jwt.md index 78b3dc65..01be1a39 100644 --- a/content/v3/es/awesome-plugins/jwt.md +++ b/content/v3/es/awesome-plugins/jwt.md @@ -1,8 +1,8 @@ -# Firebase JWT - Autenticación con JSON Web Token para Flight +# Firebase JWT - Autenticación con JSON Web Token -JWT (JSON Web Tokens) son una forma compacta y segura para URLs de representar reclamaciones entre tu aplicación y un cliente. ¡Son perfectos para la autenticación de API sin estado, sin necesidad de almacenamiento de sesiones en el servidor! Esta guía te muestra cómo integrar [Firebase JWT](https://github.com/firebase/php-jwt) con Flight para una autenticación segura basada en tokens. +JWT (JSON Web Tokens) son una forma compacta y segura para URLs de representar afirmaciones entre tu aplicación y un cliente. ¡Son perfectos para la autenticación de API sin estado, sin necesidad de almacenamiento de sesiones en el servidor! Esta guía te muestra cómo integrar [Firebase JWT](https://github.com/firebase/php-jwt) con Flight para una autenticación segura basada en tokens. -Visita el [repositorio de Github](https://github.com/firebase/php-jwt) para documentación completa y detalles. +Visita el [repositorio de Github](https://github.com/firebase/php-jwt) para obtener la documentación completa y detalles. ## ¿Qué es JWT? @@ -17,7 +17,7 @@ Ejemplo de JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (parece gibberish, ¡pero es data e - **Sin estado**: No se necesita almacenamiento de sesiones en el servidor, perfecto para microservicios y APIs - **Escalable**: Funciona genial con balanceadores de carga ya que no hay requisito de afinidad de sesión -- **Multi-dominio**: Se puede usar a través de diferentes dominios y servicios +- **Multi-dominio**: Puede usarse a través de diferentes dominios y servicios - **Amigable con móviles**: Genial para apps móviles donde las cookies pueden no funcionar bien - **Estandarizado**: Enfoque estándar de la industria (RFC 7519) @@ -63,7 +63,7 @@ try { ## Middleware JWT para Flight (Enfoque recomendado) -La forma más común y útil de usar JWT con Flight es como **middleware** para proteger tus rutas de API. Aquí hay un ejemplo completo, listo para producción: +La forma más común y útil de usar JWT con Flight es como **middleware** para proteger tus rutas de API. Aquí hay un ejemplo completo y listo para producción: ### Paso 1: Crear una clase de middleware JWT @@ -82,19 +82,19 @@ class JwtMiddleware { public function __construct(Engine $app) { $this->app = $app; - // Almacena tu clave secreta en app/config/config.php, ¡NO la hardcodees! + // Almacena tu clave secreta en app/config/config.php, ¡NO la codifiques de forma fija! $this->secretKey = $app->get('config')['jwt_secret']; } public function before(array $params) { $authHeader = $this->app->request()->getHeader('Authorization'); - // Verificar si existe el header de Authorization + // Verificar si existe el header de autorización if (empty($authHeader)) { $this->app->jsonHalt(['error' => 'No se proporcionó token de autorización'], 401); } - // Extraer token del formato "Bearer " + // Extraer el token del formato "Bearer " if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { $this->app->jsonHalt(['error' => 'Formato de autorización inválido. Usa: Bearer '], 401); } @@ -119,7 +119,7 @@ class JwtMiddleware { } ``` -### Paso 2: Registrar clave secreta JWT en tu configuración +### Paso 2: Registrar la clave secreta JWT en tu configuración ```php // app/config/config.php @@ -128,11 +128,11 @@ return [ ]; // app/config/bootstrap.php o index.php -// asegúrate de agregar esta línea si quieres exponer la config a la app +// asegúrate de agregar esta línea si quieres exponer la configuración a la app $app->set('config', $config); ``` -> **Nota de seguridad**: ¡Nunca hardcodees tu clave secreta! Usa variables de entorno en producción. +> **Nota de seguridad**: ¡Nunca codifiques de forma fija tu clave secreta! Usa variables de entorno en producción. ### Paso 3: Proteger tus rutas con middleware @@ -145,9 +145,9 @@ Flight::route('GET /api/user/profile', function() { 'username' => $user->username, 'role' => $user->role ]); -})->addMiddleware( JwtMiddleware::class); +})->addMiddleware(JwtMiddleware::class); -// Proteger un grupo entero de rutas (¡más común!) +// Proteger un grupo completo de rutas (¡más común!) Flight::group('/api', function() { Flight::route('GET /users', function() { /* ... */ }); Flight::route('GET /posts', function() { /* ... */ }); @@ -156,7 +156,7 @@ Flight::group('/api', function() { }, [ JwtMiddleware::class ]); // ¡Todas las rutas en este grupo están protegidas! ``` -Para más detalles sobre middleware, ve la [documentación de middleware](/learn/middleware). +Para más detalles sobre middleware, consulta la [documentación de middleware](/learn/middleware). ## Casos de uso comunes @@ -197,7 +197,7 @@ Flight::route('POST /api/login', function() { }); function validateUserCredentials($username, $password) { - // Tu búsqueda en base de datos y verificación de contraseña aquí + // Tu búsqueda en la base de datos y verificación de contraseña aquí // Ejemplo: $db = Flight::db(); $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); @@ -213,9 +213,9 @@ function validateUserCredentials($username, $password) { } ``` -### 2. Flujo de actualización de token +### 2. Flujo de renovación de token -Implementa un sistema de token de actualización para sesiones de larga duración: +Implementa un sistema de token de renovación para sesiones de larga duración: ```php Flight::route('POST /api/login', function() { @@ -232,7 +232,7 @@ Flight::route('POST /api/login', function() { 'exp' => time() + (15 * 60) ], $secretKey, 'HS256'); - // Token de actualización de larga duración (7 días) + // Token de renovación de larga duración (7 días) $refreshToken = JWT::encode([ 'user_id' => $user->id, 'type' => 'refresh', @@ -254,7 +254,7 @@ Flight::route('POST /api/refresh', function() { try { $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); - // Verificar que sea un token de actualización + // Verificar que sea un token de renovación if ($decoded->type !== 'refresh') { Flight::jsonHalt(['error' => 'Tipo de token inválido'], 401); } @@ -274,7 +274,7 @@ Flight::route('POST /api/refresh', function() { ]); } catch (Exception $e) { - Flight::jsonHalt(['error' => 'Token de actualización inválido'], 401); + Flight::jsonHalt(['error' => 'Token de renovación inválido'], 401); } }); ``` @@ -363,7 +363,7 @@ echo $secretKey; // ¡Almacena esto en tu archivo .env! // JWT_REFRESH_SECRET=another-base64-encoded-secret-here // También puedes usar el archivo app/config/config.php para almacenar tus secretos -// solo asegúrate de que el archivo de config no se comprometa en control de versiones +// solo asegúrate de que el archivo de configuración no se comprometa en control de versiones // return [ // 'jwt_secret' => 'your-base64-encoded-secret-here', // 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', @@ -379,7 +379,7 @@ $secretKey = getenv('JWT_SECRET'); // Buena práctica: tokens de acceso de corta duración 'exp' => time() + (15 * 60) // 15 minutos -// Para tokens de actualización: expiración más larga +// Para tokens de renovación: expiración más larga 'exp' => time() + (7 * 24 * 60 * 60) // 7 días ``` @@ -387,9 +387,9 @@ $secretKey = getenv('JWT_SECRET'); Los JWT deben **siempre** transmitirse sobre HTTPS. ¡Nunca envíes tokens sobre HTTP plano en producción! -### 5. Valida las reclamaciones del token +### 5. Valida las afirmaciones del token -Siempre valida las reclamaciones que te importan: +Siempre valida las afirmaciones que te importan: ```php $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); @@ -397,7 +397,7 @@ $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); // La verificación de expiración se maneja automáticamente por la librería // Pero puedes agregar validaciones personalizadas: if ($decoded->iat > time()) { - throw new Exception('Token usado antes de ser emitido'); + throw new Exception('Token usado antes de que se emitiera'); } if (isset($decoded->nbf) && $decoded->nbf > time()) { @@ -405,7 +405,7 @@ if (isset($decoded->nbf) && $decoded->nbf > time()) { } ``` -### 6. Considera lista negra de tokens para logout +### 6. Considera la lista negra de tokens para logout Para seguridad extra, mantén una lista negra de tokens invalidados: @@ -474,9 +474,9 @@ $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); ## Solución de problemas ### Error "Token expirado" -La reclamación `exp` de tu token está en el pasado. Emite un nuevo token o implementa actualización de token. +La afirmación `exp` de tu token está en el pasado. Emite un nuevo token o implementa renovación de token. -### "Falla en verificación de firma" +### "Fallo en la verificación de firma" - Estás usando una clave secreta diferente para decodificar que la que usaste para codificar - El token ha sido manipulado - Desfase de reloj entre servidores (agrega un buffer de tolerancia) @@ -489,7 +489,7 @@ $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); ``` ### Token no se envía en solicitudes -Asegúrate de que tu cliente esté enviando el header `Authorization`: +Asegúrate de que tu cliente envíe el header `Authorization`: ```javascript // Ejemplo en JavaScript @@ -506,8 +506,8 @@ La librería Firebase JWT proporciona estos métodos principales: - `JWT::encode(array $payload, string $key, string $alg)`: Crea un JWT a partir de un payload - `JWT::decode(string $jwt, Key $key)`: Decodifica y verifica un JWT -- `JWT::urlsafeB64Encode(string $input)`: Codificación Base64 URL-segura -- `JWT::urlsafeB64Decode(string $input)`: Decodificación Base64 URL-segura +- `JWT::urlsafeB64Encode(string $input)`: Codificación Base64 segura para URL +- `JWT::urlsafeB64Decode(string $input)`: Decodificación Base64 segura para URL - `JWT::$leeway`: Propiedad estática para establecer tolerancia de tiempo para validación (en segundos) ## ¿Por qué usar esta librería? @@ -516,7 +516,7 @@ La librería Firebase JWT proporciona estos métodos principales: - **Mantenimiento activo**: Mantenida por el equipo de Google/Firebase - **Enfocada en seguridad**: Actualizaciones regulares y parches de seguridad - **API simple**: Fácil de entender e implementar -- **Bien documentada**: Documentación extensa y soporte de comunidad +- **Bien documentada**: Documentación extensa y soporte comunitario - **Flexible**: Soporta múltiples algoritmos y opciones configurables ## Ver también @@ -529,4 +529,4 @@ La librería Firebase JWT proporciona estos métodos principales: ## Licencia -La librería Firebase JWT está licenciada bajo la Licencia BSD 3-Clause. Ve el [repositorio de Github](https://github.com/firebase/php-jwt) para detalles. \ No newline at end of file +La librería Firebase JWT está licenciada bajo la Licencia BSD 3-Clause. Consulta el [repositorio de Github](https://github.com/firebase/php-jwt) para detalles. \ No newline at end of file diff --git a/content/v3/es/awesome-plugins/runway.md b/content/v3/es/awesome-plugins/runway.md index 966cc419..7d45a232 100644 --- a/content/v3/es/awesome-plugins/runway.md +++ b/content/v3/es/awesome-plugins/runway.md @@ -48,7 +48,7 @@ Puedes ver una lista de todos los comandos disponibles ejecutando el comando `ph php runway ``` -### Ayuda de Comandos +### Ayuda de Comando Para cualquier comando, puedes pasar la bandera `--help` para obtener más información sobre cómo usar el comando. @@ -74,7 +74,7 @@ Primero asegúrate de haber instalado el plugin [Active Record](/awesome-plugins php runway make:record users ``` -Si, por ejemplo, tienes la tabla `users` con el siguiente esquema: `id`, `name`, `email`, `created_at`, `updated_at`, se creará un archivo similar al siguiente en el archivo `app/records/UserRecord.php`: +Por ejemplo, si tienes la tabla `users` con el siguiente esquema: `id`, `name`, `email`, `created_at`, `updated_at`, se creará un archivo similar al siguiente en el archivo `app/records/UserRecord.php`: ```php $config Configuración de app/config/config.php + * @param array $config Config from app/config/config.php */ public function __construct(array $config) { - parent::__construct('make:example', 'Crear un ejemplo para la documentación', $config); - $this->argument('', 'El nombre del gif gracioso'); + parent::__construct('make:example', 'Create an example for the documentation', $config); + $this->argument('', 'The name of the funny gif'); } /** - * Ejecuta la función + * Executes the function * * @return void */ @@ -169,11 +169,11 @@ class ExampleCommand extends AbstractBaseCommand { $io = $this->app()->io(); - $io->info('Creando ejemplo...'); + $io->info('Creating example...'); - // Haz algo aquí + // Do something here - $io->ok('¡Ejemplo creado!'); + $io->ok('Example created!'); } } ``` @@ -186,7 +186,7 @@ Dado que la configuración se ha movido a `app/config/config.php` a partir de `v ### Migrar Configuración Antigua -Si tienes un archivo antiguo `.runway-config.json`, puedes migrarlo fácilmente a `app/config/config.php` con el siguiente comando: +Si tienes un archivo `.runway-config.json` antiguo, puedes migrarlo fácilmente a `app/config/config.php` con el siguiente comando: ```bash php runway config:migrate @@ -216,33 +216,33 @@ Si necesitas personalizar la configuración para Runway, puedes establecer estos [ - // Aquí es donde se encuentra el directorio de tu aplicación + // This is where your application directory is located 'app_root' => 'app/', - // Este es el directorio donde se encuentra tu archivo índice raíz + // This is the directory where your root index file is located 'index_root' => 'public/', - // Estos son los caminos a las raíces de otros proyectos + // These are the paths to the roots of other projects 'root_paths' => [ '/home/user/different-project', '/var/www/another-project' ], - // Los caminos base probablemente no necesiten configurarse, pero está aquí si lo quieres + // Base paths most likely don't need to be configured, but it's here if you want it 'base_paths' => [ - '/includes/libs/vendor', // si tienes un camino realmente único para tu directorio vendor o algo + '/includes/libs/vendor', // if you have a really unique path for your vendor directory or something ], - // Los caminos finales son ubicaciones dentro de un proyecto para buscar los archivos de comandos + // Final paths are locations within a project to search for the command files 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // Si quieres agregar el camino completo, adelante (absoluto o relativo a la raíz del proyecto) + // If you want to just add the full path, go right ahead (absolute or relative to project root) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -261,26 +261,26 @@ public function execute() { $io = $this->app()->io(); - // Acceder a la configuración + // Access configuration $app_root = $this->config['runway']['app_root']; - // Acceder a servicios como quizás una conexión a la base de datos + // Access services like maybe a database connection $database = $this->config['database'] // ... } ``` -## Envoltorios de Ayudante de IA +## Wrappers de Ayudante de IA -Runway tiene algunos envoltorios de ayudante que facilitan que la IA genere comandos. Puedes usar `addOption` y `addArgument` de una manera que se sienta similar a Symfony Console. Esto es útil si estás usando herramientas de IA para generar tus comandos. +Runway tiene algunos wrappers de ayudante que facilitan que la IA genere comandos. Puedes usar `addOption` y `addArgument` de una manera que se siente similar a Symfony Console. Esto es útil si estás usando herramientas de IA para generar tus comandos. ```php public function __construct(array $config) { - parent::__construct('make:example', 'Crear un ejemplo para la documentación', $config); + parent::__construct('make:example', 'Create an example for the documentation', $config); - // El argumento mode es nullable y por defecto completamente opcional - $this->addOption('name', 'El nombre del ejemplo', null); + // The mode argument is nullable and defaults to completely optional + $this->addOption('name', 'The name of the example', null); } ``` \ No newline at end of file diff --git a/content/v3/es/learn/autoloading.md b/content/v3/es/learn/autoloading.md index 0ffc0fc2..f6a1223e 100644 --- a/content/v3/es/learn/autoloading.md +++ b/content/v3/es/learn/autoloading.md @@ -1,21 +1,21 @@ -# Autocarga +# Autoloading -## Resumen +## Visión general -La autocarga es un concepto en PHP donde especificas un directorio o directorios para cargar clases. Esto es mucho más beneficioso que usar `require` o `include` para cargar clases. También es un requisito para usar paquetes de Composer. +El autoloading es un concepto en PHP donde especificas un directorio o directorios para cargar clases. Esto es mucho más beneficioso que usar `require` o `include` para cargar clases. También es un requisito para usar paquetes de Composer. ## Comprensión -Por defecto, cualquier clase de `Flight` se autocarga automáticamente para ti gracias a Composer. Sin embargo, si quieres autocargar tus propias clases, puedes usar el método `Flight::path()` para especificar un directorio desde el cual cargar clases. +Por defecto, cualquier clase de `Flight` se autoload para ti automáticamente gracias a Composer. Sin embargo, si quieres autoload tus propias clases, puedes usar el método `Flight::path()` para especificar un directorio para cargar clases. -Usar un autocargador puede ayudar a simplificar tu código de manera significativa. En lugar de tener archivos que comiencen con una multitud de declaraciones `include` o `require` al principio para capturar todas las clases que se usan en ese archivo, puedes en su lugar llamar dinámicamente a tus clases y se incluirán automáticamente. +Usar un autoloader puede ayudar a simplificar tu código de manera significativa. En lugar de tener archivos que comiencen con una multitud de declaraciones `include` o `require` al principio para capturar todas las clases que se usan en ese archivo, puedes en su lugar llamar dinámicamente a tus clases y se incluirán automáticamente. -## Uso Básico +## Uso básico Supongamos que tenemos un árbol de directorios como el siguiente: ```text -# Ruta de ejemplo +# Ejemplo de ruta /home/user/project/my-flight-project/ ├── app │ ├── cache @@ -30,9 +30,9 @@ Supongamos que tenemos un árbol de directorios como el siguiente: └── index.php ``` -Puede que hayas notado que esta es la misma estructura de archivos que el sitio de documentación. +Puede que hayas notado que esta es la misma estructura de archivos que este sitio de documentación. -Puedes especificar cada directorio desde el cual cargar de esta manera: +Puedes especificar cada directorio para cargar de esta manera: ```php @@ -40,7 +40,7 @@ Puedes especificar cada directorio desde el cual cargar de esta manera: * public/index.php */ -// Agregar una ruta al autocargador +// Agregar una ruta al autoloader Flight::path(__DIR__.'/../app/controllers/'); Flight::path(__DIR__.'/../app/utils/'); @@ -49,9 +49,9 @@ Flight::path(__DIR__.'/../app/utils/'); * app/controllers/MyController.php */ -// no se requiere nombres de espacio +// no se requiere namespacing -// Se recomienda que todas las clases autocargadas estén en Pascal Case (cada palabra capitalizada, sin espacios) +// Todas las clases autoloaded se recomiendan en Pascal Case (cada palabra capitalizada, sin espacios) class MyController { public function index() { @@ -60,9 +60,9 @@ class MyController { } ``` -## Espacios de Nombres +## Namespaces -Si tienes espacios de nombres, en realidad se vuelve muy fácil implementarlo. Debes usar el método `Flight::path()` para especificar el directorio raíz (no la raíz del documento o la carpeta `public/`) de tu aplicación. +Si tienes namespaces, en realidad se vuelve muy fácil implementarlo. Deberías usar el método `Flight::path()` para especificar el directorio raíz (no el document root o la carpeta `public/`) de tu aplicación. ```php @@ -70,7 +70,7 @@ Si tienes espacios de nombres, en realidad se vuelve muy fácil implementarlo. D * public/index.php */ -// Agregar una ruta al autocargador +// Agregar una ruta al autoloader Flight::path(__DIR__.'/../'); ``` @@ -81,13 +81,13 @@ Ahora es así como podría verse tu controlador. Mira el ejemplo a continuación * app/controllers/MyController.php */ -// los espacios de nombres son requeridos -// los espacios de nombres son los mismos que la estructura de directorios -// los espacios de nombres deben seguir el mismo caso que la estructura de directorios -// los espacios de nombres y directorios no pueden tener guiones bajos (a menos que Loader::setV2ClassLoading(false) esté configurado) +// los namespaces son requeridos +// los namespaces son los mismos que la estructura de directorios +// los namespaces deben seguir el mismo case que la estructura de directorios +// los namespaces y directorios no pueden tener guiones bajos (a menos que Loader::setV2ClassLoading(false) esté configurado) namespace app\controllers; -// Se recomienda que todas las clases autocargadas estén en Pascal Case (cada palabra capitalizada, sin espacios) +// Todas las clases autoloaded se recomiendan en Pascal Case (cada palabra capitalizada, sin espacios) // A partir de 3.7.2, puedes usar Pascal_Snake_Case para los nombres de tus clases ejecutando Loader::setV2ClassLoading(false); class MyController { @@ -97,7 +97,7 @@ class MyController { } ``` -Y si quisieras autocargar una clase en tu directorio utils, harías básicamente lo mismo: +Y si quisieras autoload una clase en tu directorio utils, harías básicamente lo mismo: ```php @@ -105,7 +105,7 @@ Y si quisieras autocargar una clase en tu directorio utils, harías básicamente * app/UTILS/ArrayHelperUtil.php */ -// el espacio de nombres debe coincidir con la estructura de directorios y el caso (nota que el directorio UTILS está en mayúsculas +// el namespace debe coincidir con la estructura de directorios y el case (nota que el directorio UTILS está en mayúsculas // como en el árbol de archivos arriba) namespace app\UTILS; @@ -117,7 +117,7 @@ class ArrayHelperUtil { } ``` -## Guiones Bajos en Nombres de Clases +## Guiones bajos en nombres de clases A partir de 3.7.2, puedes usar Pascal_Snake_Case para los nombres de tus clases ejecutando `Loader::setV2ClassLoading(false);`. Esto te permitirá usar guiones bajos en los nombres de tus clases. @@ -130,7 +130,7 @@ use flight\core\Loader; * public/index.php */ -// Agregar una ruta al autocargador +// Agregar una ruta al autoloader Flight::path(__DIR__.'/../app/controllers/'); Flight::path(__DIR__.'/../app/utils/'); Loader::setV2ClassLoading(false); @@ -139,7 +139,7 @@ Loader::setV2ClassLoading(false); * app/controllers/My_Controller.php */ -// no se requiere nombres de espacio +// no se requiere namespacing class My_Controller { @@ -149,30 +149,30 @@ class My_Controller { } ``` -## Ver También -- [Enrutamiento](/learn/routing) - Cómo mapear rutas a controladores y renderizar vistas. -- [¿Por qué un Framework?](/learn/why-frameworks) - Entendiendo los beneficios de usar un framework como Flight. +## Ver también +- [Routing](/learn/routing) - Cómo mapear rutas a controladores y renderizar vistas. +- [Why a Framework?](/learn/why-frameworks) - Entendiendo los beneficios de usar un framework como Flight. -## Solución de Problemas -- Si no puedes averiguar por qué no se encuentran tus clases con espacios de nombres, recuerda usar `Flight::path()` al directorio raíz en tu proyecto, no a tu directorio `app/` o `src/` o equivalente. +## Solución de problemas +- Si no puedes averiguar por qué tus clases con namespaces no se encuentran, recuerda usar `Flight::path()` al directorio raíz en tu proyecto, no a tu directorio `app/` o `src/` o equivalente. -### Clase No Encontrada (autocarga no funciona) +### Clase no encontrada (autoloading no funciona) -Podría haber un par de razones para que esto no suceda. A continuación hay algunos ejemplos, pero asegúrate de revisar también la sección de [autocarga](/learn/autoloading). +Podría haber un par de razones para que esto no suceda. A continuación hay algunos ejemplos, pero asegúrate de revisar también la sección de [autoloading](/learn/autoloading). -#### Nombre de Archivo Incorrecto +#### Nombre de archivo incorrecto El más común es que el nombre de la clase no coincida con el nombre del archivo. Si tienes una clase llamada `MyClass`, entonces el archivo debería llamarse `MyClass.php`. Si tienes una clase llamada `MyClass` y el archivo se llama `myclass.php` -entonces el autocargador no podrá encontrarla. +entonces el autoloader no podrá encontrarla. -#### Espacio de Nombres Incorrecto -Si estás usando espacios de nombres, entonces el espacio de nombres debería coincidir con la estructura de directorios. +#### Namespace incorrecto +Si estás usando namespaces, entonces el namespace debería coincidir con la estructura de directorios. ```php -// ...código... +// ...code... -// si tu MyController está en el directorio app/controllers y está con espacio de nombres +// si tu MyController está en el directorio app/controllers y está namespaced // esto no funcionará. Flight::route('/hello', 'MyController->hello'); @@ -183,7 +183,7 @@ Flight::route('/hello', 'app\controllers\MyController->hello'); use app\controllers\MyController; Flight::route('/hello', [ MyController::class, 'hello' ]); -// también puede escribirse +// también se puede escribir Flight::route('/hello', MyController::class.'->hello'); // también... Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); @@ -191,14 +191,14 @@ Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); #### `path()` no definido -En la aplicación esqueleto, esto se define dentro del archivo `config.php`, pero para que se encuentren tus clases, necesitas asegurarte de que el método `path()` +En la app skeleton, esto se define dentro del archivo `config.php`, pero para que tus clases sean encontradas, necesitas asegurarte de que el método `path()` esté definido (probablemente a la raíz de tu directorio) antes de intentar usarlo. ```php -// Agregar una ruta al autocargador +// Agregar una ruta al autoloader Flight::path(__DIR__.'/../'); ``` -## Registro de Cambios +## Changelog - v3.7.2 - Puedes usar Pascal_Snake_Case para los nombres de tus clases ejecutando `Loader::setV2ClassLoading(false);` -- v2.0 - Funcionalidad de autocarga agregada. \ No newline at end of file +- v2.0 - Funcionalidad de autoload agregada. \ No newline at end of file diff --git a/content/v3/es/learn/learn.md b/content/v3/es/learn/learn.md index 47a6f91a..bc09e3b4 100644 --- a/content/v3/es/learn/learn.md +++ b/content/v3/es/learn/learn.md @@ -3,100 +3,104 @@ Flight es un framework rápido, simple y extensible para PHP. Es bastante versátil y se puede usar para construir cualquier tipo de aplicación web. Está construido con la simplicidad en mente y está escrito de una manera que es fácil de entender y usar. -> **Nota:** Verás ejemplos que usan `Flight::` como una variable estática y algunos que usan el objeto Engine `$app->`. Ambos funcionan de manera intercambiable con el otro. `$app` y `$this->app` en un controlador/middleware es el enfoque recomendado por el equipo de Flight. +> **Nota:** Verás ejemplos que usan `Flight::` como una variable estática y algunos que usan el objeto Engine `$app->`. Ambos funcionan de manera intercambiable con el otro. `$app` y `$this->app` en un controlador/intermediario es el enfoque recomendado por el equipo de Flight. ## Componentes Principales -### [Enrutamiento](/learn/routing) +### [Routing](/learn/routing) -Aprende cómo gestionar rutas para tu aplicación web. Esto también incluye agrupar rutas, parámetros de ruta y middleware. +Aprende cómo gestionar rutas para tu aplicación web. Esto también incluye agrupar rutas, parámetros de ruta e intermediarios. ### [Middleware](/learn/middleware) -Aprende cómo usar middleware para filtrar solicitudes y respuestas en tu aplicación. +Aprende cómo usar intermediarios para filtrar solicitudes y respuestas en tu aplicación. -### [Carga Automática](/learn/autoloading) +### [Autoloading](/learn/autoloading) Aprende cómo cargar automáticamente tus propias clases en tu aplicación. -### [Solicitudes](/learn/requests) +### [Requests](/learn/requests) Aprende cómo manejar solicitudes y respuestas en tu aplicación. -### [Respuestas](/learn/responses) +### [Responses](/learn/responses) Aprende cómo enviar respuestas a tus usuarios. -### [Plantillas HTML](/learn/templates) +### [HTML Templates](/learn/templates) -Aprende cómo usar el motor de vistas incorporado para renderizar tus plantillas HTML. +Aprende cómo usar el motor de vistas integrado para renderizar tus plantillas HTML. -### [Seguridad](/learn/security) +### [Security](/learn/security) Aprende cómo asegurar tu aplicación contra amenazas de seguridad comunes. -### [Configuración](/learn/configuration) +### [Configuration](/learn/configuration) Aprende cómo configurar el framework para tu aplicación. -### [Gestor de Eventos](/learn/events) +### [Event Manager](/learn/events) Aprende cómo usar el sistema de eventos para agregar eventos personalizados a tu aplicación. -### [Extender Flight](/learn/extending) +### [Extending Flight](/learn/extending) Aprende cómo extender el framework agregando tus propios métodos y clases. -### [Ganchos de Métodos y Filtrado](/learn/filtering) +### [Method Hooks and Filtering](/learn/filtering) Aprende cómo agregar ganchos de eventos a tus métodos y métodos internos del framework. -### [Contenedor de Inyección de Dependencias (DIC)](/learn/dependency-injection-container) +### [Dependency Injection Container (DIC)](/learn/dependency-injection-container) Aprende cómo usar contenedores de inyección de dependencias (DIC) para gestionar las dependencias de tu aplicación. ## Clases de Utilidad -### [Colecciones](/learn/collections) +### [Collections](/learn/collections) -Las colecciones se usan para contener datos y ser accesibles como un arreglo o como un objeto para facilitar su uso. +Las colecciones se usan para mantener datos y ser accesibles como un array o como un objeto para facilitar su uso. -### [Envoltorio JSON](/learn/json) +### [JSON Wrapper](/learn/json) Esto tiene unas pocas funciones simples para hacer que la codificación y decodificación de tu JSON sea consistente. -### [Envoltorio PDO](/learn/pdo-wrapper) +### [SimplePdo](/learn/simple-pdo) -PDO a veces puede causar más dolores de cabeza de los necesarios. Esta clase envolvente simple puede hacer que sea significativamente más fácil interactuar con tu base de datos. +PDO a veces puede agregar más dolores de cabeza de los necesarios. SimplePdo es una clase auxiliar moderna para PDO con métodos convenientes como `insert()`, `update()`, `delete()` y `transaction()` para hacer las operaciones de base de datos mucho más fáciles. -### [Manejador de Archivos Subidos](/learn/uploaded-file) +### [PdoWrapper](/learn/pdo-wrapper) (Deprecated) + +El envoltorio original de PDO está obsoleto a partir de v3.18.0. Por favor, usa [SimplePdo](/learn/simple-pdo) en su lugar. + +### [Uploaded File Handler](/learn/uploaded-file) Una clase simple para ayudar a gestionar archivos subidos y moverlos a una ubicación permanente. ## Conceptos Importantes -### [¿Por Qué un Framework?](/learn/why-frameworks) +### [Why a Framework?](/learn/why-frameworks) -Aquí hay un artículo corto sobre por qué deberías usar un framework. Es una buena idea entender los beneficios de usar un framework antes de comenzar a usar uno. +Aquí hay un artículo corto sobre por qué deberías usar un framework. Es una buena idea entender los beneficios de usar un framework antes de comenzar a usarlo. Además, se ha creado un excelente tutorial por [@lubiana](https://git.php.fail/lubiana). Aunque no entra en gran detalle sobre Flight específicamente, esta guía te ayudará a entender algunos de los conceptos principales que rodean a un framework y por qué son beneficiosos de usar. Puedes encontrar el tutorial [aquí](https://git.php.fail/lubiana/no-framework-tutorial/src/branch/master/README.md). -### [Flight Comparado con Otros Frameworks](/learn/flight-vs-another-framework) +### [Flight Compared to Other Frameworks](/learn/flight-vs-another-framework) Si estás migrando desde otro framework como Laravel, Slim, Fat-Free o Symfony a Flight, esta página te ayudará a entender las diferencias entre los dos. ## Otros Temas -### [Pruebas Unitarias](/learn/unit-testing) +### [Unit Testing](/learn/unit-testing) -Sigue esta guía para aprender cómo realizar pruebas unitarias en tu código de Flight para que sea sólido como una roca. +Sigue esta guía para aprender cómo probar unidades tu código de Flight para que sea sólido como una roca. -### [IA y Experiencia del Desarrollador](/learn/ai) +### [AI & Developer Experience](/learn/ai) -Aprende cómo Flight funciona con herramientas de IA y flujos de trabajo modernos de desarrolladores para ayudarte a codificar más rápido e inteligente. +Aprende cómo Flight funciona con herramientas de IA y flujos de trabajo modernos de desarrolladores para ayudarte a codificar más rápido y de manera más inteligente. -### [Migrando v2 -> v3](/learn/migrating-to-v3) +### [Migrating v2 -> v3](/learn/migrating-to-v3) La compatibilidad hacia atrás se ha mantenido en su mayor parte, pero hay algunos cambios de los que debes estar al tanto al migrar de v2 a v3. \ No newline at end of file diff --git a/content/v3/es/learn/pdo_wrapper.md b/content/v3/es/learn/pdo_wrapper.md index bf50e508..dd288728 100644 --- a/content/v3/es/learn/pdo_wrapper.md +++ b/content/v3/es/learn/pdo_wrapper.md @@ -1,14 +1,18 @@ # Clase Ayudante PDO PdoWrapper +> **ADVERTENCIA** +> +> **Obsoleto:** `PdoWrapper` está obsoleto desde Flight v3.18.0. No se eliminará en una versión futura, pero se mantendrá para compatibilidad hacia atrás. Por favor, use [SimplePdo](/learn/simple-pdo) en su lugar, que ofrece la misma funcionalidad más métodos ayudantes adicionales para operaciones comunes de base de datos. + ## Resumen -La clase `PdoWrapper` en Flight es un ayudante amigable para trabajar con bases de datos usando PDO. Simplifica tareas comunes de base de datos, agrega algunos métodos útiles para obtener resultados y devuelve los resultados como [Collections](/learn/collections) para un acceso fácil. También soporta registro de consultas y monitoreo de rendimiento de aplicaciones (APM) para casos de uso avanzados. +La clase `PdoWrapper` en Flight es un ayudante amigable para trabajar con bases de datos usando PDO. Simplifica tareas comunes de base de datos, agrega algunos métodos útiles para obtener resultados y devuelve los resultados como [Collections](/learn/collections) para un acceso fácil. También soporta registro de consultas y monitoreo de rendimiento de la aplicación (APM) para casos de uso avanzados. -## Entendiendo +## Comprensión Trabajar con bases de datos en PHP puede ser un poco verboso, especialmente cuando se usa PDO directamente. `PdoWrapper` extiende PDO y agrega métodos que hacen que consultar, obtener y manejar resultados sea mucho más fácil. En lugar de manejar declaraciones preparadas y modos de obtención, obtienes métodos simples para tareas comunes, y cada fila se devuelve como una Collection, por lo que puedes usar notación de array u objeto. -Puedes registrar `PdoWrapper` como un servicio compartido en Flight, y luego usarlo en cualquier lugar de tu aplicación a través de `Flight::db()`. +Puedes registrar `PdoWrapper` como un servicio compartido en Flight, y luego usarlo en cualquier lugar de tu app a través de `Flight::db()`. ## Uso Básico diff --git a/content/v3/es/learn/simple_pdo.md b/content/v3/es/learn/simple_pdo.md new file mode 100644 index 00000000..ce7cf4f5 --- /dev/null +++ b/content/v3/es/learn/simple_pdo.md @@ -0,0 +1,320 @@ +# Clase Auxiliar SimplePdo para PDO + +## Resumen + +La clase `SimplePdo` en Flight es un auxiliar moderno y rico en funciones para trabajar con bases de datos usando PDO. Extiende `PdoWrapper` y agrega métodos auxiliares convenientes para operaciones comunes de base de datos como `insert()`, `update()`, `delete()` y transacciones. Simplifica las tareas de base de datos, devuelve resultados como [Collections](/learn/collections) para un acceso fácil, y soporta registro de consultas y monitoreo de rendimiento de aplicaciones (APM) para casos de uso avanzados. + +## Comprensión + +La clase `SimplePdo` está diseñada para hacer que trabajar con bases de datos en PHP sea mucho más fácil. En lugar de manejar declaraciones preparadas, modos de obtención y operaciones SQL verbosas, obtienes métodos limpios y simples para tareas comunes. Cada fila se devuelve como una Collection, por lo que puedes usar tanto notación de arreglo (`$row['name']`) como notación de objeto (`$row->name`). + +Esta clase es un superconjunto de `PdoWrapper`, lo que significa que incluye toda la funcionalidad de `PdoWrapper` más métodos auxiliares adicionales que hacen que tu código sea más limpio y mantenible. Si estás usando actualmente `PdoWrapper`, actualizar a `SimplePdo` es directo ya que extiende `PdoWrapper`. + +Puedes registrar `SimplePdo` como un servicio compartido en Flight, y luego usarlo en cualquier lugar de tu aplicación a través de `Flight::db()`. + +## Uso Básico + +### Registro de SimplePdo + +Primero, registra la clase `SimplePdo` con Flight: + +```php +Flight::register('db', \flight\database\SimplePdo::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 + ] +]); +``` + +> **NOTA** +> +> Si no especificas `PDO::ATTR_DEFAULT_FETCH_MODE`, `SimplePdo` lo establecerá automáticamente en `PDO::FETCH_ASSOC` por ti. + +Ahora puedes usar `Flight::db()` en cualquier lugar para obtener tu conexión a la base de datos. + +### Ejecución de Consultas + +#### `runQuery()` + +`function runQuery(string $sql, array $params = []): PDOStatement` + +Usa esto para INSERT, UPDATE, o cuando quieras obtener resultados manualmente: + +```php +$db = Flight::db(); +$statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']); +while ($row = $statement->fetch()) { + // $row es un arreglo +} +``` + +También puedes usarlo para escrituras: + +```php +$db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); +$db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]); +``` + +#### `fetchField()` + +`function fetchField(string $sql, array $params = []): mixed` + +Obtén un solo valor de la base de datos: + +```php +$count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']); +``` + +#### `fetchRow()` + +`function fetchRow(string $sql, array $params = []): ?Collection` + +Obtén una sola fila como una Collection (acceso a arreglo/objeto): + +```php +$user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); +echo $user['name']; +// o +echo $user->name; +``` + +> **CONSEJO** +> +> `SimplePdo` agrega automáticamente `LIMIT 1` a las consultas de `fetchRow()` si no está presente, haciendo que tus consultas sean más eficientes. + +#### `fetchAll()` + +`function fetchAll(string $sql, array $params = []): array` + +Obtén todas las filas como un arreglo de Collections: + +```php +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); +foreach ($users as $user) { + echo $user['name']; + // o + echo $user->name; +} +``` + +#### `fetchColumn()` + +`function fetchColumn(string $sql, array $params = []): array` + +Obtén una sola columna como un arreglo: + +```php +$ids = Flight::db()->fetchColumn("SELECT id FROM users WHERE active = ?", [1]); +// Devuelve: [1, 2, 3, 4, 5] +``` + +#### `fetchPairs()` + +`function fetchPairs(string $sql, array $params = []): array` + +Obtén resultados como pares clave-valor (primera columna como clave, segunda como valor): + +```php +$userNames = Flight::db()->fetchPairs("SELECT id, name FROM users"); +// Devuelve: [1 => 'John', 2 => 'Jane', 3 => 'Bob'] +``` + +### Usando Marcadores de Posición `IN()` + +Puedes usar un solo `?` en una cláusula `IN()` y pasar un arreglo: + +```php +$ids = [1, 2, 3]; +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); +``` + +## Métodos Auxiliares + +Una de las principales ventajas de `SimplePdo` sobre `PdoWrapper` es la adición de métodos auxiliares convenientes para operaciones comunes de base de datos. + +### `insert()` + +`function insert(string $table, array $data): string` + +Inserta una o más filas y devuelve el último ID de inserción. + +**Inserción única:** + +```php +$id = Flight::db()->insert('users', [ + 'name' => 'John', + 'email' => 'john@example.com' +]); +``` + +**Inserción masiva:** + +```php +$id = Flight::db()->insert('users', [ + ['name' => 'John', 'email' => 'john@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'], +]); +``` + +### `update()` + +`function update(string $table, array $data, string $where, array $whereParams = []): int` + +Actualiza filas y devuelve el número de filas afectadas: + +```php +$affected = Flight::db()->update( + 'users', + ['name' => 'Jane', 'email' => 'jane@example.com'], + 'id = ?', + [1] +); +``` + +> **NOTA** +> +> El `rowCount()` de SQLite devuelve el número de filas donde los datos realmente cambiaron. Si actualizas una fila con los mismos valores que ya tiene, `rowCount()` devolverá 0. Esto difiere del comportamiento de MySQL cuando se usa `PDO::MYSQL_ATTR_FOUND_ROWS`. + +### `delete()` + +`function delete(string $table, string $where, array $whereParams = []): int` + +Elimina filas y devuelve el número de filas eliminadas: + +```php +$deleted = Flight::db()->delete('users', 'id = ?', [1]); +``` + +### `transaction()` + +`function transaction(callable $callback): mixed` + +Ejecuta un callback dentro de una transacción. La transacción se confirma automáticamente en caso de éxito o se revierte en caso de error: + +```php +$result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John']); + $db->insert('logs', ['action' => 'user_created']); + return $db->lastInsertId(); +}); +``` + +Si se lanza alguna excepción dentro del callback, la transacción se revierte automáticamente y la excepción se relanza. + +## Uso Avanzado + +### Registro de Consultas y APM + +Si quieres rastrear el rendimiento de las consultas, habilita el seguimiento de APM al registrar: + +```php +Flight::register('db', \flight\database\SimplePdo::class, [ + 'mysql:host=localhost;dbname=cool_db_name', + 'user', + 'pass', + [/* opciones de PDO */], + [ + 'trackApmQueries' => true, + 'maxQueryMetrics' => 1000 + ] +]); +``` + +Después de ejecutar consultas, puedes registrarlas manualmente, pero el APM las registrará automáticamente si está habilitado: + +```php +Flight::db()->logQueries(); +``` + +Esto activará un evento (`flight.db.queries`) con métricas de conexión y consultas, que puedes escuchar usando el sistema de eventos de Flight. + +### Ejemplo Completo + +```php +Flight::route('/users', function () { + // Obtener todos los usuarios + $users = Flight::db()->fetchAll('SELECT * FROM users'); + + // Transmitir todos los usuarios + $statement = Flight::db()->runQuery('SELECT * FROM users'); + while ($user = $statement->fetch()) { + echo $user['name']; + } + + // Obtener un solo usuario + $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); + + // Obtener un solo valor + $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); + + // Obtener una sola columna + $ids = Flight::db()->fetchColumn('SELECT id FROM users'); + + // Obtener pares clave-valor + $userNames = Flight::db()->fetchPairs('SELECT id, name FROM users'); + + // Sintaxis especial IN() + $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); + + // Insertar un nuevo usuario + $id = Flight::db()->insert('users', [ + 'name' => 'Bob', + 'email' => 'bob@example.com' + ]); + + // Inserción masiva de usuarios + Flight::db()->insert('users', [ + ['name' => 'Bob', 'email' => 'bob@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'] + ]); + + // Actualizar un usuario + $affected = Flight::db()->update('users', ['name' => 'Bob'], 'id = ?', [123]); + + // Eliminar un usuario + $deleted = Flight::db()->delete('users', 'id = ?', [123]); + + // Usar una transacción + $result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John', 'email' => 'john@example.com']); + $db->insert('audit_log', ['action' => 'user_created']); + return $db->lastInsertId(); + }); +}); +``` + +## Migración desde PdoWrapper + +Si estás usando actualmente `PdoWrapper`, migrar a `SimplePdo` es directo: + +1. **Actualiza tu registro:** + ```php + // Antiguo + Flight::register('db', \flight\database\PdoWrapper::class, [ /* ... */ ]); + + // Nuevo + Flight::register('db', \flight\database\SimplePdo::class, [ /* ... */ ]); + ``` + +2. **Todos los métodos existentes de `PdoWrapper` funcionan en `SimplePdo`** - No hay cambios que rompan la compatibilidad. Tu código existente continuará funcionando. + +3. **Opcionalmente usa los nuevos métodos auxiliares** - Comienza a usar `insert()`, `update()`, `delete()` y `transaction()` para simplificar tu código. + +## Ver También + +- [Collections](/learn/collections) - Aprende cómo usar la clase Collection para un acceso fácil a los datos. +- [PdoWrapper](/learn/pdo-wrapper) - La clase auxiliar PDO legacy (deprecada). + +## Solución de Problemas + +- Si obtienes un error sobre la conexión a la base de datos, verifica tu DSN, nombre de usuario, contraseña y opciones. +- Todas las filas se devuelven como Collections—si necesitas un arreglo plano, usa `$collection->getData()`. +- Para consultas `IN (?)`, asegúrate de pasar un arreglo. +- Si estás experimentando problemas de memoria con el registro de consultas en procesos de larga duración, ajusta la opción `maxQueryMetrics`. + +## Registro de Cambios + +- v3.18.0 - Lanzamiento inicial de SimplePdo con métodos auxiliares para insert, update, delete y transacciones. \ No newline at end of file diff --git a/content/v3/fr/awesome-plugins/awesome_plugins.md b/content/v3/fr/awesome-plugins/awesome_plugins.md index 4564bd42..514955e2 100644 --- a/content/v3/fr/awesome-plugins/awesome_plugins.md +++ b/content/v3/fr/awesome-plugins/awesome_plugins.md @@ -1,13 +1,13 @@ -# Plugins Géniaux +# Plugins Formidables -Flight est incroyablement extensible. Il existe un certain nombre de plugins qui peuvent être utilisés pour ajouter des fonctionnalités à votre application Flight. Certains sont officiellement supportés par l'équipe Flight et d'autres sont des bibliothèques micro/lite pour vous aider à démarrer. +Flight est incroyablement extensible. Il existe un certain nombre de plugins qui peuvent être utilisés pour ajouter des fonctionnalités à votre application Flight. Certains sont officiellement pris en charge par l'équipe Flight et d'autres sont des bibliothèques micro/lite pour vous aider à démarrer. ## Documentation API La documentation API est cruciale pour toute API. Elle aide les développeurs à comprendre comment interagir avec votre API et ce qu'ils peuvent attendre en retour. Il existe quelques outils disponibles pour vous aider à générer la documentation API pour vos projets Flight. - [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Article de blog écrit par Daniel Schreiber sur la façon d'utiliser la spécification OpenAPI avec FlightPHP pour construire votre API en adoptant une approche API-first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI est un excellent outil pour vous aider à générer la documentation API pour vos projets Flight. Il est très facile à utiliser et peut être personnalisé selon vos besoins. C'est la bibliothèque PHP pour vous aider à générer la documentation Swagger. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI est un excellent outil pour vous aider à générer la documentation API pour vos projets Flight. Il est très facile à utiliser et peut être personnalisé pour répondre à vos besoins. C'est la bibliothèque PHP pour vous aider à générer la documentation Swagger. ## Surveillance des Performances des Applications (APM) @@ -22,7 +22,7 @@ Flight est déjà un framework rapide, mais lui ajouter un turbo le rend encore ## Autorisation/Permissions -L'autorisation et les permissions sont cruciales pour toute application qui nécessite des contrôles sur qui peut accéder à quoi. +L'autorisation et les permissions sont cruciales pour toute application qui nécessite des contrôles pour déterminer qui peut accéder à quoi. - officiel [flightphp/permissions](/awesome-plugins/permissions) - Bibliothèque officielle Flight Permissions. Cette bibliothèque est une façon simple d'ajouter des permissions au niveau utilisateur et application à votre application. @@ -30,13 +30,13 @@ L'autorisation et les permissions sont cruciales pour toute application qui néc L'authentification est essentielle pour les applications qui doivent vérifier l'identité des utilisateurs et sécuriser les points de terminaison API. -- [firebase/php-jwt](/awesome-plugins/jwt) - Bibliothèque JSON Web Token (JWT) pour PHP. Une façon simple et sécurisée d'implémenter l'authentification basée sur des tokens dans vos applications Flight. Parfaite pour l'authentification API stateless, la protection des routes avec des middleware, et l'implémentation de flux d'autorisation de style OAuth. +- [firebase/php-jwt](/awesome-plugins/jwt) - Bibliothèque JSON Web Token (JWT) pour PHP. Une façon simple et sécurisée d'implémenter l'authentification basée sur des tokens dans vos applications Flight. Parfaite pour l'authentification API sans état, la protection des routes avec des middlewares, et l'implémentation de flux d'autorisation de style OAuth. ## Mise en Cache La mise en cache est une excellente façon d'accélérer votre application. Il existe un certain nombre de bibliothèques de mise en cache qui peuvent être utilisées avec Flight. -- officiel [flightphp/cache](/awesome-plugins/php-file-cache) - Classe de mise en cache légère, simple et autonome en fichier PHP +- officiel [flightphp/cache](/awesome-plugins/php-file-cache) - Classe de mise en cache PHP légère, simple et autonome en fichier ## CLI @@ -61,15 +61,16 @@ Le débogage est crucial lorsque vous développez dans votre environnement local Les bases de données sont au cœur de la plupart des applications. C'est ainsi que vous stockez et récupérez les données. Certaines bibliothèques de bases de données sont simplement des wrappers pour écrire des requêtes et d'autres sont des ORMs complets. -- officiel [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO officiel Flight qui fait partie du cœur. C'est un wrapper simple pour aider à simplifier le processus d'écriture et d'exécution des requêtes. Ce n'est pas un ORM. -- officiel [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord officiel Flight. Excellente petite bibliothèque pour récupérer et stocker facilement des données dans votre base de données. +- officiel [flightphp/core SimplePdo](/learn/simple-pdo) - Aide officielle Flight PDO qui fait partie du core. C'est un wrapper moderne avec des méthodes d'aide pratiques comme `insert()`, `update()`, `delete()`, et `transaction()` pour simplifier les opérations de base de données. Tous les résultats sont retournés sous forme de Collections pour un accès flexible aux tableaux/objets. Pas un ORM, juste une meilleure façon de travailler avec PDO. +- déprécié [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper officiel Flight PDO qui fait partie du core (déprécié depuis la v3.18.0). Utilisez SimplePdo à la place. +- officiel [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper officiel Flight ActiveRecord. Excellente petite bibliothèque pour récupérer et stocker facilement des données dans votre base de données. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin pour suivre toutes les modifications de base de données pour votre projet. ## Chiffrement Le chiffrement est crucial pour toute application qui stocke des données sensibles. Chiffrer et déchiffrer les données n'est pas terriblement difficile, mais stocker correctement la clé de chiffrement [peut](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [être](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difficile](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). La chose la plus importante est de ne jamais stocker votre clé de chiffrement dans un répertoire public ou de l'engager dans votre dépôt de code. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - C'est une bibliothèque qui peut être utilisée pour chiffrer et déchiffrer les données. Se lancer est assez simple pour commencer à chiffrer et déchiffrer les données. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - C'est une bibliothèque qui peut être utilisée pour chiffrer et déchiffrer des données. Se lancer est assez simple pour commencer à chiffrer et déchiffrer des données. ## File d'Attente de Tâches @@ -79,24 +80,24 @@ Les files d'attente de tâches sont vraiment utiles pour traiter les tâches de ## Session -Les sessions ne sont pas vraiment utiles pour les API mais pour construire une application web, les sessions peuvent être cruciales pour maintenir l'état et les informations de connexion. +Les sessions ne sont pas vraiment utiles pour les API, mais pour construire une application web, les sessions peuvent être cruciales pour maintenir l'état et les informations de connexion. -- officiel [flightphp/session](/awesome-plugins/session) - Bibliothèque officielle Flight Session. C'est une bibliothèque de session simple qui peut être utilisée pour stocker et récupérer les données de session. Elle utilise la gestion de session intégrée de PHP. +- officiel [flightphp/session](/awesome-plugins/session) - Bibliothèque officielle Flight Session. C'est une bibliothèque de session simple qui peut être utilisée pour stocker et récupérer des données de session. Elle utilise la gestion de session intégrée de PHP. - [Ghostff/Session](/awesome-plugins/ghost-session) - Gestionnaire de Session PHP (non-bloquant, flash, segment, chiffrement de session). Utilise PHP open_ssl pour le chiffrement/déchiffrement optionnel des données de session. ## Modélisation La modélisation est au cœur de toute application web avec une interface utilisateur. Il existe un certain nombre de moteurs de modélisation qui peuvent être utilisés avec Flight. -- déprécié [flightphp/core View](/learn#views) - C'est un moteur de modélisation très basique qui fait partie du cœur. Il n'est pas recommandé de l'utiliser si vous avez plus de quelques pages dans votre projet. +- déprécié [flightphp/core View](/learn#views) - C'est un moteur de modélisation très basique qui fait partie du core. Il n'est pas recommandé de l'utiliser si vous avez plus de quelques pages dans votre projet. - [latte/latte](/awesome-plugins/latte) - Latte est un moteur de modélisation complet qui est très facile à utiliser et se rapproche plus de la syntaxe PHP que Twig ou Smarty. Il est également très facile à étendre et à ajouter vos propres filtres et fonctions. - [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate est un puissant moteur de template PHP avec compilation d'actifs, héritage de templates, et traitement de variables. Fonctionnalités : minification automatique CSS/JS, mise en cache, encodage Base64, et intégration optionnelle avec le framework PHP Flight. ## Intégration WordPress -Vous voulez utiliser Flight dans votre projet WordPress ? Il y a un plugin pratique pour cela ! +Voulez-vous utiliser Flight dans votre projet WordPress ? Il y a un plugin pratique pour cela ! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Ce plugin WordPress vous permet d'exécuter Flight juste à côté de WordPress. C'est parfait pour ajouter des API personnalisées, des microservices, ou même des applications complètes à votre site WordPress en utilisant le framework Flight. Super utile si vous voulez le meilleur des deux mondes ! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Ce plugin WordPress vous permet d'exécuter Flight directement aux côtés de WordPress. C'est parfait pour ajouter des API personnalisées, des microservices, ou même des applications complètes à votre site WordPress en utilisant le framework Flight. Super utile si vous voulez le meilleur des deux mondes ! ## Contribution diff --git a/content/v3/fr/awesome-plugins/jwt.md b/content/v3/fr/awesome-plugins/jwt.md index 9bd87ca1..bb911dff 100644 --- a/content/v3/fr/awesome-plugins/jwt.md +++ b/content/v3/fr/awesome-plugins/jwt.md @@ -1,6 +1,6 @@ -# Firebase JWT - Authentification par JSON Web Token pour Flight +# Firebase JWT - Authentification par JSON Web Token -JWT (JSON Web Tokens) est une méthode compacte et sûre pour les URL pour représenter des revendications entre votre application et un client. Ils sont parfaits pour l'authentification d'API sans état — pas besoin de stockage de sessions côté serveur ! Ce guide vous montre comment intégrer [Firebase JWT](https://github.com/firebase/php-jwt) avec Flight pour une authentification sécurisée basée sur des tokens. +JWT (JSON Web Tokens) sont une méthode compacte et sécurisée pour les URL permettant de représenter des revendications entre votre application et un client. Ils sont parfaits pour l'authentification API sans état — pas besoin de stockage de sessions côté serveur ! Ce guide vous montre comment intégrer [Firebase JWT](https://github.com/firebase/php-jwt) avec Flight pour une authentification sécurisée basée sur des tokens. Visitez le [dépôt Github](https://github.com/firebase/php-jwt) pour la documentation complète et les détails. @@ -16,9 +16,9 @@ Exemple de JWT : `eyJ0eXAiOiJKV1QiLCJhbGc...` (ça ressemble à du charabia, mai ### Pourquoi utiliser JWT ? - **Sans état** : Pas besoin de stockage de sessions côté serveur — parfait pour les microservices et les API -- **Évolutif** : Fonctionne bien avec les équilibreurs de charge car il n'y a pas d'exigence d'affinité de session +- **Évolutif** : Fonctionne bien avec les équilibreurs de charge car il n'y a pas de besoin d'affinité de session - **Multi-domaines** : Peut être utilisé à travers différents domaines et services -- **Adapté aux mobiles** : Idéal pour les applications mobiles où les cookies ne fonctionnent pas bien +- **Adapté au mobile** : Idéal pour les applications mobiles où les cookies ne fonctionnent pas bien - **Standardisé** : Approche standard de l'industrie (RFC 7519) ## Installation @@ -57,15 +57,15 @@ try { $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); echo "User ID: " . $decoded->user_id; } catch (Exception $e) { - echo "Token invalide : " . $e->getMessage(); + echo "Invalid token: " . $e->getMessage(); } ``` ## Middleware JWT pour Flight (Approche recommandée) -La façon la plus courante et utile d'utiliser JWT avec Flight est en tant que **middleware** pour protéger vos routes API. Voici un exemple complet, prêt pour la production : +La manière la plus courante et utile d'utiliser JWT avec Flight est en tant que **middleware** pour protéger vos routes API. Voici un exemple complet, prêt pour la production : -### Étape 1 : Créer une classe de middleware JWT +### Étape 1 : Créer une classe Middleware JWT ```php // app/middleware/JwtMiddleware.php @@ -91,12 +91,12 @@ class JwtMiddleware { // Vérifier si l'en-tête Authorization existe if (empty($authHeader)) { - $this->app->jsonHalt(['error' => 'Aucun token d\'autorisation fourni'], 401); + $this->app->jsonHalt(['error' => 'No authorization token provided'], 401); } // Extraire le token du format "Bearer " if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { - $this->app->jsonHalt(['error' => 'Format d\'autorisation invalide. Utilisez : Bearer '], 401); + $this->app->jsonHalt(['error' => 'Invalid authorization format. Use: Bearer '], 401); } $jwt = $matches[1]; @@ -109,11 +109,11 @@ class JwtMiddleware { $this->app->request()->data->user = $decoded; } catch (ExpiredException $e) { - $this->app->jsonHalt(['error' => 'Le token a expiré'], 401); + $this->app->jsonHalt(['error' => 'Token has expired'], 401); } catch (SignatureInvalidException $e) { - $this->app->jsonHalt(['error' => 'Signature de token invalide'], 401); + $this->app->jsonHalt(['error' => 'Invalid token signature'], 401); } catch (Exception $e) { - $this->app->jsonHalt(['error' => 'Token invalide : ' . $e->getMessage()], 401); + $this->app->jsonHalt(['error' => 'Invalid token: ' . $e->getMessage()], 401); } } } @@ -145,7 +145,7 @@ Flight::route('GET /api/user/profile', function() { 'username' => $user->username, 'role' => $user->role ]); -})->addMiddleware( JwtMiddleware::class); +})->addMiddleware(JwtMiddleware::class); // Protéger un groupe entier de routes (plus courant !) Flight::group('/api', function() { @@ -156,11 +156,11 @@ Flight::group('/api', function() { }, [ JwtMiddleware::class ]); // Toutes les routes de ce groupe sont protégées ! ``` -Pour plus de détails sur le middleware, consultez la [documentation middleware](/learn/middleware). +Pour plus de détails sur le middleware, consultez la [documentation du middleware](/learn/middleware). ## Cas d'utilisation courants -### 1. Point de terminaison de connexion (Génération de token) +### 1. Endpoint de connexion (Génération de token) Créez une route qui génère un JWT après une authentification réussie : @@ -174,7 +174,7 @@ Flight::route('POST /api/login', function() { $user = validateUserCredentials($username, $password); if (!$user) { - Flight::jsonHalt(['error' => 'Identifiants invalides'], 401); + Flight::jsonHalt(['error' => 'Invalid credentials'], 401); } // Générer JWT @@ -215,7 +215,7 @@ function validateUserCredentials($username, $password) { ### 2. Flux de rafraîchissement de token -Implémentez un système de token de rafraîchissement pour des sessions longues : +Implémentez un système de token de rafraîchissement pour les sessions longues : ```php Flight::route('POST /api/login', function() { @@ -256,7 +256,7 @@ Flight::route('POST /api/refresh', function() { // Vérifier que c'est un token de rafraîchissement if ($decoded->type !== 'refresh') { - Flight::jsonHalt(['error' => 'Type de token invalide'], 401); + Flight::jsonHalt(['error' => 'Invalid token type'], 401); } // Générer un nouveau token d'accès @@ -274,7 +274,7 @@ Flight::route('POST /api/refresh', function() { ]); } catch (Exception $e) { - Flight::jsonHalt(['error' => 'Token de rafraîchissement invalide'], 401); + Flight::jsonHalt(['error' => 'Invalid refresh token'], 401); } }); ``` @@ -299,17 +299,17 @@ class JwtRoleMiddleware { $user = $this->app->request()->data->user ?? null; if (!$user) { - $this->app->jsonHalt(['error' => 'Authentification requise'], 401); + $this->app->jsonHalt(['error' => 'Authentication required'], 401); } // Vérifier si l'utilisateur a le rôle requis if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { - $this->app->jsonHalt(['error' => 'Permissions insuffisantes'], 403); + $this->app->jsonHalt(['error' => 'Insufficient permissions'], 403); } } } -// Utilisation : Route admin seulement +// Utilisation : Route admin uniquement Flight::route('DELETE /api/users/@id', function($id) { // Logique de suppression d'utilisateur })->addMiddleware([ @@ -320,7 +320,7 @@ Flight::route('DELETE /api/users/@id', function($id) { ### 4. API publique avec limitation de taux par utilisateur -Utilisez JWT pour suivre et limiter le taux des utilisateurs sans sessions : +Utilisez JWT pour suivre et limiter les taux des utilisateurs sans sessions : ```php class RateLimitMiddleware { @@ -334,7 +334,7 @@ class RateLimitMiddleware { $requests = Flight::cache()->get($cacheKey, 0); if ($requests >= 100) { // 100 requêtes par heure - Flight::jsonHalt(['error' => 'Limite de taux dépassée'], 429); + Flight::jsonHalt(['error' => 'Rate limit exceeded'], 429); } Flight::cache()->set($cacheKey, $requests + 1, 3600); @@ -397,17 +397,17 @@ $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); // La vérification de l'expiration est gérée automatiquement par la bibliothèque // Mais vous pouvez ajouter des validations personnalisées : if ($decoded->iat > time()) { - throw new Exception('Token utilisé avant sa date d\'émission'); + throw new Exception('Token used before it was issued'); } if (isset($decoded->nbf) && $decoded->nbf > time()) { - throw new Exception('Token pas encore valide'); + throw new Exception('Token not yet valid'); } ``` ### 6. Considérer la liste noire des tokens pour la déconnexion -Pour une sécurité supplémentaire, maintenez une liste noire de tokens invalidés : +Pour une sécurité supplémentaire, maintenez une liste noire des tokens invalidés : ```php Flight::route('POST /api/logout', function() { @@ -422,7 +422,7 @@ Flight::route('POST /api/logout', function() { // Stocker dans le cache/redis jusqu'à expiration Flight::cache()->set("blacklist:$jwt", true, $ttl); - Flight::json(['message' => 'Déconnexion réussie']); + Flight::json(['message' => 'Successfully logged out']); }); // Ajoutez à votre JwtMiddleware : @@ -431,7 +431,7 @@ public function before(array $params) { // Vérifier la liste noire if (Flight::cache()->get("blacklist:$jwt")) { - $this->app->jsonHalt(['error' => 'Le token a été révoqué'], 401); + $this->app->jsonHalt(['error' => 'Token has been revoked'], 401); } // ... vérifier le token ... @@ -453,7 +453,7 @@ $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); ### Algorithmes asymétriques (RSA/ECDSA) - **RS256**, **RS384**, **RS512** : Utilise des paires de clés publique/privée -- **ES256**, **ES384**, **ES512** : Variantes à courbe elliptique +- **ES256**, **ES384**, **ES512** : Variantes courbe elliptique ```php // Générer des clés : openssl genrsa -out private.key 2048 @@ -469,17 +469,17 @@ $jwt = JWT::encode($payload, $privateKey, 'RS256'); $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); ``` -> **Quand utiliser RSA** : Utilisez RSA lorsque vous devez distribuer la clé publique pour la vérification (ex. : microservices, intégrations tierces). Pour une seule application, HS256 est plus simple et suffisant. +> **Quand utiliser RSA** : Utilisez RSA quand vous devez distribuer la clé publique pour la vérification (ex. : microservices, intégrations tierces). Pour une seule application, HS256 est plus simple et suffisant. ## Dépannage ### Erreur "Token expiré" La revendication `exp` de votre token est dans le passé. Émettez un nouveau token ou implémentez le rafraîchissement de token. -### "Échec de la vérification de signature" +### "Échec de vérification de signature" - Vous utilisez une clé secrète différente pour décoder que pour encoder - Le token a été modifié -- Décalage d'horloge entre les serveurs (ajoutez un tampon de tolérance) +- Décalage d'horloge entre serveurs (ajoutez un tampon de tolérance) ```php use Firebase\JWT\JWT; @@ -521,12 +521,12 @@ La bibliothèque Firebase JWT fournit ces méthodes principales : ## Voir aussi -- [Dépôt Github de Firebase JWT](https://github.com/firebase/php-jwt) +- [Dépôt Github Firebase JWT](https://github.com/firebase/php-jwt) - [JWT.io](https://jwt.io/) - Déboguer et décoder les JWT - [RFC 7519](https://tools.ietf.org/html/rfc7519) - Spécification officielle JWT -- [Documentation Middleware de Flight](/learn/middleware) -- [Plugin Session de Flight](/awesome-plugins/session) - Pour l'authentification basée sur sessions traditionnelles +- [Documentation du middleware Flight](/learn/middleware) +- [Plugin Session Flight](/awesome-plugins/session) - Pour l'authentification basée sur sessions traditionnelles ## Licence -La bibliothèque Firebase JWT est sous licence BSD 3-Clause. Consultez le [dépôt Github](https://github.com/firebase/php-jwt) pour les détails. \ No newline at end of file +La bibliothèque Firebase JWT est sous licence BSD 3-Clause. Voir le [dépôt Github](https://github.com/firebase/php-jwt) pour les détails. \ No newline at end of file diff --git a/content/v3/fr/awesome-plugins/runway.md b/content/v3/fr/awesome-plugins/runway.md index 51a1218a..523f3b5a 100644 --- a/content/v3/fr/awesome-plugins/runway.md +++ b/content/v3/fr/awesome-plugins/runway.md @@ -6,7 +6,7 @@ Cliquez [ici](https://github.com/flightphp/runway) pour voir le code. ## Installation -Installez avec composer. +Installez avec Composer. ```bash composer require flightphp/runway @@ -14,7 +14,7 @@ composer require flightphp/runway ## Configuration de Base -La première fois que vous exécutez Runway, il essaiera de trouver une configuration `runway` dans `app/config/config.php` via la clé `'runway'`. +La première fois que vous exécutez Runway, elle essaiera de trouver une configuration `runway` dans `app/config/config.php` via la clé `'runway'`. ```php $config Configuration de app/config/config.php + * @param array $config Config de app/config/config.php */ public function __construct(array $config) { @@ -182,7 +182,7 @@ Consultez la [Documentation adhocore/php-cli](https://github.com/adhocore/php-cl ## Gestion de la Configuration -Puisque la configuration a été déplacée vers `app/config/config.php` à partir de `v1.2.0`, il existe quelques commandes d'aide pour gérer la configuration. +Puisque la configuration a été déplacée vers `app/config/config.php` à partir de `v1.2.0`, il y a quelques commandes d'aide pour gérer la configuration. ### Migrer l'Ancienne Configuration @@ -210,13 +210,13 @@ php runway config:get app_root ## Toutes les Configurations Runway -Si vous devez personnaliser la configuration pour Runway, vous pouvez définir ces valeurs dans `app/config/config.php`. Voici quelques configurations supplémentaires que vous pouvez définir : +Si vous avez besoin de personnaliser la configuration pour Runway, vous pouvez définir ces valeurs dans `app/config/config.php`. Voici quelques configurations supplémentaires que vous pouvez définir : ```php [ // C'est là que se trouve votre répertoire d'application @@ -231,12 +231,12 @@ return [ '/var/www/another-project' ], - // Les chemins de base n'ont probablement pas besoin d'être configurés, mais ils sont là si vous en voulez + // Les chemins de base n'ont probablement pas besoin d'être configurés, mais c'est là si vous le souhaitez 'base_paths' => [ - '/includes/libs/vendor', // si vous avez un chemin vraiment unique pour votre répertoire vendor ou autre + '/includes/libs/vendor', // si vous avez un chemin vraiment unique pour votre répertoire vendor ou quelque chose ], - // Les chemins finaux sont des emplacements dans un projet pour rechercher les fichiers de commandes + // Les chemins finaux sont des emplacements dans un projet pour rechercher les fichiers de commande 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', @@ -254,7 +254,7 @@ return [ ### Accéder à la Configuration -Si vous devez accéder efficacement aux valeurs de configuration, vous pouvez les accéder via la méthode `__construct` ou la méthode `app()`. Il est également important de noter que si vous avez un fichier `app/config/services.php`, ces services seront également disponibles pour votre commande. +Si vous avez besoin d'accéder efficacement aux valeurs de configuration, vous pouvez y accéder via la méthode `__construct` ou la méthode `app()`. Il est également important de noter que si vous avez un fichier `app/config/services.php`, ces services seront également disponibles pour votre commande. ```php public function execute() @@ -271,9 +271,9 @@ public function execute() } ``` -## Wrappers d'Aide IA +## Enveloppeurs d'Aide IA -Runway dispose de quelques wrappers d'aide qui facilitent la génération de commandes par l'IA. Vous pouvez utiliser `addOption` et `addArgument` d'une manière qui ressemble à Symfony Console. Cela est utile si vous utilisez des outils IA pour générer vos commandes. +Runway dispose de quelques enveloppeurs d'aide qui facilitent la génération de commandes par l'IA. Vous pouvez utiliser `addOption` et `addArgument` d'une manière qui ressemble à Symfony Console. Cela est utile si vous utilisez des outils IA pour générer vos commandes. ```php public function __construct(array $config) diff --git a/content/v3/fr/learn/autoloading.md b/content/v3/fr/learn/autoloading.md index 7f56f8a5..303a58e5 100644 --- a/content/v3/fr/learn/autoloading.md +++ b/content/v3/fr/learn/autoloading.md @@ -2,13 +2,13 @@ ## Aperçu -L'autoloading est un concept en PHP où vous spécifiez un répertoire ou des répertoires pour charger les classes. Cela est beaucoup plus avantageux que d'utiliser `require` ou `include` pour charger les classes. C'est également une exigence pour utiliser les packages Composer. +L'autoloading est un concept en PHP où vous spécifiez un répertoire ou des répertoires pour charger les classes. Cela est beaucoup plus avantageux que d'utiliser `require` ou `include` pour charger les classes. C'est également une exigence pour utiliser les paquets Composer. -## Compréhension +## Comprendre Par défaut, toute classe `Flight` est autoloadée automatiquement pour vous grâce à Composer. Cependant, si vous souhaitez autoloader vos propres classes, vous pouvez utiliser la méthode `Flight::path()` pour spécifier un répertoire à partir duquel charger les classes. -L'utilisation d'un autoloader peut aider à simplifier votre code de manière significative. Au lieu d'avoir des fichiers qui commencent par une multitude d'instructions `include` ou `require` en haut pour capturer toutes les classes utilisées dans ce fichier, vous pouvez au contraire appeler dynamiquement vos classes et elles seront incluses automatiquement. +L'utilisation d'un autoloader peut simplifier votre code de manière significative. Au lieu d'avoir des fichiers qui commencent par une multitude d'instructions `include` ou `require` en haut pour capturer toutes les classes utilisées dans ce fichier, vous pouvez au lieu de cela appeler dynamiquement vos classes et elles seront incluses automatiquement. ## Utilisation de base @@ -51,7 +51,7 @@ Flight::path(__DIR__.'/../app/utils/'); // pas de namespace requis -// Toutes les classes autoloadées sont recommandées d'être en Pascal Case (chaque mot en majuscule, sans espaces) +// Toutes les classes autoloadées sont recommandées en Pascal Case (chaque mot avec majuscule, sans espaces) class MyController { public function index() { @@ -60,7 +60,7 @@ class MyController { } ``` -## Espaces de noms +## Namespaces Si vous avez des namespaces, il devient en fait très facile de les implémenter. Vous devriez utiliser la méthode `Flight::path()` pour spécifier le répertoire racine (pas la racine du document ou le dossier `public/`) de votre application. @@ -82,12 +82,12 @@ Maintenant, voici à quoi pourrait ressembler votre contrôleur. Regardez l'exem */ // les namespaces sont requis -// les namespaces sont les mêmes que la structure de répertoires -// les namespaces doivent suivre la même casse que la structure de répertoires +// les namespaces sont les mêmes que la structure des répertoires +// les namespaces doivent suivre le même cas que la structure des répertoires // les namespaces et les répertoires ne peuvent pas avoir de tirets bas (sauf si Loader::setV2ClassLoading(false) est défini) namespace app\controllers; -// Toutes les classes autoloadées sont recommandées d'être en Pascal Case (chaque mot en majuscule, sans espaces) +// Toutes les classes autoloadées sont recommandées en Pascal Case (chaque mot avec majuscule, sans espaces) // À partir de 3.7.2, vous pouvez utiliser Pascal_Snake_Case pour les noms de vos classes en exécutant Loader::setV2ClassLoading(false); class MyController { @@ -105,7 +105,7 @@ Et si vous vouliez autoloader une classe dans votre répertoire utils, vous feri * app/UTILS/ArrayHelperUtil.php */ -// le namespace doit correspondre à la structure de répertoires et à la casse (notez que le répertoire UTILS est tout en majuscules +// le namespace doit correspondre à la structure des répertoires et au cas (notez que le répertoire UTILS est tout en majuscules // comme dans l'arbre de fichiers ci-dessus) namespace app\UTILS; @@ -121,7 +121,7 @@ class ArrayHelperUtil { À partir de 3.7.2, vous pouvez utiliser Pascal_Snake_Case pour les noms de vos classes en exécutant `Loader::setV2ClassLoading(false);`. Cela vous permettra d'utiliser des tirets bas dans les noms de vos classes. -Cela n'est pas recommandé, mais c'est disponible pour ceux qui en ont besoin. +Cela n'est pas recommandé, mais il est disponible pour ceux qui en ont besoin. ```php use flight\core\Loader; @@ -151,14 +151,14 @@ class My_Controller { ## Voir aussi - [Routing](/learn/routing) - Comment mapper les routes aux contrôleurs et rendre les vues. -- [Pourquoi un Framework ?](/learn/why-frameworks) - Comprendre les avantages d'utiliser un framework comme Flight. +- [Why a Framework?](/learn/why-frameworks) - Comprendre les avantages d'utiliser un framework comme Flight. ## Dépannage - Si vous ne parvenez pas à comprendre pourquoi vos classes avec namespace ne sont pas trouvées, rappelez-vous d'utiliser `Flight::path()` vers le répertoire racine de votre projet, pas votre répertoire `app/` ou `src/` ou équivalent. ### Classe non trouvée (autoloading ne fonctionne pas) -Il pourrait y avoir plusieurs raisons pour cela. Ci-dessous, quelques exemples, mais assurez-vous également de consulter la section [autoloading](/learn/autoloading). +Il pourrait y avoir plusieurs raisons pour cela. Ci-dessous quelques exemples, mais assurez-vous de consulter également la section [autoloading](/learn/autoloading). #### Nom de fichier incorrect Le plus courant est que le nom de la classe ne correspond pas au nom du fichier. @@ -167,7 +167,7 @@ Si vous avez une classe nommée `MyClass`, alors le fichier devrait s'appeler `M alors l'autoloader ne pourra pas la trouver. #### Namespace incorrect -Si vous utilisez des namespaces, alors le namespace devrait correspondre à la structure de répertoires. +Si vous utilisez des namespaces, alors le namespace devrait correspondre à la structure des répertoires. ```php // ...code... @@ -185,14 +185,14 @@ use app\controllers\MyController; Flight::route('/hello', [ MyController::class, 'hello' ]); // peut aussi être écrit Flight::route('/hello', MyController::class.'->hello'); -// ou encore... +// aussi... Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); ``` #### `path()` non défini Dans l'application squelette, cela est défini dans le fichier `config.php`, mais pour que vos classes soient trouvées, vous devez vous assurer que la méthode `path()` -est définie (probablement vers la racine de votre répertoire) avant de l'utiliser. +est définie (probablement vers la racine de votre répertoire) avant d'essayer de l'utiliser. ```php // Ajouter un chemin à l'autoloader diff --git a/content/v3/fr/learn/learn.md b/content/v3/fr/learn/learn.md index 43cf57fe..f111950a 100644 --- a/content/v3/fr/learn/learn.md +++ b/content/v3/fr/learn/learn.md @@ -1,37 +1,37 @@ -# Découvrir Flight +# Apprenez à connaître Flight Flight est un framework rapide, simple et extensible pour PHP. Il est très polyvalent et peut être utilisé pour construire tout type d'application web. -Il est conçu avec la simplicité en tête et écrit de manière à être facile à comprendre et à utiliser. +Il est conçu avec la simplicité à l'esprit et est écrit de manière facile à comprendre et à utiliser. -> **Note :** Vous verrez des exemples qui utilisent `Flight::` comme une variable statique et d'autres qui utilisent l'objet Engine `$app->`. Les deux fonctionnent de manière interchangeable avec l'autre. `$app` et `$this->app` dans un contrôleur/middleware est l'approche recommandée par l'équipe Flight. +> **Note :** Vous verrez des exemples qui utilisent `Flight::` comme une variable statique et d'autres qui utilisent l'objet Engine `$app->`. Les deux fonctionnent de manière interchangeable l'un avec l'autre. `$app` et `$this->app` dans un contrôleur/middleware est l'approche recommandée par l'équipe Flight. -## Composants de base +## Composants principaux -### [Routage](/learn/routing) +### [Routing](/learn/routing) -Apprenez à gérer les routes pour votre application web. Cela inclut également le groupement de routes, les paramètres de route et les middleware. +Apprenez à gérer les routes pour votre application web. Cela inclut également le groupement des routes, les paramètres de route et les middlewares. ### [Middleware](/learn/middleware) -Apprenez à utiliser les middleware pour filtrer les requêtes et les réponses dans votre application. +Apprenez à utiliser les middlewares pour filtrer les requêtes et les réponses dans votre application. ### [Autoloading](/learn/autoloading) Apprenez à charger automatiquement vos propres classes dans votre application. -### [Requêtes](/learn/requests) +### [Requests](/learn/requests) Apprenez à gérer les requêtes et les réponses dans votre application. -### [Réponses](/learn/responses) +### [Responses](/learn/responses) Apprenez à envoyer des réponses à vos utilisateurs. -### [Modèles HTML](/learn/templates) +### [HTML Templates](/learn/templates) -Apprenez à utiliser le moteur de vue intégré pour rendre vos modèles HTML. +Apprenez à utiliser le moteur de vue intégré pour rendre vos templates HTML. -### [Sécurité](/learn/security) +### [Security](/learn/security) Apprenez à sécuriser votre application contre les menaces de sécurité courantes. @@ -39,19 +39,19 @@ Apprenez à sécuriser votre application contre les menaces de sécurité couran Apprenez à configurer le framework pour votre application. -### [Gestionnaire d'événements](/learn/events) +### [Event Manager](/learn/events) Apprenez à utiliser le système d'événements pour ajouter des événements personnalisés à votre application. -### [Extension de Flight](/learn/extending) +### [Extending Flight](/learn/extending) Apprenez à étendre le framework en ajoutant vos propres méthodes et classes. -### [Crochets de méthodes et filtrage](/learn/filtering) +### [Method Hooks and Filtering](/learn/filtering) -Apprenez à ajouter des crochets d'événements à vos méthodes et aux méthodes internes du framework. +Apprenez à ajouter des hooks d'événements à vos méthodes et aux méthodes internes du framework. -### [Conteneur d'injection de dépendances (DIC)](/learn/dependency-injection-container) +### [Dependency Injection Container (DIC)](/learn/dependency-injection-container) Apprenez à utiliser les conteneurs d'injection de dépendances (DIC) pour gérer les dépendances de votre application. @@ -59,23 +59,27 @@ Apprenez à utiliser les conteneurs d'injection de dépendances (DIC) pour gére ### [Collections](/learn/collections) -Les collections sont utilisées pour stocker des données et y accéder comme un tableau ou un objet pour plus de simplicité. +Les collections sont utilisées pour stocker des données et y accéder comme un tableau ou comme un objet pour plus de facilité d'utilisation. -### [Wrapper JSON](/learn/json) +### [JSON Wrapper](/learn/json) Cela comprend quelques fonctions simples pour rendre l'encodage et le décodage de votre JSON cohérents. -### [Wrapper PDO](/learn/pdo-wrapper) +### [SimplePdo](/learn/simple-pdo) -PDO peut parfois causer plus de maux de tête que nécessaire. Cette classe wrapper simple peut rendre l'interaction avec votre base de données significativement plus facile. +PDO peut parfois causer plus de maux de tête que nécessaire. SimplePdo est une classe d'aide PDO moderne avec des méthodes pratiques comme `insert()`, `update()`, `delete()`, et `transaction()` pour rendre les opérations de base de données beaucoup plus faciles. -### [Gestionnaire de fichiers téléchargés](/learn/uploaded-file) +### [PdoWrapper](/learn/pdo-wrapper) (Déprécié) + +Le wrapper PDO original est déprécié à partir de la v3.18.0. Veuillez utiliser [SimplePdo](/learn/simple-pdo) à la place. + +### [Uploaded File Handler](/learn/uploaded-file) Une classe simple pour aider à gérer les fichiers téléchargés et à les déplacer vers un emplacement permanent. ## Concepts importants -### [Pourquoi un framework ?](/learn/why-frameworks) +### [Why a Framework?](/learn/why-frameworks) Voici un court article sur pourquoi vous devriez utiliser un framework. Il est une bonne idée de comprendre les avantages d'utiliser un framework avant de commencer à en utiliser un. @@ -83,20 +87,20 @@ De plus, un excellent tutoriel a été créé par [@lubiana](https://git.php.fai ce guide vous aidera à comprendre certains des concepts majeurs entourant un framework et pourquoi ils sont bénéfiques à utiliser. Vous pouvez trouver le tutoriel [ici](https://git.php.fail/lubiana/no-framework-tutorial/src/branch/master/README.md). -### [Flight comparé à d'autres frameworks](/learn/flight-vs-another-framework) +### [Flight Compared to Other Frameworks](/learn/flight-vs-another-framework) Si vous migrez d'un autre framework comme Laravel, Slim, Fat-Free ou Symfony vers Flight, cette page vous aidera à comprendre les différences entre les deux. ## Autres sujets -### [Tests unitaires](/learn/unit-testing) +### [Unit Testing](/learn/unit-testing) Suivez ce guide pour apprendre à tester vos unités de code Flight de manière solide. -### [IA et expérience développeur](/learn/ai) +### [AI & Developer Experience](/learn/ai) -Apprenez comment Flight fonctionne avec les outils d'IA et les flux de travail modernes des développeurs pour vous aider à coder plus rapidement et plus intelligemment. +Apprenez comment Flight fonctionne avec les outils d'IA et les flux de travail de développement modernes pour vous aider à coder plus rapidement et plus intelligemment. -### [Migration v2 -> v3](/learn/migrating-to-v3) +### [Migrating v2 -> v3](/learn/migrating-to-v3) -La compatibilité descendante a été maintenue dans l'ensemble, mais il y a certains changements dont vous devriez être conscient lors de la migration de v2 à v3. \ No newline at end of file +La compatibilité ascendante a été maintenue dans l'ensemble, mais il y a certains changements dont vous devriez être conscient lors de la migration de v2 vers v3. \ No newline at end of file diff --git a/content/v3/fr/learn/pdo_wrapper.md b/content/v3/fr/learn/pdo_wrapper.md index 891f59dd..fa4c9d22 100644 --- a/content/v3/fr/learn/pdo_wrapper.md +++ b/content/v3/fr/learn/pdo_wrapper.md @@ -1,18 +1,22 @@ -# Classe d'Aide PDO PdoWrapper +# Classe d'aide PDO PdoWrapper + +> **AVERTISSEMENT** +> +> **Déprécié :** `PdoWrapper` est déprécié depuis Flight v3.18.0. Il ne sera pas supprimé dans une version future, mais sera maintenu pour la compatibilité descendante. Veuillez utiliser [SimplePdo](/learn/simple-pdo) à la place, qui offre la même fonctionnalité plus des méthodes d'aide supplémentaires pour les opérations de base de données courantes. ## Aperçu -La classe `PdoWrapper` dans Flight est un assistant convivial pour travailler avec les bases de données en utilisant PDO. Elle simplifie les tâches courantes de base de données, ajoute des méthodes pratiques pour récupérer les résultats, et retourne les résultats sous forme de [Collections](/learn/collections) pour un accès facile. Elle supporte également la journalisation des requêtes et la surveillance des performances de l'application (APM) pour des cas d'utilisation avancés. +La classe `PdoWrapper` dans Flight est un aide convivial pour travailler avec les bases de données en utilisant PDO. Elle simplifie les tâches courantes de base de données, ajoute des méthodes pratiques pour récupérer les résultats, et retourne les résultats sous forme de [Collections](/learn/collections) pour un accès facile. Elle supporte également la journalisation des requêtes et la surveillance des performances de l'application (APM) pour des cas d'utilisation avancés. ## Comprendre -Travailler avec les bases de données en PHP peut être un peu verbeux, surtout en utilisant PDO directement. `PdoWrapper` étend PDO et ajoute des méthodes qui rendent les requêtes, la récupération et la gestion des résultats beaucoup plus faciles. Au lieu de jongler avec des instructions préparées et des modes de récupération, vous obtenez des méthodes simples pour les tâches courantes, et chaque ligne est retournée sous forme de Collection, afin que vous puissiez utiliser la notation tableau ou objet. +Travailler avec les bases de données en PHP peut être un peu verbeux, surtout en utilisant PDO directement. `PdoWrapper` étend PDO et ajoute des méthodes qui rendent les requêtes, la récupération et la gestion des résultats beaucoup plus faciles. Au lieu de jongler avec des instructions préparées et des modes de récupération, vous obtenez des méthodes simples pour les tâches courantes, et chaque ligne est retournée comme une Collection, afin que vous puissiez utiliser la notation tableau ou objet. -Vous pouvez enregistrer `PdoWrapper` en tant que service partagé dans Flight, puis l'utiliser n'importe où dans votre application via `Flight::db()`. +Vous pouvez enregistrer `PdoWrapper` comme un service partagé dans Flight, et ensuite l'utiliser n'importe où dans votre application via `Flight::db()`. -## Utilisation de Base +## Utilisation de base -### Enregistrement de l'Aideur PDO +### Enregistrement de l'aide PDO D'abord, enregistrez la classe `PdoWrapper` avec Flight : @@ -29,13 +33,13 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ Maintenant, vous pouvez utiliser `Flight::db()` n'importe où pour obtenir votre connexion à la base de données. -### Exécution de Requêtes +### Exécution des requêtes #### `runQuery()` `function runQuery(string $sql, array $params = []): PDOStatement` -Utilisez ceci pour les INSERT, UPDATE, ou lorsque vous voulez récupérer les résultats manuellement : +Utilisez ceci pour les INSERT, UPDATE, ou quand vous voulez récupérer les résultats manuellement : ```php $db = Flight::db(); @@ -45,7 +49,7 @@ while ($row = $statement->fetch()) { } ``` -Vous pouvez également l'utiliser pour les écritures : +Vous pouvez aussi l'utiliser pour les écritures : ```php $db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); @@ -66,7 +70,7 @@ $count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", `function fetchRow(string $sql, array $params = []): Collection` -Obtenez une seule ligne sous forme de Collection (accès tableau/objet) : +Obtenez une seule ligne comme une Collection (accès tableau/objet) : ```php $user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); @@ -79,7 +83,7 @@ echo $user->name; `function fetchAll(string $sql, array $params = []): array` -Obtenez toutes les lignes sous forme de tableau de Collections : +Obtenez toutes les lignes comme un tableau de Collections : ```php $users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); @@ -90,7 +94,7 @@ foreach ($users as $user) { } ``` -### Utilisation des Lieux-Tenants `IN()` +### Utilisation des placeholders `IN()` Vous pouvez utiliser un seul `?` dans une clause `IN()` et passer un tableau ou une chaîne séparée par des virgules : @@ -101,9 +105,9 @@ $users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); $users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", ['1,2,3']); ``` -## Utilisation Avancée +## Utilisation avancée -### Journalisation des Requêtes & APM +### Journalisation des requêtes & APM Si vous voulez suivre les performances des requêtes, activez le suivi APM lors de l'enregistrement : @@ -113,7 +117,7 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ ]); ``` -Après l'exécution des requêtes, vous pouvez les journaliser manuellement, mais l'APM les journalisera automatiquement si activé : +Après avoir exécuté des requêtes, vous pouvez les journaliser manuellement mais l'APM les journalisera automatiquement si activé : ```php Flight::db()->logQueries(); @@ -121,7 +125,7 @@ Flight::db()->logQueries(); Cela déclenchera un événement (`flight.db.queries`) avec les métriques de connexion et de requête, que vous pouvez écouter en utilisant le système d'événements de Flight. -### Exemple Complet +### Exemple complet ```php Flight::route('/users', function () { @@ -160,16 +164,16 @@ Flight::route('/users', function () { }); ``` -## Voir Aussi +## Voir aussi - [Collections](/learn/collections) - Apprenez comment utiliser la classe Collection pour un accès facile aux données. ## Dépannage - Si vous obtenez une erreur concernant la connexion à la base de données, vérifiez votre DSN, nom d'utilisateur, mot de passe et options. -- Toutes les lignes sont retournées sous forme de Collections—si vous avez besoin d'un tableau simple, utilisez `$collection->getData()`. +- Toutes les lignes sont retournées comme des Collections—si vous avez besoin d'un tableau simple, utilisez `$collection->getData()`. - Pour les requêtes `IN (?)`, assurez-vous de passer un tableau ou une chaîne séparée par des virgules. -## Journal des Modifications +## Journal des modifications -- v3.2.0 - Publication initiale de PdoWrapper avec les méthodes de requête et de récupération de base. \ No newline at end of file +- v3.2.0 - Version initiale de PdoWrapper avec des méthodes de requête et de récupération de base. \ No newline at end of file diff --git a/content/v3/fr/learn/simple_pdo.md b/content/v3/fr/learn/simple_pdo.md new file mode 100644 index 00000000..2b71d8c6 --- /dev/null +++ b/content/v3/fr/learn/simple_pdo.md @@ -0,0 +1,320 @@ +# Classe d'aide SimplePdo PDO + +## Aperçu + +La classe `SimplePdo` dans Flight est un assistant moderne et riche en fonctionnalités pour travailler avec des bases de données en utilisant PDO. Elle étend `PdoWrapper` et ajoute des méthodes d'aide pratiques pour les opérations courantes sur les bases de données comme `insert()`, `update()`, `delete()`, et les transactions. Elle simplifie les tâches liées aux bases de données, retourne les résultats sous forme de [Collections](/learn/collections) pour un accès facile, et prend en charge la journalisation des requêtes et la surveillance des performances des applications (APM) pour les cas d'utilisation avancés. + +## Comprendre + +La classe `SimplePdo` est conçue pour rendre le travail avec les bases de données en PHP beaucoup plus facile. Au lieu de jongler avec des instructions préparées, des modes de récupération et des opérations SQL verbeuses, vous obtenez des méthodes propres et simples pour les tâches courantes. Chaque ligne est retournée sous forme de Collection, afin que vous puissiez utiliser à la fois la notation tableau (`$row['name']`) et la notation objet (`$row->name`). + +Cette classe est un sur-ensemble de `PdoWrapper`, ce qui signifie qu'elle inclut toute la fonctionnalité de `PdoWrapper` plus des méthodes d'aide supplémentaires qui rendent votre code plus propre et plus maintenable. Si vous utilisez actuellement `PdoWrapper`, la mise à niveau vers `SimplePdo` est simple car elle étend `PdoWrapper`. + +Vous pouvez enregistrer `SimplePdo` en tant que service partagé dans Flight, puis l'utiliser n'importe où dans votre application via `Flight::db()`. + +## Utilisation de base + +### Enregistrement de SimplePdo + +D'abord, enregistrez la classe `SimplePdo` avec Flight : + +```php +Flight::register('db', \flight\database\SimplePdo::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 + ] +]); +``` + +> **NOTE** +> +> Si vous ne spécifiez pas `PDO::ATTR_DEFAULT_FETCH_MODE`, `SimplePdo` le définira automatiquement à `PDO::FETCH_ASSOC` pour vous. + +Maintenant, vous pouvez utiliser `Flight::db()` n'importe où pour obtenir votre connexion à la base de données. + +### Exécution de requêtes + +#### `runQuery()` + +`function runQuery(string $sql, array $params = []): PDOStatement` + +Utilisez ceci pour les INSERT, UPDATE, ou lorsque vous voulez récupérer les résultats manuellement : + +```php +$db = Flight::db(); +$statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']); +while ($row = $statement->fetch()) { + // $row est un tableau +} +``` + +Vous pouvez aussi l'utiliser pour les écritures : + +```php +$db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); +$db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]); +``` + +#### `fetchField()` + +`function fetchField(string $sql, array $params = []): mixed` + +Obtenez une seule valeur de la base de données : + +```php +$count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']); +``` + +#### `fetchRow()` + +`function fetchRow(string $sql, array $params = []): ?Collection` + +Obtenez une seule ligne sous forme de Collection (accès tableau/objet) : + +```php +$user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); +echo $user['name']; +// ou +echo $user->name; +``` + +> **TIP** +> +> `SimplePdo` ajoute automatiquement `LIMIT 1` aux requêtes `fetchRow()` si elle n'est pas déjà présente, rendant vos requêtes plus efficaces. + +#### `fetchAll()` + +`function fetchAll(string $sql, array $params = []): array` + +Obtenez toutes les lignes sous forme de tableau de Collections : + +```php +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); +foreach ($users as $user) { + echo $user['name']; + // ou + echo $user->name; +} +``` + +#### `fetchColumn()` + +`function fetchColumn(string $sql, array $params = []): array` + +Récupérez une seule colonne sous forme de tableau : + +```php +$ids = Flight::db()->fetchColumn("SELECT id FROM users WHERE active = ?", [1]); +// Retourne : [1, 2, 3, 4, 5] +``` + +#### `fetchPairs()` + +`function fetchPairs(string $sql, array $params = []): array` + +Récupérez les résultats sous forme de paires clé-valeur (première colonne comme clé, seconde comme valeur) : + +```php +$userNames = Flight::db()->fetchPairs("SELECT id, name FROM users"); +// Retourne : [1 => 'John', 2 => 'Jane', 3 => 'Bob'] +``` + +### Utilisation des placeholders `IN()` + +Vous pouvez utiliser un seul `?` dans une clause `IN()` et passer un tableau : + +```php +$ids = [1, 2, 3]; +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); +``` + +## Méthodes d'aide + +L'un des principaux avantages de `SimplePdo` par rapport à `PdoWrapper` est l'ajout de méthodes d'aide pratiques pour les opérations courantes sur les bases de données. + +### `insert()` + +`function insert(string $table, array $data): string` + +Insérez une ou plusieurs lignes et retournez le dernier ID inséré. + +**Insertion unique :** + +```php +$id = Flight::db()->insert('users', [ + 'name' => 'John', + 'email' => 'john@example.com' +]); +``` + +**Insertion en masse :** + +```php +$id = Flight::db()->insert('users', [ + ['name' => 'John', 'email' => 'john@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'], +]); +``` + +### `update()` + +`function update(string $table, array $data, string $where, array $whereParams = []): int` + +Mettez à jour des lignes et retournez le nombre de lignes affectées : + +```php +$affected = Flight::db()->update( + 'users', + ['name' => 'Jane', 'email' => 'jane@example.com'], + 'id = ?', + [1] +); +``` + +> **NOTE** +> +> Le `rowCount()` de SQLite retourne le nombre de lignes où les données ont réellement changé. Si vous mettez à jour une ligne avec les mêmes valeurs qu'elle a déjà, `rowCount()` retournera 0. Cela diffère du comportement de MySQL lors de l'utilisation de `PDO::MYSQL_ATTR_FOUND_ROWS`. + +### `delete()` + +`function delete(string $table, string $where, array $whereParams = []): int` + +Supprimez des lignes et retournez le nombre de lignes supprimées : + +```php +$deleted = Flight::db()->delete('users', 'id = ?', [1]); +``` + +### `transaction()` + +`function transaction(callable $callback): mixed` + +Exécutez un rappel dans une transaction. La transaction s'engage automatiquement en cas de succès ou se déroule en cas d'erreur : + +```php +$result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John']); + $db->insert('logs', ['action' => 'user_created']); + return $db->lastInsertId(); +}); +``` + +Si une exception est levée dans le rappel, la transaction est automatiquement déroulée et l'exception est relancée. + +## Utilisation avancée + +### Journalisation des requêtes & APM + +Si vous voulez suivre les performances des requêtes, activez le suivi APM lors de l'enregistrement : + +```php +Flight::register('db', \flight\database\SimplePdo::class, [ + 'mysql:host=localhost;dbname=cool_db_name', + 'user', + 'pass', + [/* options PDO */], + [ + 'trackApmQueries' => true, + 'maxQueryMetrics' => 1000 + ] +]); +``` + +Après avoir exécuté des requêtes, vous pouvez les journaliser manuellement, mais l'APM les journalisera automatiquement si activé : + +```php +Flight::db()->logQueries(); +``` + +Cela déclenchera un événement (`flight.db.queries`) avec les métriques de connexion et de requête, que vous pouvez écouter en utilisant le système d'événements de Flight. + +### Exemple complet + +```php +Flight::route('/users', function () { + // Obtenir tous les utilisateurs + $users = Flight::db()->fetchAll('SELECT * FROM users'); + + // Diffuser tous les utilisateurs + $statement = Flight::db()->runQuery('SELECT * FROM users'); + while ($user = $statement->fetch()) { + echo $user['name']; + } + + // Obtenir un seul utilisateur + $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); + + // Obtenir une seule valeur + $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); + + // Obtenir une seule colonne + $ids = Flight::db()->fetchColumn('SELECT id FROM users'); + + // Obtenir des paires clé-valeur + $userNames = Flight::db()->fetchPairs('SELECT id, name FROM users'); + + // Syntaxe spéciale IN() + $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); + + // Insérer un nouvel utilisateur + $id = Flight::db()->insert('users', [ + 'name' => 'Bob', + 'email' => 'bob@example.com' + ]); + + // Insertion en masse d'utilisateurs + Flight::db()->insert('users', [ + ['name' => 'Bob', 'email' => 'bob@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'] + ]); + + // Mettre à jour un utilisateur + $affected = Flight::db()->update('users', ['name' => 'Bob'], 'id = ?', [123]); + + // Supprimer un utilisateur + $deleted = Flight::db()->delete('users', 'id = ?', [123]); + + // Utiliser une transaction + $result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John', 'email' => 'john@example.com']); + $db->insert('audit_log', ['action' => 'user_created']); + return $db->lastInsertId(); + }); +}); +``` + +## Migration depuis PdoWrapper + +Si vous utilisez actuellement `PdoWrapper`, la migration vers `SimplePdo` est simple : + +1. **Mettez à jour votre enregistrement :** + ```php + // Ancien + Flight::register('db', \flight\database\PdoWrapper::class, [ /* ... */ ]); + + // Nouveau + Flight::register('db', \flight\database\SimplePdo::class, [ /* ... */ ]); + ``` + +2. **Toutes les méthodes existantes de `PdoWrapper` fonctionnent dans `SimplePdo`** - Il n'y a pas de changements cassants. Votre code existant continuera à fonctionner. + +3. **Utilisez optionnellement les nouvelles méthodes d'aide** - Commencez à utiliser `insert()`, `update()`, `delete()`, et `transaction()` pour simplifier votre code. + +## Voir aussi + +- [Collections](/learn/collections) - Apprenez comment utiliser la classe Collection pour un accès facile aux données. +- [PdoWrapper](/learn/pdo-wrapper) - La classe d'aide PDO legacy (dépréciée). + +## Dépannage + +- Si vous obtenez une erreur concernant la connexion à la base de données, vérifiez votre DSN, nom d'utilisateur, mot de passe et options. +- Toutes les lignes sont retournées sous forme de Collections — si vous avez besoin d'un tableau simple, utilisez `$collection->getData()`. +- Pour les requêtes `IN (?)`, assurez-vous de passer un tableau. +- Si vous rencontrez des problèmes de mémoire avec la journalisation des requêtes dans des processus longs, ajustez l'option `maxQueryMetrics`. + +## Journal des modifications + +- v3.18.0 - Première publication de SimplePdo avec des méthodes d'aide pour insert, update, delete, et transactions. \ No newline at end of file diff --git a/content/v3/id/awesome-plugins/awesome_plugins.md b/content/v3/id/awesome-plugins/awesome_plugins.md index 1895bdd8..3bf10cb1 100644 --- a/content/v3/id/awesome-plugins/awesome_plugins.md +++ b/content/v3/id/awesome-plugins/awesome_plugins.md @@ -7,11 +7,11 @@ Flight sangat mudah diperluas. Ada sejumlah plugin yang dapat digunakan untuk me Dokumentasi API sangat penting untuk API apa pun. Ini membantu pengembang memahami cara berinteraksi dengan API Anda dan apa yang diharapkan sebagai balasan. Ada beberapa alat yang tersedia untuk membantu Anda menghasilkan dokumentasi API untuk Proyek Flight Anda. - [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Posting blog yang ditulis oleh Daniel Schreiber tentang cara menggunakan Spesifikasi OpenAPI dengan FlightPHP untuk membangun API Anda menggunakan pendekatan API pertama. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI adalah alat yang hebat untuk membantu Anda menghasilkan dokumentasi API untuk proyek Flight Anda. Ini sangat mudah digunakan dan dapat disesuaikan sesuai kebutuhan Anda. Ini adalah pustaka PHP untuk membantu Anda menghasilkan dokumentasi Swagger. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI adalah alat hebat untuk membantu Anda menghasilkan dokumentasi API untuk proyek Flight Anda. Ini sangat mudah digunakan dan dapat disesuaikan sesuai kebutuhan Anda. Ini adalah pustaka PHP untuk membantu Anda menghasilkan dokumentasi Swagger. ## Pemantauan Kinerja Aplikasi (APM) -Pemantauan Kinerja Aplikasi (APM) sangat penting untuk aplikasi apa pun. Ini membantu Anda memahami bagaimana aplikasi Anda berkinerja dan di mana kemacetan berada. Ada sejumlah alat APM yang dapat digunakan dengan Flight. +Pemantauan Kinerja Aplikasi (APM) sangat penting untuk aplikasi apa pun. Ini membantu Anda memahami bagaimana aplikasi Anda berkinerja dan di mana kemacetan terjadi. Ada sejumlah alat APM yang dapat digunakan dengan Flight. - resmi [flightphp/apm](/awesome-plugins/apm) - Flight APM adalah pustaka APM sederhana yang dapat digunakan untuk memantau aplikasi Flight Anda. Ini dapat digunakan untuk memantau kinerja aplikasi Anda dan membantu Anda mengidentifikasi kemacetan. ## Async @@ -22,58 +22,59 @@ Flight sudah merupakan framework yang cepat, tetapi menambahkan mesin turbo pada ## Otorisasi/Izin -Otorisasi dan Izin sangat penting untuk aplikasi apa pun yang memerlukan kontrol atas siapa yang dapat mengakses apa. +Otorisasi dan Izin sangat penting untuk aplikasi apa pun yang memerlukan kontrol untuk siapa yang dapat mengakses apa. - resmi [flightphp/permissions](/awesome-plugins/permissions) - Pustaka Permissions Flight resmi. Pustaka ini adalah cara sederhana untuk menambahkan izin tingkat pengguna dan aplikasi ke aplikasi Anda. -## Otentikasi +## Autentikasi -Otentikasi sangat penting untuk aplikasi yang perlu memverifikasi identitas pengguna dan mengamankan endpoint API. +Autentikasi sangat penting untuk aplikasi yang perlu memverifikasi identitas pengguna dan mengamankan endpoint API. -- [firebase/php-jwt](/awesome-plugins/jwt) - Pustaka JSON Web Token (JWT) untuk PHP. Cara sederhana dan aman untuk mengimplementasikan otentikasi berbasis token di aplikasi Flight Anda. Sempurna untuk otentikasi API tanpa status, melindungi rute dengan middleware, dan mengimplementasikan alur otorisasi gaya OAuth. +- [firebase/php-jwt](/awesome-plugins/jwt) - Pustaka JSON Web Token (JWT) untuk PHP. Cara sederhana dan aman untuk mengimplementasikan autentikasi berbasis token di aplikasi Flight Anda. Sempurna untuk autentikasi API tanpa status, melindungi rute dengan middleware, dan mengimplementasikan alur otorisasi gaya OAuth. ## Penyimpanan Cache Penyimpanan cache adalah cara hebat untuk mempercepat aplikasi Anda. Ada sejumlah pustaka caching yang dapat digunakan dengan Flight. -- resmi [flightphp/cache](/awesome-plugins/php-file-cache) - Kelas caching dalam file PHP yang ringan, sederhana, dan mandiri +- resmi [flightphp/cache](/awesome-plugins/php-file-cache) - Kelas caching dalam file PHP yang ringan, sederhana, dan standalone ## CLI -Aplikasi CLI adalah cara hebat untuk berinteraksi dengan aplikasi Anda. Anda dapat menggunakannya untuk menghasilkan controller, menampilkan semua rute, dan banyak lagi. +Aplikasi CLI adalah cara hebat untuk berinteraksi dengan aplikasi Anda. Anda dapat menggunakannya untuk menghasilkan controller, menampilkan semua rute, dan lainnya. - resmi [flightphp/runway](/awesome-plugins/runway) - Runway adalah aplikasi CLI yang membantu Anda mengelola aplikasi Flight Anda. ## Cookies -Cookies adalah cara hebat untuk menyimpan bit data kecil di sisi klien. Mereka dapat digunakan untuk menyimpan preferensi pengguna, pengaturan aplikasi, dan banyak lagi. +Cookies adalah cara hebat untuk menyimpan bit data kecil di sisi klien. Mereka dapat digunakan untuk menyimpan preferensi pengguna, pengaturan aplikasi, dan lainnya. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie adalah pustaka PHP yang menyediakan cara sederhana dan efektif untuk mengelola cookies. ## Debugging -Debugging sangat penting saat Anda mengembangkan di lingkungan lokal Anda. Ada beberapa plugin yang dapat meningkatkan pengalaman debugging Anda. +Debugging sangat penting saat Anda mengembangkan di lingkungan lokal. Ada beberapa plugin yang dapat meningkatkan pengalaman debugging Anda. - [tracy/tracy](/awesome-plugins/tracy) - Ini adalah penanganan kesalahan lengkap yang dapat digunakan dengan Flight. Ini memiliki sejumlah panel yang dapat membantu Anda mendebug aplikasi Anda. Ini juga sangat mudah untuk diperluas dan menambahkan panel Anda sendiri. - resmi [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Digunakan dengan penanganan kesalahan [Tracy](/awesome-plugins/tracy), plugin ini menambahkan beberapa panel tambahan untuk membantu debugging khusus untuk proyek Flight. ## Database -Database adalah inti dari sebagian besar aplikasi. Inilah cara Anda menyimpan dan mengambil data. Beberapa pustaka database hanyalah wrapper untuk menulis query dan beberapa adalah ORM lengkap. +Database adalah inti dari sebagian besar aplikasi. Ini adalah cara Anda menyimpan dan mengambil data. Beberapa pustaka database hanyalah wrapper untuk menulis kueri dan beberapa adalah ORM lengkap. -- resmi [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO Flight resmi yang merupakan bagian dari inti. Ini adalah wrapper sederhana untuk membantu menyederhanakan proses penulisan query dan mengeksekusinya. Ini bukan ORM. +- resmi [flightphp/core SimplePdo](/learn/simple-pdo) - Pembantu PDO Flight resmi yang merupakan bagian dari inti. Ini adalah wrapper modern dengan metode pembantu yang nyaman seperti `insert()`, `update()`, `delete()`, dan `transaction()` untuk menyederhanakan operasi database. Semua hasil dikembalikan sebagai Collections untuk akses array/objek yang fleksibel. Bukan ORM, hanya cara yang lebih baik untuk bekerja dengan PDO. +- deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO Flight resmi yang merupakan bagian dari inti (deprecated sejak v3.18.0). Gunakan SimplePdo sebagai gantinya. - resmi [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord Flight resmi. Pustaka kecil yang hebat untuk dengan mudah mengambil dan menyimpan data di database Anda. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin untuk melacak semua perubahan database untuk proyek Anda. ## Enkripsi -Enkripsi sangat penting untuk aplikasi apa pun yang menyimpan data sensitif. Mengenkripsi dan mendekripsi data tidak terlalu sulit, tetapi menyimpan kunci enkripsi dengan benar [bisa](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [menjadi](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [sulit](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Hal terpenting adalah jangan pernah menyimpan kunci enkripsi Anda di direktori publik atau mengommitnya ke repositori kode Anda. +Enkripsi sangat penting untuk aplikasi apa pun yang menyimpan data sensitif. Mengenkripsi dan mendekripsi data tidak terlalu sulit, tetapi menyimpan kunci enkripsi dengan benar [bisa](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [menjadi](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [sulit](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Hal yang paling penting adalah jangan pernah menyimpan kunci enkripsi Anda di direktori publik atau mengkomitnya ke repositori kode Anda. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Ini adalah pustaka yang dapat digunakan untuk mengenkripsi dan mendekripsi data. Memulai dan menjalankannya cukup sederhana untuk mulai mengenkripsi dan mendekripsi data. ## Antrian Pekerjaan -Antrian pekerjaan sangat membantu untuk memproses tugas secara asinkron. Ini bisa berupa mengirim email, memproses gambar, atau apa pun yang tidak perlu dilakukan secara real-time. +Antrian pekerjaan sangat membantu untuk memproses tugas secara asinkron. Ini bisa mengirim email, memproses gambar, atau apa pun yang tidak perlu dilakukan secara real time. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue adalah pustaka yang dapat digunakan untuk memproses pekerjaan secara asinkron. Ini dapat digunakan dengan beanstalkd, MySQL/MariaDB, SQLite, dan PostgreSQL. @@ -88,9 +89,9 @@ Sesi tidak terlalu berguna untuk API tetapi untuk membangun aplikasi web, sesi b Templating adalah inti dari aplikasi web apa pun dengan UI. Ada sejumlah mesin templating yang dapat digunakan dengan Flight. -- deprecated [flightphp/core View](/learn#views) - Ini adalah mesin templating dasar yang merupakan bagian dari inti. Tidak disarankan digunakan jika Anda memiliki lebih dari beberapa halaman di proyek Anda. +- deprecated [flightphp/core View](/learn#views) - Ini adalah mesin templating dasar yang merupakan bagian dari inti. Tidak direkomendasikan untuk digunakan jika Anda memiliki lebih dari beberapa halaman di proyek Anda. - [latte/latte](/awesome-plugins/latte) - Latte adalah mesin templating lengkap yang sangat mudah digunakan dan terasa lebih dekat dengan sintaks PHP daripada Twig atau Smarty. Ini juga sangat mudah untuk diperluas dan menambahkan filter dan fungsi Anda sendiri. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate adalah mesin template PHP yang kuat dengan kompilasi aset, pewarisan template, dan pemrosesan variabel. Fitur minifikasi CSS/JS otomatis, caching, pengkodean Base64, dan integrasi opsional dengan framework PHP Flight. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate adalah mesin template PHP yang kuat dengan kompilasi aset, pewarisan template, dan pemrosesan variabel. Fitur minifikasi CSS/JS otomatis, caching, pengkodean Base64, dan integrasi opsional dengan framework Flight PHP. ## Integrasi WordPress @@ -100,4 +101,4 @@ Ingin menggunakan Flight di proyek WordPress Anda? Ada plugin yang berguna untuk ## Berkontribusi -Punya plugin yang ingin dibagikan? Kirimkan pull request untuk menambahkannya ke daftar! \ No newline at end of file +Punya plugin yang ingin Anda bagikan? Ajukan pull request untuk menambahkannya ke daftar! \ No newline at end of file diff --git a/content/v3/id/awesome-plugins/jwt.md b/content/v3/id/awesome-plugins/jwt.md index 2349fab2..5558263a 100644 --- a/content/v3/id/awesome-plugins/jwt.md +++ b/content/v3/id/awesome-plugins/jwt.md @@ -1,4 +1,4 @@ -# Firebase JWT - Autentikasi JSON Web Token untuk Flight +# Firebase JWT - Autentikasi JSON Web Token JWT (JSON Web Tokens) adalah cara yang ringkas dan aman untuk URL untuk merepresentasikan klaim antara aplikasi Anda dan klien. Mereka sempurna untuk autentikasi API tanpa state—tidak perlu penyimpanan sesi di sisi server! Panduan ini menunjukkan cara mengintegrasikan [Firebase JWT](https://github.com/firebase/php-jwt) dengan Flight untuk autentikasi berbasis token yang aman. @@ -11,7 +11,7 @@ JSON Web Token adalah string yang berisi tiga bagian: 2. **Payload**: Data Anda (ID pengguna, peran, kedaluwarsa, dll.) 3. **Signature**: Tanda tangan kriptografis untuk memverifikasi keaslian -Contoh JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (terlihat seperti sampah, tapi ini data terstruktur!) +Contoh JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (terlihat seperti omong kosong, tapi itu data terstruktur!) ### Mengapa Menggunakan JWT? @@ -31,7 +31,7 @@ composer require firebase/php-jwt ## Penggunaan Dasar -Berikut adalah contoh cepat untuk membuat dan memverifikasi JWT: +Berikut contoh cepat untuk membuat dan memverifikasi JWT: ```php use Firebase\JWT\JWT; @@ -46,7 +46,7 @@ $payload = [ 'username' => 'johndoe', 'role' => 'admin', 'iat' => time(), // Diterbitkan pada - 'exp' => time() + 3600 // Berakhir dalam 1 jam + 'exp' => time() + 3600 // Kedaluwarsa dalam 1 jam ]; $jwt = JWT::encode($payload, $secretKey, 'HS256'); @@ -63,7 +63,7 @@ try { ## Middleware JWT untuk Flight (Pendekatan yang Direkomendasikan) -Cara paling umum dan berguna untuk menggunakan JWT dengan Flight adalah sebagai **middleware** untuk melindungi rute API Anda. Berikut adalah contoh lengkap yang siap produksi: +Cara paling umum dan berguna untuk menggunakan JWT dengan Flight adalah sebagai **middleware** untuk melindungi rute API Anda. Berikut contoh lengkap yang siap produksi: ### Langkah 1: Buat Kelas Middleware JWT @@ -128,7 +128,7 @@ return [ ]; // app/config/bootstrap.php atau index.php -// pastikan untuk menambahkan baris ini jika Anda ingin mengekspos konfigurasi ke app +// pastikan untuk menambahkan baris ini jika Anda ingin mengekspos konfigurasi ke aplikasi $app->set('config', $config); ``` @@ -145,7 +145,7 @@ Flight::route('GET /api/user/profile', function() { 'username' => $user->username, 'role' => $user->role ]); -})->addMiddleware( JwtMiddleware::class); +})->addMiddleware(JwtMiddleware::class); // Lindungi seluruh grup rute (lebih umum!) Flight::group('/api', function() { @@ -213,9 +213,9 @@ function validateUserCredentials($username, $password) { } ``` -### 2. Alur Refresh Token +### 2. Alur Pembaruan Token -Implementasikan sistem refresh token untuk sesi yang panjang umurnya: +Implementasikan sistem token pembaruan untuk sesi yang panjang: ```php Flight::route('POST /api/login', function() { @@ -224,7 +224,7 @@ Flight::route('POST /api/login', function() { $secretKey = Flight::get('config')['jwt_secret']; $refreshSecret = Flight::get('config')['jwt_refresh_secret']; - // Access token yang pendek umurnya (15 menit) + // Token akses jangka pendek (15 menit) $accessToken = JWT::encode([ 'user_id' => $user->id, 'type' => 'access', @@ -232,7 +232,7 @@ Flight::route('POST /api/login', function() { 'exp' => time() + (15 * 60) ], $secretKey, 'HS256'); - // Refresh token yang panjang umurnya (7 hari) + // Token pembaruan jangka panjang (7 hari) $refreshToken = JWT::encode([ 'user_id' => $user->id, 'type' => 'refresh', @@ -254,12 +254,12 @@ Flight::route('POST /api/refresh', function() { try { $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); - // Verifikasi ini adalah refresh token + // Verifikasi ini adalah token pembaruan if ($decoded->type !== 'refresh') { Flight::jsonHalt(['error' => 'Tipe token tidak valid'], 401); } - // Hasilkan access token baru + // Hasilkan token akses baru $secretKey = Flight::get('config')['jwt_secret']; $accessToken = JWT::encode([ 'user_id' => $decoded->user_id, @@ -274,7 +274,7 @@ Flight::route('POST /api/refresh', function() { ]); } catch (Exception $e) { - Flight::jsonHalt(['error' => 'Refresh token tidak valid'], 401); + Flight::jsonHalt(['error' => 'Token pembaruan tidak valid'], 401); } }); ``` @@ -318,9 +318,9 @@ Flight::route('DELETE /api/users/@id', function($id) { ]); ``` -### 4. API Publik dengan Rate Limiting berdasarkan Pengguna +### 4. API Publik dengan Batasan Tingkat Berdasarkan Pengguna -Gunakan JWT untuk melacak dan membatasi laju pengguna tanpa sesi: +Gunakan JWT untuk melacak dan membatasi tingkat pengguna tanpa sesi: ```php class RateLimitMiddleware { @@ -334,7 +334,7 @@ class RateLimitMiddleware { $requests = Flight::cache()->get($cacheKey, 0); if ($requests >= 100) { // 100 permintaan per jam - Flight::jsonHalt(['error' => 'Batas laju terlampaui'], 429); + Flight::jsonHalt(['error' => 'Batas tingkat terlampaui'], 429); } Flight::cache()->set($cacheKey, $requests + 1, 3600); @@ -362,7 +362,7 @@ echo $secretKey; // Simpan ini di file .env Anda! // JWT_SECRET=your-base64-encoded-secret-here // JWT_REFRESH_SECRET=another-base64-encoded-secret-here -// Anda juga bisa menggunakan file app/config/config.php untuk menyimpan rahasia Anda +// Anda juga dapat menggunakan file app/config/config.php untuk menyimpan rahasia Anda // pastikan file konfigurasi tidak di-commit ke kontrol versi // return [ // 'jwt_secret' => 'your-base64-encoded-secret-here', @@ -373,13 +373,13 @@ echo $secretKey; // Simpan ini di file .env Anda! $secretKey = getenv('JWT_SECRET'); ``` -### 3. Atur Waktu Kedaluwarsa yang Sesuai +### 3. Tetapkan Waktu Kedaluwarsa yang Sesuai ```php -// Praktik baik: access token yang pendek umurnya +// Praktik baik: token akses jangka pendek 'exp' => time() + (15 * 60) // 15 menit -// Untuk refresh token: kedaluwarsa lebih lama +// Untuk token pembaruan: kedaluwarsa lebih panjang 'exp' => time() + (7 * 24 * 60 * 60) // 7 hari ``` @@ -394,8 +394,8 @@ Selalu validasi klaim yang Anda pedulikan: ```php $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); -// Pemeriksaan kedaluwarsa ditangani secara otomatis oleh library -// Tapi Anda bisa menambahkan validasi kustom: +// Periksa kedaluwarsa ditangani secara otomatis oleh library +// Tapi Anda dapat menambahkan validasi kustom: if ($decoded->iat > time()) { throw new Exception('Token digunakan sebelum diterbitkan'); } @@ -405,7 +405,7 @@ if (isset($decoded->nbf) && $decoded->nbf > time()) { } ``` -### 6. Pertimbangkan Blacklisting Token untuk Logout +### 6. Pertimbangkan Daftar Hitam Token untuk Logout Untuk keamanan ekstra, pertahankan daftar hitam token yang dibatalkan: @@ -474,17 +474,17 @@ $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); ## Pemecahan Masalah ### Kesalahan "Token kedaluwarsa" -Klaim `exp` token Anda sudah lewat. Terbitkan token baru atau implementasikan refresh token. +Klaim `exp` token Anda di masa lalu. Terbitkan token baru atau implementasikan pembaruan token. ### "Verifikasi tanda tangan gagal" - Anda menggunakan kunci rahasia yang berbeda untuk dekode daripada yang digunakan untuk encode - Token telah dimanipulasi -- Perbedaan jam antara server (tambahkan buffer leeway) +- Penyimpangan jam antara server (tambahkan buffer leeway) ```php use Firebase\JWT\JWT; -JWT::$leeway = 60; // Izinkan 60 detik perbedaan jam +JWT::$leeway = 60; // Izinkan 60 detik penyimpangan jam $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); ``` @@ -506,17 +506,17 @@ Library Firebase JWT menyediakan metode inti ini: - `JWT::encode(array $payload, string $key, string $alg)`: Membuat JWT dari payload - `JWT::decode(string $jwt, Key $key)`: Mendekode dan memverifikasi JWT -- `JWT::urlsafeB64Encode(string $input)`: Encoding Base64 URL-safe -- `JWT::urlsafeB64Decode(string $input)`: Decoding Base64 URL-safe -- `JWT::$leeway`: Properti statis untuk mengatur leeway waktu untuk validasi (dalam detik) +- `JWT::urlsafeB64Encode(string $input)`: Encoding Base64 aman URL +- `JWT::urlsafeB64Decode(string $input)`: Decoding Base64 aman URL +- `JWT::$leeway`: Properti statis untuk menetapkan leeway waktu untuk validasi (dalam detik) ## Mengapa Menggunakan Library Ini? -- **Standar Industri**: Firebase JWT adalah library JWT paling populer dan tepercaya untuk PHP +- **Standar Industri**: Firebase JWT adalah library JWT paling populer dan tepercaya secara luas untuk PHP - **Pemeliharaan Aktif**: Dipelihara oleh tim Google/Firebase - **Fokus Keamanan**: Pembaruan rutin dan patch keamanan - **API Sederhana**: Mudah dipahami dan diimplementasikan -- **Dokumentasi Lengkap**: Dokumentasi ekstensif dan dukungan komunitas +- **Didokumentasikan dengan Baik**: Dokumentasi ekstensif dan dukungan komunitas - **Fleksibel**: Mendukung beberapa algoritma dan opsi yang dapat dikonfigurasi ## Lihat Juga diff --git a/content/v3/id/awesome-plugins/runway.md b/content/v3/id/awesome-plugins/runway.md index ed850f71..bf6333c9 100644 --- a/content/v3/id/awesome-plugins/runway.md +++ b/content/v3/id/awesome-plugins/runway.md @@ -1,6 +1,6 @@ # Runway -Runway adalah aplikasi CLI yang membantu Anda mengelola aplikasi Flight Anda. Ini dapat menghasilkan controller, menampilkan semua rute, dan banyak lagi. Ini didasarkan pada pustaka [adhocore/php-cli](https://github.com/adhocore/php-cli) yang luar biasa. +Runway adalah aplikasi CLI yang membantu Anda mengelola aplikasi Flight Anda. Ini dapat menghasilkan controller, menampilkan semua rute, dan lainnya. Ini didasarkan pada pustaka [adhocore/php-cli](https://github.com/adhocore/php-cli) yang luar biasa. Klik [di sini](https://github.com/flightphp/runway) untuk melihat kode. @@ -27,11 +27,11 @@ return [ ]; ``` -> **CATATAN** - Mulai dari **v1.2.0**, `.runway-config.json` sudah usang. Silakan migrasi konfigurasi Anda ke `app/config/config.php`. Anda dapat melakukannya dengan mudah menggunakan perintah `php runway config:migrate`. +> **CATATAN** - Mulai dari **v1.2.0**, `.runway-config.json` sudah tidak digunakan lagi. Silakan migrasikan konfigurasi Anda ke `app/config/config.php`. Anda dapat melakukan ini dengan mudah menggunakan perintah `php runway config:migrate`. ### Deteksi Root Proyek -Runway cukup pintar untuk mendeteksi root proyek Anda, bahkan jika Anda menjalankannya dari subdirektori. Ini mencari indikator seperti `composer.json`, `.git`, atau `app/config/config.php` untuk menentukan di mana root proyek berada. Ini berarti Anda dapat menjalankan perintah Runway dari mana saja di proyek Anda! +Runway cukup pintar untuk mendeteksi root proyek Anda, bahkan jika Anda menjalankannya dari subdirektori. Ini mencari indikator seperti `composer.json`, `.git`, atau `app/config/config.php` untuk menentukan di mana root proyek berada. Ini berarti Anda dapat menjalankan perintah Runway dari mana saja di proyek Anda! ## Penggunaan @@ -50,7 +50,7 @@ php runway ### Bantuan Perintah -Untuk perintah apa pun, Anda dapat meneruskan flag `--help` untuk mendapatkan informasi lebih lanjut tentang cara menggunakan perintah tersebut. +Untuk perintah apa pun, Anda dapat menambahkan flag `--help` untuk mendapatkan informasi lebih lanjut tentang cara menggunakan perintah tersebut. ```bash php runway routes --help @@ -122,7 +122,7 @@ Ini akan menampilkan semua rute yang saat ini terdaftar dengan Flight. php runway routes ``` -Jika Anda ingin hanya melihat rute tertentu, Anda dapat meneruskan flag untuk memfilter rute. +Jika Anda ingin hanya melihat rute tertentu, Anda dapat menambahkan flag untuk memfilter rute. ```bash # Tampilkan hanya rute GET @@ -136,9 +136,9 @@ php runway routes --post ## Menambahkan Perintah Kustom ke Runway -Jika Anda sedang membuat paket untuk Flight, atau ingin menambahkan perintah kustom sendiri ke proyek Anda, Anda dapat melakukannya dengan membuat direktori `src/commands/`, `flight/commands/`, `app/commands/`, atau `commands/` untuk proyek/paket Anda. Jika Anda memerlukan kustomisasi lebih lanjut, lihat bagian di bawah tentang Konfigurasi. +Jika Anda sedang membuat paket untuk Flight, atau ingin menambahkan perintah kustom sendiri ke proyek Anda, Anda dapat melakukannya dengan membuat direktori `src/commands/`, `flight/commands/`, `app/commands/`, atau `commands/` untuk proyek/paket Anda. Jika Anda membutuhkan penyesuaian lebih lanjut, lihat bagian di bawah tentang Konfigurasi. -Untuk membuat perintah, Anda cukup memperluas kelas `AbstractBaseCommand`, dan mengimplementasikan setidaknya metode `__construct` dan metode `execute`. +Untuk membuat perintah, Anda cukup memperluas kelas `AbstractBaseCommand`, dan mengimplementasikan minimal metode `__construct` dan metode `execute`. ```php 'app/', - // Ini adalah direktori di mana file indeks root Anda berada + // Ini adalah direktori di mana file index root Anda berada 'index_root' => 'public/', - // Ini adalah path ke root proyek lain + // Ini adalah path ke root proyek lainnya 'root_paths' => [ '/home/user/different-project', '/var/www/another-project' @@ -254,7 +254,7 @@ return [ ### Mengakses Konfigurasi -Jika Anda perlu mengakses nilai konfigurasi secara efektif, Anda dapat mengaksesnya melalui metode `__construct` atau metode `app()`. Penting juga untuk dicatat bahwa jika Anda memiliki file `app/config/services.php`, layanan-layanan tersebut juga akan tersedia untuk perintah Anda. +Jika Anda perlu mengakses nilai konfigurasi secara efektif, Anda dapat mengaksesnya melalui metode `__construct` atau metode `app()`. Penting juga untuk dicatat bahwa jika Anda memiliki file `app/config/services.php`, layanan tersebut juga akan tersedia untuk perintah Anda. ```php public function execute() @@ -273,7 +273,7 @@ public function execute() ## Wrapper Pembantu AI -Runway memiliki beberapa wrapper pembantu yang memudahkan AI untuk menghasilkan perintah. Anda dapat menggunakan `addOption` dan `addArgument` dengan cara yang mirip dengan Symfony Console. Ini membantu jika Anda menggunakan alat AI untuk menghasilkan perintah Anda. +Runway memiliki beberapa wrapper pembantu yang membuat lebih mudah bagi AI untuk menghasilkan perintah. Anda dapat menggunakan `addOption` dan `addArgument` dengan cara yang mirip dengan Symfony Console. Ini membantu jika Anda menggunakan alat AI untuk menghasilkan perintah Anda. ```php public function __construct(array $config) diff --git a/content/v3/id/learn/autoloading.md b/content/v3/id/learn/autoloading.md index b0b90e72..eefd25ad 100644 --- a/content/v3/id/learn/autoloading.md +++ b/content/v3/id/learn/autoloading.md @@ -1,18 +1,18 @@ # Autoloading -## Gambaran Umum +## Ringkasan -Autoloading adalah konsep di PHP di mana Anda menentukan direktori atau direktori untuk memuat kelas dari. Ini jauh lebih bermanfaat daripada menggunakan `require` atau `include` untuk memuat kelas. Ini juga merupakan persyaratan untuk menggunakan paket Composer. +Autoloading adalah konsep dalam PHP di mana Anda menentukan direktori atau direktori untuk memuat kelas dari. Ini jauh lebih bermanfaat daripada menggunakan `require` atau `include` untuk memuat kelas. Ini juga merupakan persyaratan untuk menggunakan paket Composer. ## Pemahaman -Secara default, kelas `Flight` apa pun dimuat secara otomatis untuk Anda berkat composer. Namun, jika Anda ingin memuat kelas Anda sendiri secara otomatis, Anda dapat menggunakan metode `Flight::path()` untuk menentukan direktori untuk memuat kelas dari. +Secara default, kelas `Flight` apa pun dimuat otomatis untuk Anda berkat composer. Namun, jika Anda ingin memuat otomatis kelas Anda sendiri, Anda dapat menggunakan metode `Flight::path()` untuk menentukan direktori untuk memuat kelas dari. Menggunakan autoloader dapat membantu menyederhanakan kode Anda secara signifikan. Alih-alih memiliki file yang dimulai dengan berbagai pernyataan `include` atau `require` di bagian atas untuk menangkap semua kelas yang digunakan dalam file tersebut, Anda dapat secara dinamis memanggil kelas Anda dan mereka akan disertakan secara otomatis. ## Penggunaan Dasar -Misalkan kita memiliki pohon direktori seperti berikut: +Misalkan kita memiliki struktur direktori seperti berikut: ```text # Contoh path @@ -30,7 +30,7 @@ Misalkan kita memiliki pohon direktori seperti berikut: └── index.php ``` -Anda mungkin telah memperhatikan bahwa ini adalah struktur file yang sama dengan situs dokumentasi ini. +Anda mungkin memperhatikan bahwa ini adalah struktur file yang sama dengan situs dokumentasi ini. Anda dapat menentukan setiap direktori untuk dimuat seperti ini: @@ -51,7 +51,7 @@ Flight::path(__DIR__.'/../app/utils/'); // tidak diperlukan namespacing -// Semua kelas yang dimuat secara otomatis disarankan menggunakan Pascal Case (setiap kata dikapitalisasi, tanpa spasi) +// Semua kelas yang dimuat otomatis disarankan menggunakan Pascal Case (setiap kata dikapitalisasi, tanpa spasi) class MyController { public function index() { @@ -74,7 +74,7 @@ Jika Anda memiliki namespace, sebenarnya sangat mudah untuk mengimplementasikann Flight::path(__DIR__.'/../'); ``` -Sekarang ini adalah tampilan controller Anda. Lihat contoh di bawah ini, tetapi perhatikan komentar untuk informasi penting. +Sekarang ini adalah tampilan controller Anda. Lihat contoh di bawah, tapi perhatikan komentar untuk informasi penting. ```php /** @@ -84,10 +84,10 @@ Sekarang ini adalah tampilan controller Anda. Lihat contoh di bawah ini, tetapi // namespace diperlukan // namespace sama dengan struktur direktori // namespace harus mengikuti case yang sama dengan struktur direktori -// namespace dan direktori tidak boleh memiliki underscore (kecuali Loader::setV2ClassLoading(false) diatur) +// namespace dan direktori tidak boleh memiliki underscore (kecuali Loader::setV2ClassLoading(false) disetel) namespace app\controllers; -// Semua kelas yang dimuat secara otomatis disarankan menggunakan Pascal Case (setiap kata dikapitalisasi, tanpa spasi) +// Semua kelas yang dimuat otomatis disarankan menggunakan Pascal Case (setiap kata dikapitalisasi, tanpa spasi) // Mulai dari 3.7.2, Anda dapat menggunakan Pascal_Snake_Case untuk nama kelas Anda dengan menjalankan Loader::setV2ClassLoading(false); class MyController { @@ -97,7 +97,7 @@ class MyController { } ``` -Dan jika Anda ingin memuat kelas di direktori utils Anda secara otomatis, Anda akan melakukan hal yang sama secara dasar: +Dan jika Anda ingin memuat otomatis kelas di direktori utils Anda, Anda pada dasarnya melakukan hal yang sama: ```php @@ -106,7 +106,7 @@ Dan jika Anda ingin memuat kelas di direktori utils Anda secara otomatis, Anda a */ // namespace harus cocok dengan struktur direktori dan case (perhatikan direktori UTILS semua huruf kapital -// seperti di pohon file di atas) +// seperti dalam pohon file di atas) namespace app\UTILS; class ArrayHelperUtil { @@ -117,11 +117,11 @@ class ArrayHelperUtil { } ``` -## Underscores di Nama Kelas +## Underscores dalam Nama Kelas Mulai dari 3.7.2, Anda dapat menggunakan Pascal_Snake_Case untuk nama kelas Anda dengan menjalankan `Loader::setV2ClassLoading(false);`. -Ini akan memungkinkan Anda menggunakan underscore di nama kelas Anda. -Ini tidak disarankan, tetapi tersedia untuk mereka yang membutuhkannya. +Ini akan memungkinkan Anda menggunakan underscore dalam nama kelas Anda. +Ini tidak disarankan, tapi tersedia untuk mereka yang membutuhkannya. ```php use flight\core\Loader; @@ -154,25 +154,25 @@ class My_Controller { - [Mengapa Framework?](/learn/why-frameworks) - Memahami manfaat menggunakan framework seperti Flight. ## Pemecahan Masalah -- Jika Anda tidak dapat mengetahui mengapa kelas namespaced Anda tidak ditemukan, ingatlah untuk menggunakan `Flight::path()` ke direktori root di proyek Anda, bukan direktori `app/` atau `src/` atau setara. +- Jika Anda tidak bisa memahami mengapa kelas namespaced Anda tidak ditemukan, ingatlah untuk menggunakan `Flight::path()` ke direktori root di proyek Anda, bukan direktori `app/` atau `src/` atau setara. ### Kelas Tidak Ditemukan (autoloading tidak berfungsi) -Ada beberapa alasan mengapa ini bisa terjadi. Di bawah ini beberapa contoh tetapi pastikan Anda juga memeriksa bagian [autoloading](/learn/autoloading). +Ada beberapa alasan mengapa ini bisa terjadi. Di bawah ini beberapa contoh tapi pastikan Anda juga memeriksa bagian [autoloading](/learn/autoloading). #### Nama File Salah Yang paling umum adalah nama kelas tidak cocok dengan nama file. Jika Anda memiliki kelas bernama `MyClass` maka file harus bernama `MyClass.php`. Jika Anda memiliki kelas bernama `MyClass` dan file bernama `myclass.php` -maka autoloader tidak akan dapat menemukannya. +maka autoloader tidak akan bisa menemukannya. #### Namespace Salah Jika Anda menggunakan namespace, maka namespace harus cocok dengan struktur direktori. ```php -// ...code... +// ...kode... -// jika MyController Anda berada di direktori app/controllers dan bernamespace +// jika MyController Anda berada di direktori app/controllers dan namespaced // ini tidak akan berfungsi. Flight::route('/hello', 'MyController->hello'); @@ -191,7 +191,7 @@ Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); #### `path()` tidak didefinisikan -Di aplikasi skeleton, ini didefinisikan di dalam file `config.php`, tetapi agar kelas Anda ditemukan, Anda perlu memastikan bahwa metode `path()` +Dalam aplikasi skeleton, ini didefinisikan di dalam file `config.php`, tapi agar kelas Anda ditemukan, Anda perlu memastikan bahwa metode `path()` didefinisikan (mungkin ke root direktori Anda) sebelum Anda mencoba menggunakannya. ```php diff --git a/content/v3/id/learn/learn.md b/content/v3/id/learn/learn.md index 93767e26..7ff39a12 100644 --- a/content/v3/id/learn/learn.md +++ b/content/v3/id/learn/learn.md @@ -3,7 +3,7 @@ Flight adalah framework PHP yang cepat, sederhana, dan dapat diperluas. Ini sangat serbaguna dan dapat digunakan untuk membangun berbagai jenis aplikasi web. Ini dibangun dengan prinsip kesederhanaan dan ditulis dengan cara yang mudah dipahami dan digunakan. -> **Catatan:** Anda akan melihat contoh yang menggunakan `Flight::` sebagai variabel statis dan beberapa yang menggunakan objek Engine `$app->`. Keduanya dapat digunakan secara bergantian. `$app` dan `$this->app` di controller/middleware adalah pendekatan yang direkomendasikan oleh tim Flight. +> **Catatan:** Anda akan melihat contoh yang menggunakan `Flight::` sebagai variabel statis dan beberapa yang menggunakan objek Engine `$app->`. Keduanya dapat digunakan secara bergantian. `$app` dan `$this->app` dalam controller/middleware adalah pendekatan yang direkomendasikan oleh tim Flight. ## Komponen Inti @@ -13,15 +13,15 @@ Pelajari cara mengelola rute untuk aplikasi web Anda. Ini juga mencakup pengelom ### [Middleware](/learn/middleware) -Pelajari cara menggunakan middleware untuk memfilter permintaan dan respons di aplikasi Anda. +Pelajari cara menggunakan middleware untuk memfilter permintaan dan respons dalam aplikasi Anda. ### [Autoloading](/learn/autoloading) -Pelajari cara memuat otomatis kelas Anda sendiri di aplikasi Anda. +Pelajari cara autoload kelas Anda sendiri dalam aplikasi Anda. ### [Requests](/learn/requests) -Pelajari cara menangani permintaan dan respons di aplikasi Anda. +Pelajari cara menangani permintaan dan respons dalam aplikasi Anda. ### [Responses](/learn/responses) @@ -53,21 +53,25 @@ Pelajari cara menambahkan hook event ke metode Anda dan metode framework interna ### [Dependency Injection Container (DIC)](/learn/dependency-injection-container) -Pelajari cara menggunakan wadah injeksi dependensi (DIC) untuk mengelola dependensi aplikasi Anda. +Pelajari cara menggunakan container injeksi dependensi (DIC) untuk mengelola dependensi aplikasi Anda. ## Kelas Utilitas ### [Collections](/learn/collections) -Koleksi digunakan untuk menyimpan data dan dapat diakses sebagai array atau objek untuk kemudahan penggunaan. +Collections digunakan untuk menyimpan data dan dapat diakses sebagai array atau objek untuk kemudahan penggunaan. ### [JSON Wrapper](/learn/json) Ini memiliki beberapa fungsi sederhana untuk membuat pengkodean dan dekode JSON Anda konsisten. -### [PDO Wrapper](/learn/pdo-wrapper) +### [SimplePdo](/learn/simple-pdo) -PDO terkadang bisa menimbulkan lebih banyak masalah daripada yang diperlukan. Kelas wrapper sederhana ini dapat membuat interaksi dengan database Anda jauh lebih mudah. +PDO terkadang bisa menambah sakit kepala yang tidak perlu. SimplePdo adalah kelas pembantu PDO modern dengan metode yang nyaman seperti `insert()`, `update()`, `delete()`, dan `transaction()` untuk membuat operasi database jauh lebih mudah. + +### [PdoWrapper](/learn/pdo-wrapper) (Deprecated) + +Wrapper PDO asli sudah deprecated sejak v3.18.0. Silakan gunakan [SimplePdo](/learn/simple-pdo) sebagai gantinya. ### [Uploaded File Handler](/learn/uploaded-file) @@ -79,9 +83,9 @@ Kelas sederhana untuk membantu mengelola file yang diunggah dan memindahkannya k Berikut adalah artikel singkat tentang mengapa Anda harus menggunakan framework. Ini ide bagus untuk memahami manfaat menggunakan framework sebelum Anda mulai menggunakannya. -Selain itu, tutorial yang sangat baik telah dibuat oleh [@lubiana](https://git.php.fail/lubiana). Meskipun tidak membahas secara mendalam tentang Flight secara khusus, +Selain itu, tutorial yang sangat baik telah dibuat oleh [@lubiana](https://git.php.fail/lubiana). Meskipun tidak membahas secara mendetail tentang Flight secara khusus, panduan ini akan membantu Anda memahami beberapa konsep utama seputar framework dan mengapa mereka bermanfaat untuk digunakan. -Anda dapat menemukan tutorial [di sini](https://git.php.fail/lubiana/no-framework-tutorial/src/branch/master/README.md). +Anda dapat menemukan tutorial tersebut [di sini](https://git.php.fail/lubiana/no-framework-tutorial/src/branch/master/README.md). ### [Flight Compared to Other Frameworks](/learn/flight-vs-another-framework) @@ -91,11 +95,11 @@ Jika Anda bermigrasi dari framework lain seperti Laravel, Slim, Fat-Free, atau S ### [Unit Testing](/learn/unit-testing) -Ikuti panduan ini untuk mempelajari cara melakukan unit testing kode Flight Anda agar menjadi kokoh. +Ikuti panduan ini untuk mempelajari cara melakukan unit testing kode Flight Anda agar kokoh. ### [AI & Developer Experience](/learn/ai) -Pelajari bagaimana Flight bekerja dengan alat AI dan alur kerja pengembang modern untuk membantu Anda mengkode lebih cepat dan lebih cerdas. +Pelajari bagaimana Flight bekerja dengan alat AI dan alur kerja pengembang modern untuk membantu Anda mengkode lebih cepat dan lebih pintar. ### [Migrating v2 -> v3](/learn/migrating-to-v3) diff --git a/content/v3/id/learn/pdo_wrapper.md b/content/v3/id/learn/pdo_wrapper.md index 60c4ce76..021b5df4 100644 --- a/content/v3/id/learn/pdo_wrapper.md +++ b/content/v3/id/learn/pdo_wrapper.md @@ -1,14 +1,18 @@ # Kelas Pembantu PDO PdoWrapper +> **PERINGATAN** +> +> **Usang:** `PdoWrapper` sudah usang sejak Flight v3.18.0. Ini tidak akan dihapus di versi mendatang, tetapi akan dipelihara untuk kompatibilitas mundur. Silakan gunakan [SimplePdo](/learn/simple-pdo) sebagai gantinya, yang menawarkan fungsionalitas yang sama ditambah metode pembantu tambahan untuk operasi database umum. + ## Gambaran Umum Kelas `PdoWrapper` di Flight adalah pembantu yang ramah untuk bekerja dengan database menggunakan PDO. Ini menyederhanakan tugas database umum, menambahkan beberapa metode yang berguna untuk mengambil hasil, dan mengembalikan hasil sebagai [Collections](/learn/collections) untuk akses yang mudah. Ini juga mendukung pencatatan query dan pemantauan kinerja aplikasi (APM) untuk kasus penggunaan lanjutan. ## Pemahaman -Bekerja dengan database di PHP bisa sedikit verbose, terutama saat menggunakan PDO secara langsung. `PdoWrapper` memperluas PDO dan menambahkan metode yang membuat querying, fetching, dan penanganan hasil jauh lebih mudah. Alih-alih mengelola pernyataan yang disiapkan dan mode fetch, Anda mendapatkan metode sederhana untuk tugas umum, dan setiap baris dikembalikan sebagai Collection, sehingga Anda dapat menggunakan notasi array atau objek. +Bekerja dengan database di PHP bisa agak verbose, terutama saat menggunakan PDO secara langsung. `PdoWrapper` memperluas PDO dan menambahkan metode yang membuat querying, fetching, dan penanganan hasil jauh lebih mudah. Alih-alih mengelola pernyataan yang disiapkan dan mode fetch, Anda mendapatkan metode sederhana untuk tugas umum, dan setiap baris dikembalikan sebagai Collection, sehingga Anda bisa menggunakan notasi array atau objek. -Anda dapat mendaftarkan `PdoWrapper` sebagai layanan bersama di Flight, dan kemudian menggunakannya di mana saja di aplikasi Anda melalui `Flight::db()`. +Anda bisa mendaftarkan `PdoWrapper` sebagai layanan bersama di Flight, dan kemudian menggunakannya di mana saja di aplikasi Anda melalui `Flight::db()`. ## Penggunaan Dasar @@ -27,7 +31,7 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ ]); ``` -Sekarang Anda dapat menggunakan `Flight::db()` di mana saja untuk mendapatkan koneksi database Anda. +Sekarang Anda bisa menggunakan `Flight::db()` di mana saja untuk mendapatkan koneksi database Anda. ### Menjalankan Query @@ -45,7 +49,7 @@ while ($row = $statement->fetch()) { } ``` -Anda juga dapat menggunakannya untuk penulisan: +Anda juga bisa menggunakannya untuk penulisan: ```php $db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); @@ -92,7 +96,7 @@ foreach ($users as $user) { ### Menggunakan Placeholder `IN()` -Anda dapat menggunakan satu `?` tunggal dalam klausa `IN()` dan meneruskan array atau string yang dipisahkan koma: +Anda bisa menggunakan satu `?` tunggal dalam klausa `IN()` dan meneruskan array atau string yang dipisahkan koma: ```php $ids = [1, 2, 3]; @@ -109,17 +113,17 @@ Jika Anda ingin melacak kinerja query, aktifkan pelacakan APM saat mendaftarkan: ```php Flight::register('db', \flight\database\PdoWrapper::class, [ - 'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [/* options */], true // param terakhir mengaktifkan APM + 'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [/* options */], true // parameter terakhir mengaktifkan APM ]); ``` -Setelah menjalankan query, Anda dapat mencatatnya secara manual tetapi APM akan mencatatnya secara otomatis jika diaktifkan: +Setelah menjalankan query, Anda bisa mencatatnya secara manual tetapi APM akan mencatatnya secara otomatis jika diaktifkan: ```php Flight::db()->logQueries(); ``` -Ini akan memicu sebuah event (`flight.db.queries`) dengan metrik koneksi dan query, yang dapat Anda dengarkan menggunakan sistem event Flight. +Ini akan memicu event (`flight.db.queries`) dengan metrik koneksi dan query, yang bisa Anda dengarkan menggunakan sistem event Flight. ### Contoh Lengkap @@ -134,10 +138,10 @@ Flight::route('/users', function () { echo $user['name']; } - // Dapatkan satu pengguna tunggal + // Dapatkan satu pengguna $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); - // Dapatkan satu nilai tunggal + // Dapatkan satu nilai $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); // Sintaks IN() khusus diff --git a/content/v3/id/learn/simple_pdo.md b/content/v3/id/learn/simple_pdo.md new file mode 100644 index 00000000..9d9412a8 --- /dev/null +++ b/content/v3/id/learn/simple_pdo.md @@ -0,0 +1,320 @@ +# Kelas Pembantu SimplePdo PDO + +## Gambaran Umum + +Kelas `SimplePdo` di Flight adalah pembantu modern dan kaya fitur untuk bekerja dengan database menggunakan PDO. Ia memperluas `PdoWrapper` dan menambahkan metode pembantu yang nyaman untuk operasi database umum seperti `insert()`, `update()`, `delete()`, dan transaksi. Ia menyederhanakan tugas database, mengembalikan hasil sebagai [Collections](/learn/collections) untuk akses mudah, dan mendukung pencatatan query serta pemantauan kinerja aplikasi (APM) untuk kasus penggunaan lanjutan. + +## Pemahaman + +Kelas `SimplePdo` dirancang untuk membuat bekerja dengan database di PHP menjadi jauh lebih mudah. Daripada mengelola pernyataan yang disiapkan, mode pengambilan, dan operasi SQL yang verbose, Anda mendapatkan metode yang bersih dan sederhana untuk tugas umum. Setiap baris dikembalikan sebagai Collection, sehingga Anda dapat menggunakan notasi array (`$row['name']`) dan notasi objek (`$row->name`). + +Kelas ini adalah superset dari `PdoWrapper`, yang berarti ia mencakup semua fungsionalitas `PdoWrapper` ditambah metode pembantu tambahan yang membuat kode Anda lebih bersih dan mudah dipelihara. Jika Anda saat ini menggunakan `PdoWrapper`, upgrade ke `SimplePdo` adalah hal yang sederhana karena ia memperluas `PdoWrapper`. + +Anda dapat mendaftarkan `SimplePdo` sebagai layanan bersama di Flight, dan kemudian menggunakannya di mana saja di aplikasi Anda melalui `Flight::db()`. + +## Penggunaan Dasar + +### Mendaftarkan SimplePdo + +Pertama, daftarkan kelas `SimplePdo` dengan Flight: + +```php +Flight::register('db', \flight\database\SimplePdo::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 + ] +]); +``` + +> **CATATAN** +> +> Jika Anda tidak menentukan `PDO::ATTR_DEFAULT_FETCH_MODE`, `SimplePdo` akan secara otomatis mengaturnya ke `PDO::FETCH_ASSOC` untuk Anda. + +Sekarang Anda dapat menggunakan `Flight::db()` di mana saja untuk mendapatkan koneksi database Anda. + +### Menjalankan Query + +#### `runQuery()` + +`function runQuery(string $sql, array $params = []): PDOStatement` + +Gunakan ini untuk INSERT, UPDATE, atau ketika Anda ingin mengambil hasil secara manual: + +```php +$db = Flight::db(); +$statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']); +while ($row = $statement->fetch()) { + // $row adalah array +} +``` + +Anda juga dapat menggunakannya untuk penulisan: + +```php +$db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); +$db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]); +``` + +#### `fetchField()` + +`function fetchField(string $sql, array $params = []): mixed` + +Dapatkan satu nilai tunggal dari database: + +```php +$count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']); +``` + +#### `fetchRow()` + +`function fetchRow(string $sql, array $params = []): ?Collection` + +Dapatkan satu baris sebagai Collection (akses array/objek): + +```php +$user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); +echo $user['name']; +// atau +echo $user->name; +``` + +> **TIPS** +> +> `SimplePdo` secara otomatis menambahkan `LIMIT 1` ke query `fetchRow()` jika belum ada, membuat query Anda lebih efisien. + +#### `fetchAll()` + +`function fetchAll(string $sql, array $params = []): array` + +Dapatkan semua baris sebagai array dari Collections: + +```php +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); +foreach ($users as $user) { + echo $user['name']; + // atau + echo $user->name; +} +``` + +#### `fetchColumn()` + +`function fetchColumn(string $sql, array $params = []): array` + +Ambil satu kolom sebagai array: + +```php +$ids = Flight::db()->fetchColumn("SELECT id FROM users WHERE active = ?", [1]); +// Mengembalikan: [1, 2, 3, 4, 5] +``` + +#### `fetchPairs()` + +`function fetchPairs(string $sql, array $params = []): array` + +Ambil hasil sebagai pasangan kunci-nilai (kolom pertama sebagai kunci, kedua sebagai nilai): + +```php +$userNames = Flight::db()->fetchPairs("SELECT id, name FROM users"); +// Mengembalikan: [1 => 'John', 2 => 'Jane', 3 => 'Bob'] +``` + +### Menggunakan Placeholder `IN()` + +Anda dapat menggunakan satu `?` tunggal dalam klausa `IN()` dan meneruskan array: + +```php +$ids = [1, 2, 3]; +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); +``` + +## Metode Pembantu + +Salah satu keunggulan utama `SimplePdo` dibandingkan `PdoWrapper` adalah penambahan metode pembantu yang nyaman untuk operasi database umum. + +### `insert()` + +`function insert(string $table, array $data): string` + +Masukkan satu atau lebih baris dan kembalikan ID sisipan terakhir. + +**Sisipan tunggal:** + +```php +$id = Flight::db()->insert('users', [ + 'name' => 'John', + 'email' => 'john@example.com' +]); +``` + +**Sisipan massal:** + +```php +$id = Flight::db()->insert('users', [ + ['name' => 'John', 'email' => 'john@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'], +]); +``` + +### `update()` + +`function update(string $table, array $data, string $where, array $whereParams = []): int` + +Perbarui baris dan kembalikan jumlah baris yang terpengaruh: + +```php +$affected = Flight::db()->update( + 'users', + ['name' => 'Jane', 'email' => 'jane@example.com'], + 'id = ?', + [1] +); +``` + +> **CATATAN** +> +> `rowCount()` SQLite mengembalikan jumlah baris di mana data benar-benar berubah. Jika Anda memperbarui baris dengan nilai yang sama yang sudah dimilikinya, `rowCount()` akan mengembalikan 0. Ini berbeda dari perilaku MySQL saat menggunakan `PDO::MYSQL_ATTR_FOUND_ROWS`. + +### `delete()` + +`function delete(string $table, string $where, array $whereParams = []): int` + +Hapus baris dan kembalikan jumlah baris yang dihapus: + +```php +$deleted = Flight::db()->delete('users', 'id = ?', [1]); +``` + +### `transaction()` + +`function transaction(callable $callback): mixed` + +Jalankan callback dalam transaksi. Transaksi secara otomatis melakukan commit pada sukses atau rollback pada kesalahan: + +```php +$result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John']); + $db->insert('logs', ['action' => 'user_created']); + return $db->lastInsertId(); +}); +``` + +Jika ada pengecualian yang dilemparkan dalam callback, transaksi secara otomatis di-rollback dan pengecualian dilemparkan kembali. + +## Penggunaan Lanjutan + +### Pencatatan Query & APM + +Jika Anda ingin melacak kinerja query, aktifkan pelacakan APM saat mendaftarkan: + +```php +Flight::register('db', \flight\database\SimplePdo::class, [ + 'mysql:host=localhost;dbname=cool_db_name', + 'user', + 'pass', + [/* opsi PDO */], + [ + 'trackApmQueries' => true, + 'maxQueryMetrics' => 1000 + ] +]); +``` + +Setelah menjalankan query, Anda dapat mencatatnya secara manual, tetapi APM akan mencatatnya secara otomatis jika diaktifkan: + +```php +Flight::db()->logQueries(); +``` + +Ini akan memicu event (`flight.db.queries`) dengan metrik koneksi dan query, yang dapat Anda dengarkan menggunakan sistem event Flight. + +### Contoh Lengkap + +```php +Flight::route('/users', function () { + // Dapatkan semua pengguna + $users = Flight::db()->fetchAll('SELECT * FROM users'); + + // Stream semua pengguna + $statement = Flight::db()->runQuery('SELECT * FROM users'); + while ($user = $statement->fetch()) { + echo $user['name']; + } + + // Dapatkan satu pengguna + $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); + + // Dapatkan satu nilai + $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); + + // Dapatkan satu kolom + $ids = Flight::db()->fetchColumn('SELECT id FROM users'); + + // Dapatkan pasangan kunci-nilai + $userNames = Flight::db()->fetchPairs('SELECT id, name FROM users'); + + // Sintaks IN() khusus + $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); + + // Sisipkan pengguna baru + $id = Flight::db()->insert('users', [ + 'name' => 'Bob', + 'email' => 'bob@example.com' + ]); + + // Sisipkan massal pengguna + Flight::db()->insert('users', [ + ['name' => 'Bob', 'email' => 'bob@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'] + ]); + + // Perbarui pengguna + $affected = Flight::db()->update('users', ['name' => 'Bob'], 'id = ?', [123]); + + // Hapus pengguna + $deleted = Flight::db()->delete('users', 'id = ?', [123]); + + // Gunakan transaksi + $result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John', 'email' => 'john@example.com']); + $db->insert('audit_log', ['action' => 'user_created']); + return $db->lastInsertId(); + }); +}); +``` + +## Migrasi dari PdoWrapper + +Jika Anda saat ini menggunakan `PdoWrapper`, migrasi ke `SimplePdo` adalah hal yang sederhana: + +1. **Perbarui pendaftaran Anda:** + ```php + // Lama + Flight::register('db', \flight\database\PdoWrapper::class, [ /* ... */ ]); + + // Baru + Flight::register('db', \flight\database\SimplePdo::class, [ /* ... */ ]); + ``` + +2. **Semua metode `PdoWrapper` yang ada bekerja di `SimplePdo`** - Tidak ada perubahan yang merusak. Kode Anda yang ada akan terus bekerja. + +3. **Secara opsional gunakan metode pembantu baru** - Mulai gunakan `insert()`, `update()`, `delete()`, dan `transaction()` untuk menyederhanakan kode Anda. + +## Lihat Juga + +- [Collections](/learn/collections) - Pelajari cara menggunakan kelas Collection untuk akses data yang mudah. +- [PdoWrapper](/learn/pdo-wrapper) - Kelas pembantu PDO lama (deprecated). + +## Pemecahan Masalah + +- Jika Anda mendapatkan kesalahan tentang koneksi database, periksa DSN, nama pengguna, kata sandi, dan opsi Anda. +- Semua baris dikembalikan sebagai Collections—jika Anda membutuhkan array biasa, gunakan `$collection->getData()`. +- Untuk query `IN (?)`, pastikan untuk meneruskan array. +- Jika Anda mengalami masalah memori dengan pencatatan query di proses yang berjalan lama, sesuaikan opsi `maxQueryMetrics`. + +## Changelog + +- v3.18.0 - Rilis awal SimplePdo dengan metode pembantu untuk insert, update, delete, dan transaksi. \ No newline at end of file diff --git a/content/v3/ja/awesome-plugins/awesome_plugins.md b/content/v3/ja/awesome-plugins/awesome_plugins.md index d96af062..236c402c 100644 --- a/content/v3/ja/awesome-plugins/awesome_plugins.md +++ b/content/v3/ja/awesome-plugins/awesome_plugins.md @@ -1,103 +1,104 @@ # 素晴らしいプラグイン -Flight は非常に拡張性が高いです。Flight アプリケーションに機能を追加するために使用できるプラグインがいくつかあります。一部は Flight Team によって公式にサポートされており、他のものは開始するためのマイクロ/ライトライブラリです。 +Flight は非常に拡張性が高いです。Flight アプリケーションに機能を追加するために使用できるプラグインがいくつかあります。一部は Flight チームによって公式にサポートされており、他のものは開始に役立つマイクロ/ライトライブラリです。 ## API ドキュメント -API ドキュメントは任意の API にとって重要です。開発者が API とどのようにやり取りするかを理解し、返されるものを期待するのに役立ちます。Flight プロジェクトの API ドキュメントを生成するのに役立つツールがいくつかあります。 +API ドキュメントはあらゆる API にとって重要です。開発者が API とどのようにやり取りするかを理解し、返されるものを期待するのに役立ちます。Flight プロジェクトの API ドキュメントを生成するのに役立つツールがいくつかあります。 - [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber によるブログ投稿で、OpenAPI Spec を FlightPHP と使用して API ファーストアプローチで API を構築する方法について説明しています。 -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI は、Flight プロジェクトの API ドキュメントを生成するのに役立つ優れたツールです。非常に使いやすく、ニーズに合わせてカスタマイズできます。これは Swagger ドキュメントを生成するための PHP ライブラリです。 +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI は、Flight プロジェクトの API ドキュメントを生成するのに役立つ素晴らしいツールです。非常に使いやすく、ニーズに合わせてカスタマイズできます。これは Swagger ドキュメントを生成するための PHP ライブラリです。 -## アプリケーション パフォーマンス監視 (APM) +## アプリケーション パフォーマンス モニタリング (APM) -アプリケーション パフォーマンス監視 (APM) は任意のアプリケーションにとって重要です。アプリケーションのパフォーマンスを理解し、ボトルネックがどこにあるかを特定するのに役立ちます。Flight で使用できる APM ツールがいくつかあります。 +アプリケーション パフォーマンス モニタリング (APM) はあらゆるアプリケーションにとって重要です。アプリケーションのパフォーマンスを理解し、ボトルネックがどこにあるかを特定するのに役立ちます。Flight で使用できる APM ツールがいくつかあります。 - official [flightphp/apm](/awesome-plugins/apm) - Flight APM は、Flight アプリケーションを監視するために使用できるシンプルな APM ライブラリです。アプリケーションのパフォーマンスを監視し、ボトルネックを特定するのに役立ちます。 ## Async Flight はすでに高速なフレームワークですが、ターボエンジンを追加するとすべてがより楽しく(そして挑戦的)になります! -- [flightphp/async](/awesome-plugins/async) - 公式の Flight Async ライブラリです。このライブラリは、アプリケーションに非同期処理を追加するシンプルな方法です。Swoole/Openswoole を内部で使用して、タスクを非同期で実行するシンプルで効果的な方法を提供します。 +- [flightphp/async](/awesome-plugins/async) - 公式の Flight Async ライブラリです。このライブラリは、アプリケーションに非同期処理を追加するシンプルな方法です。バックエンドで Swoole/Openswoole を使用して、タスクを非同期で実行するシンプルで効果的な方法を提供します。 -## 認可/権限 +## 承認/権限 -認可と権限は、誰が何にアクセスできるかを制御する必要がある任意のアプリケーションにとって重要です。 +承認と権限は、誰が何にアクセスできるかを制御する必要があるあらゆるアプリケーションにとって重要です。 - official [flightphp/permissions](/awesome-plugins/permissions) - 公式の Flight Permissions ライブラリです。このライブラリは、アプリケーションにユーザーおよびアプリケーション レベルの権限を追加するシンプルな方法です。 ## 認証 -認証は、ユーザー ID を検証し、API エンドポイントを保護する必要があるアプリケーションに不可欠です。 +認証は、ユーザー ID を検証し、API エンドポイントを保護する必要があるアプリケーションにとって不可欠です。 -- [firebase/php-jwt](/awesome-plugins/jwt) - PHP 用の JSON Web Token (JWT) ライブラリです。Flight アプリケーションでトークンベースの認証を実装するためのシンプルで安全な方法です。ステートレス API 認証、ミドルウェアによるルートの保護、OAuth スタイルの認可フローの実装に最適です。 +- [firebase/php-jwt](/awesome-plugins/jwt) - PHP 用の JSON Web Token (JWT) ライブラリです。Flight アプリケーションでトークンベースの認証を実装するシンプルで安全な方法です。ステートレス API 認証、ミドルウェアによるルートの保護、OAuth スタイルの承認フローの実装に最適です。 ## キャッシュ -キャッシュはアプリケーションを高速化する優れた方法です。Flight で使用できるキャッシュ ライブラリがいくつかあります。 +キャッシュはアプリケーションを高速化する素晴らしい方法です。Flight で使用できるキャッシュ ライブラリがいくつかあります。 -- official [flightphp/cache](/awesome-plugins/php-file-cache) - 軽量でシンプルなスタンドアロンの PHP イン-File キャッシュ クラス +- official [flightphp/cache](/awesome-plugins/php-file-cache) - 軽量でシンプルなスタンドアロンの PHP イン ファイル キャッシュ クラス ## CLI -CLI アプリケーションは、アプリケーションとやり取りする優れた方法です。コントローラーを生成したり、すべてのルートを表示したり、その他多くの機能に使用できます。 +CLI アプリケーションは、アプリケーションとやり取りする素晴らしい方法です。コントローラーを生成したり、すべてのルートを表示したり、その他多くの機能に使用できます。 - official [flightphp/runway](/awesome-plugins/runway) - Runway は、Flight アプリケーションを管理するのに役立つ CLI アプリケーションです。 ## Cookies -クッキーは、クライアント側に少量のデータを保存する優れた方法です。ユーザー設定、アプリケーション設定などを保存するために使用できます。 +クッキーはクライアント側に少量のデータを保存する素晴らしい方法です。ユーザー設定、アプリケーション設定などを保存するために使用できます。 -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie は、クッキーを管理するためのシンプルで効果的な PHP ライブラリです。 +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie は、クッキーを管理するシンプルで効果的な方法を提供する PHP ライブラリです。 ## デバッグ ローカル環境で開発する際のデバッグは重要です。デバッグ体験を向上させるプラグインがいくつかあります。 -- [tracy/tracy](/awesome-plugins/tracy) - Flight で使用できるフル機能のエラー ハンドラーです。アプリケーションをデバッグするのに役立つパネルがいくつかあります。また、拡張して独自のパネルを追加することも非常に簡単です。 -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) エラー ハンドラーと使用され、このプラグインは Flight プロジェクト特有のデバッグを支援するための追加パネルをいくつか追加します。 +- [tracy/tracy](/awesome-plugins/tracy) - Flight で使用できるフル機能のエラー ハンドラーです。アプリケーションのデバッグに役立つパネルがいくつかあります。また、拡張して独自のパネルを追加することも非常に簡単です。 +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) エラー ハンドラーと使用され、Flight プロジェクトのデバッグに特化した追加のパネルをいくつか追加します。 ## データベース -データベースはほとんどのアプリケーションのコアです。これによりデータを保存および取得します。一部のデータベース ライブラリはクエリを書くための単なるラッパーであり、他のものはフル機能の ORM です。 +データベースはほとんどのアプリケーションのコアです。これによりデータを保存および取得します。一部のデータベース ライブラリはクエリを書くための単なるラッパーで、一部はフル機能の ORM です。 -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - コアの一部である公式の Flight PDO Wrapper です。クエリを書くプロセスを簡素化するためのシンプルなラッパーです。ORM ではありません。 -- official [flightphp/active-record](/awesome-plugins/active-record) - 公式の Flight ActiveRecord ORM/Mapper です。データベースからデータを簡単に取得および保存するための優れたライブラリです。 +- official [flightphp/core SimplePdo](/learn/simple-pdo) - コアの一部である公式の Flight PDO ヘルパーです。これは、`insert()`、`update()`、`delete()`、`transaction()` などの便利なヘルパー メソッドを備えたモダンなラッパーで、データベース操作を簡素化します。すべての結果は柔軟な配列/オブジェクト アクセス用にコレクションとして返されます。ORM ではなく、PDO をより良く作業するための方法です。 +- deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) - コアの一部である公式の Flight PDO ラッパー(v3.18.0 以降非推奨)。SimplePdo を使用してください。 +- official [flightphp/active-record](/awesome-plugins/active-record) - 公式の Flight ActiveRecord ORM/マッパーです。データベースからデータを簡単に取得および保存するための優れた小さなライブラリです。 - [byjg/php-migration](/awesome-plugins/migrations) - プロジェクトのすべてのデータベース変更を追跡するためのプラグインです。 ## 暗号化 -暗号化は、機密データを保存する任意のアプリケーションにとって重要です。データを暗号化および復号化するのはそれほど難しくありませんが、暗号化キーを適切に保存することは [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [です](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [が](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)、難しい場合があります。最も重要なことは、暗号化キーを公開ディレクトリに保存したり、コード リポジトリにコミットしたりしないことです。 +暗号化は機密データを保存するあらゆるアプリケーションにとって重要です。データを暗号化および復号化するのはそれほど難しくありませんが、暗号化キーを適切に保存することは [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [です](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [が](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)、[困難](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key) です。最も重要なことは、暗号化キーを公開ディレクトリに保存したり、コード リポジトリにコミットしたりしないことです。 - [defuse/php-encryption](/awesome-plugins/php-encryption) - データを暗号化および復号化するために使用できるライブラリです。データを暗号化および復号化するのに開始するのはかなりシンプルです。 ## ジョブ キュー -ジョブ キューは、タスクを非同期で処理するのに非常に役立ちます。これはメールの送信、画像の処理、またはリアルタイムで実行する必要のない任意のものです。 +ジョブ キューは、タスクを非同期で処理するのに非常に役立ちます。これは、メールの送信、画像の処理、またはリアルタイムで実行する必要のないあらゆるものです。 - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue は、ジョブを非同期で処理するために使用できるライブラリです。beanstalkd、MySQL/MariaDB、SQLite、PostgreSQL と使用できます。 ## セッション -セッションは API にはあまり有用ではありませんが、Web アプリケーションを構築する際には、状態とログイン情報を維持するために重要です。 +セッションは API にはあまり役立ちませんが、Web アプリケーションを構築する際には、状態とログイン情報を維持するために重要です。 -- official [flightphp/session](/awesome-plugins/session) - 公式の Flight Session ライブラリです。セッションデータを保存および取得するために使用できるシンプルなセッション ライブラリです。PHP の組み込みセッション処理を使用します。 -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (非ブロッキング、フラッシュ、セグメント、セッション暗号化)。セッションデータのオプションの暗号化/復号化に PHP open_ssl を使用します。 +- official [flightphp/session](/awesome-plugins/session) - 公式の Flight Session ライブラリです。これは、セッションデータを保存および取得するために使用できるシンプルなセッション ライブラリです。PHP の組み込みセッション ハンドリングを使用します。 +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager(非ブロッキング、フラッシュ、セグメント、セッション暗号化)。セッションデータのオプションの暗号化/復号化に PHP open_ssl を使用します。 ## テンプレート -テンプレートは UI を備えた任意の Web アプリケーションのコアです。Flight で使用できるテンプレート エンジンがいくつかあります。 +テンプレートは UI を備えたあらゆる Web アプリケーションのコアです。Flight で使用できるテンプレート エンジンがいくつかあります。 - deprecated [flightphp/core View](/learn#views) - コアの一部である非常に基本的なテンプレート エンジンです。プロジェクトに数ページ以上ある場合は使用しないことを推奨します。 -- [latte/latte](/awesome-plugins/latte) - Latte は、Twig や Smarty よりも PHP 構文に近いフル機能のテンプレート エンジンで、非常に使いやすいです。また、拡張して独自のフィルターと関数を追加することも非常に簡単です。 +- [latte/latte](/awesome-plugins/latte) - Latte は、Twig や Smarty よりも PHP 構文に近いフル機能のテンプレート エンジンで、非常に使いやすいです。また、拡張して独自のフィルターや関数を追加することも非常に簡単です。 - [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate は、アセット コンパイル、テンプレート継承、変数処理を備えた強力な PHP テンプレート エンジンです。自動 CSS/JS 最小化、キャッシュ、Base64 エンコーディング、およびオプションの Flight PHP フレームワーク統合を備えています。 ## WordPress 統合 -WordPress プロジェクトで Flight を使用したいですか?そのための便利なプラグインがあります! +WordPress プロジェクトで Flight を使用したいですか? そのための便利なプラグインがあります! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - この WordPress プラグインにより、WordPress と並行して Flight を実行できます。カスタム API、マイクロサービス、または WordPress サイトに Flight フレームワークを使用してフルアプリを追加するのに最適です。両方の世界の最高のものを求める場合に非常に便利です! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - この WordPress プラグインにより、WordPress と並行して Flight を実行できます。カスタム API、マイクロサービス、または Flight フレームワークを使用して WordPress サイトにフル アプリを追加するのに最適です。両方の世界の最高のものを求める場合に超便利です! ## 貢献 -共有したいプラグインがありますか?リストに追加するためのプルリクエストを送信してください! \ No newline at end of file +共有したいプラグインがありますか? リストに追加するためのプル リクエストを送信してください! \ No newline at end of file diff --git a/content/v3/ja/awesome-plugins/jwt.md b/content/v3/ja/awesome-plugins/jwt.md index e25efcf0..20cd9e0e 100644 --- a/content/v3/ja/awesome-plugins/jwt.md +++ b/content/v3/ja/awesome-plugins/jwt.md @@ -1,22 +1,22 @@ -# Firebase JWT - Flight 用の JSON Web Token 認証 +# Firebase JWT - JSON Web Token 認証 -JWT (JSON Web Tokens) は、アプリケーションとクライアント間の主張を表すコンパクトで URL セーフな方法です。サーバー側のセッションストレージが不要なステートレス API 認証に最適です!このガイドでは、[Firebase JWT](https://github.com/firebase/php-jwt) を Flight と統合して、セキュアなトークンベースの認証を行う方法を示します。 +JWT (JSON Web Tokens) は、アプリケーションとクライアント間で請求を表すためのコンパクトで URL セーフな方法です。サーバー側のセッションストレージが不要なステートレス API 認証に最適です!このガイドでは、[Firebase JWT](https://github.com/firebase/php-jwt) を Flight と統合して、セキュアなトークンベースの認証を行う方法を示します。 完全なドキュメントと詳細については、[Github リポジトリ](https://github.com/firebase/php-jwt) をご覧ください。 ## JWT とは? JSON Web Token は、3つの部分を含む文字列です: -1. **ヘッダー**: トークンに関するメタデータ (アルゴリズム、タイプ) -2. **ペイロード**: あなたのデータ (ユーザー ID、ロール、期限切れなど) -3. **シグネチャー**: 真正性を検証するための暗号署名 +1. **ヘッダー**: トークンに関するメタデータ(アルゴリズム、タイプ) +2. **ペイロード**: あなたのデータ(ユーザー ID、ロール、期限切れなど) +3. **署名**: 真正性を検証するための暗号署名 -例の JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (意味不明に見えますが、構造化されたデータです!) +例の JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...`(意味不明に見えますが、構造化されたデータです!) ### JWT を使用する理由は? - **ステートレス**: サーバー側のセッションストレージが不要 — マイクロサービスや API に最適 -- **スケーラブル**: セッションアフィニティの要件がないため、ロードバランサーとよく動作 +- **スケーラブル**: セッション親和性要件がないため、ロードバランサーでうまく動作 - **クロスドメイン**: 異なるドメインやサービス間で使用可能 - **モバイルフレンドリー**: クッキーがうまく動作しないモバイルアプリに最適 - **標準化**: 業界標準のアプローチ (RFC 7519) @@ -37,7 +37,7 @@ JWT を作成して検証する簡単な例: use Firebase\JWT\JWT; use Firebase\JWT\Key; -// あなたの秘密鍵 (これをセキュアに保ってください!) +// あなたのシークレットキー(これを安全に保ってください!) $secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; // トークンを作成 @@ -61,9 +61,9 @@ try { } ``` -## Flight 用の JWT ミドルウェア (推奨アプローチ) +## Flight 用の JWT ミドルウェア(推奨アプローチ) -Flight で JWT を使用する最も一般的で有用な方法は、**ミドルウェア**として API ルートを保護することです。以下は、完全で本番環境対応の例です: +Flight で JWT を使用する最も一般的で有用な方法は、API ルートを保護するための **ミドルウェア** としてです。以下は、完全で本番環境対応の例です: ### ステップ 1: JWT ミドルウェアクラスを作成 @@ -82,21 +82,21 @@ class JwtMiddleware { public function __construct(Engine $app) { $this->app = $app; - // 秘密鍵を app/config/config.php に保存し、ハードコードしないでください! + // シークレットキーを app/config/config.php に保存し、ハードコードしないでください! $this->secretKey = $app->get('config')['jwt_secret']; } public function before(array $params) { $authHeader = $this->app->request()->getHeader('Authorization'); - // Authorization ヘッダーが存在するかチェック + // Authorization ヘッダーの存在を確認 if (empty($authHeader)) { - $this->app->jsonHalt(['error' => 'No authorization token provided'], 401); + $this->app->jsonHalt(['error' => '認証トークンが提供されていません'], 401); } // "Bearer " 形式からトークンを抽出 if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { - $this->app->jsonHalt(['error' => 'Invalid authorization format. Use: Bearer '], 401); + $this->app->jsonHalt(['error' => '無効な認証形式です。Bearer を使用してください'], 401); } $jwt = $matches[1]; @@ -109,17 +109,17 @@ class JwtMiddleware { $this->app->request()->data->user = $decoded; } catch (ExpiredException $e) { - $this->app->jsonHalt(['error' => 'Token has expired'], 401); + $this->app->jsonHalt(['error' => 'トークンの有効期限が切れています'], 401); } catch (SignatureInvalidException $e) { - $this->app->jsonHalt(['error' => 'Invalid token signature'], 401); + $this->app->jsonHalt(['error' => '無効なトークン署名'], 401); } catch (Exception $e) { - $this->app->jsonHalt(['error' => 'Invalid token: ' . $e->getMessage()], 401); + $this->app->jsonHalt(['error' => '無効なトークン: ' . $e->getMessage()], 401); } } } ``` -### ステップ 2: 設定に JWT 秘密鍵を登録 +### ステップ 2: 設定に JWT シークレットを登録 ```php // app/config/config.php @@ -128,26 +128,26 @@ return [ ]; // app/config/bootstrap.php または index.php -// 設定をアプリに公開したい場合、この行を追加してください +// 設定をアプリに公開したい場合は、この行を追加してください $app->set('config', $config); ``` -> **セキュリティノート**: 秘密鍵をハードコードしないでください!本番環境では環境変数を使用してください。 +> **セキュリティノート**: シークレットキーをハードコードしないでください!本番環境では環境変数を使用してください。 ### ステップ 3: ミドルウェアでルートを保護 ```php // 単一のルートを保護 Flight::route('GET /api/user/profile', function() { - $user = Flight::request()->data->user; // ミドルウェアによって設定 + $user = Flight::request()->data->user; // ミドルウェアで設定 Flight::json([ 'user_id' => $user->user_id, 'username' => $user->username, 'role' => $user->role ]); -})->addMiddleware( JwtMiddleware::class); +})->addMiddleware(JwtMiddleware::class); -// ルートのグループ全体を保護 (より一般的!) +// ルートのグループ全体を保護(より一般的!) Flight::group('/api', function() { Flight::route('GET /users', function() { /* ... */ }); Flight::route('GET /posts', function() { /* ... */ }); @@ -158,9 +158,9 @@ Flight::group('/api', function() { ミドルウェアの詳細については、[ミドルウェアドキュメント](/learn/middleware) を参照してください。 -## 一般的なユースケース +## 一般的な使用事例 -### 1. ログインエンドポイント (トークン生成) +### 1. ログインエンドポイント(トークン生成) 認証成功後に JWT を生成するルートを作成: @@ -170,11 +170,11 @@ Flight::route('POST /api/login', function() { $username = $data->username ?? ''; $password = $data->password ?? ''; - // 認証情報を検証 (例 — 独自のロジックを使用!) + // 認証情報を検証(例 — 独自のロジックを使用!) $user = validateUserCredentials($username, $password); if (!$user) { - Flight::jsonHalt(['error' => 'Invalid credentials'], 401); + Flight::jsonHalt(['error' => '無効な認証情報'], 401); } // JWT を生成 @@ -184,7 +184,7 @@ Flight::route('POST /api/login', function() { 'username' => $user->username, 'role' => $user->role, 'iat' => time(), - 'exp' => time() + (60 * 60) // 1時間後の期限切れ + 'exp' => time() + (60 * 60) // 1時間の有効期限 ]; $jwt = JWT::encode($payload, $secretKey, 'HS256'); @@ -197,7 +197,7 @@ Flight::route('POST /api/login', function() { }); function validateUserCredentials($username, $password) { - // ここにデータベース検索とパスワード検証を実装 + // ここにデータベース検索とパスワード検証 // 例: $db = Flight::db(); $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); @@ -213,7 +213,7 @@ function validateUserCredentials($username, $password) { } ``` -### 2. トークンリフレッシュフロー +### 2. トークン更新フロー 長期間のセッションのためのリフレッシュトークンシステムを実装: @@ -224,7 +224,7 @@ Flight::route('POST /api/login', function() { $secretKey = Flight::get('config')['jwt_secret']; $refreshSecret = Flight::get('config')['jwt_refresh_secret']; - // 短期間のアクセス トークン (15 分) + // 短期間のアクセストークン (15 分) $accessToken = JWT::encode([ 'user_id' => $user->id, 'type' => 'access', @@ -232,7 +232,7 @@ Flight::route('POST /api/login', function() { 'exp' => time() + (15 * 60) ], $secretKey, 'HS256'); - // 長期間のリフレッシュ トークン (7 日) + // 長期間のリフレッシュトークン (7 日) $refreshToken = JWT::encode([ 'user_id' => $user->id, 'type' => 'refresh', @@ -254,12 +254,12 @@ Flight::route('POST /api/refresh', function() { try { $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); - // これがリフレッシュ トークンであることを検証 + // これがリフレッシュトークンであることを検証 if ($decoded->type !== 'refresh') { - Flight::jsonHalt(['error' => 'Invalid token type'], 401); + Flight::jsonHalt(['error' => '無効なトークンタイプ'], 401); } - // 新しいアクセス トークンを生成 + // 新しいアクセストークンを生成 $secretKey = Flight::get('config')['jwt_secret']; $accessToken = JWT::encode([ 'user_id' => $decoded->user_id, @@ -274,7 +274,7 @@ Flight::route('POST /api/refresh', function() { ]); } catch (Exception $e) { - Flight::jsonHalt(['error' => 'Invalid refresh token'], 401); + Flight::jsonHalt(['error' => '無効なリフレッシュトークン'], 401); } }); ``` @@ -295,21 +295,21 @@ class JwtRoleMiddleware { } public function before(array $params) { - // JwtMiddleware が既に実行され、ユーザー データが設定されていると仮定 + // JwtMiddleware がすでに実行され、ユーザー データが設定されていると仮定 $user = $this->app->request()->data->user ?? null; if (!$user) { - $this->app->jsonHalt(['error' => 'Authentication required'], 401); + $this->app->jsonHalt(['error' => '認証が必要です'], 401); } - // ユーザーが必要なロールを持っているかチェック + // ユーザーが必要なロールを持っているかをチェック if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { - $this->app->jsonHalt(['error' => 'Insufficient permissions'], 403); + $this->app->jsonHalt(['error' => '権限が不足しています'], 403); } } } -// 使用例: 管理者限定ルート +// 使用例: 管理者専用ルート Flight::route('DELETE /api/users/@id', function($id) { // ユーザー削除ロジック })->addMiddleware([ @@ -320,7 +320,7 @@ Flight::route('DELETE /api/users/@id', function($id) { ### 4. ユーザーごとのレート制限付きパブリック API -セッションなしでユーザーを追跡してレート制限: +セッションなしで JWT を使用してユーザー を追跡し、レート制限: ```php class RateLimitMiddleware { @@ -330,11 +330,11 @@ class RateLimitMiddleware { $userId = $user ? $user->user_id : Flight::request()->ip; $cacheKey = "rate_limit:$userId"; - // app/config/services.php でキャッシュ サービスを設定してください + // app/config/services.php でキャッシュサービスを設定してください $requests = Flight::cache()->get($cacheKey, 0); if ($requests >= 100) { // 1時間あたり 100 リクエスト - Flight::jsonHalt(['error' => 'Rate limit exceeded'], 429); + Flight::jsonHalt(['error' => 'レート制限を超えました'], 429); } Flight::cache()->set($cacheKey, $requests + 1, 3600); @@ -344,26 +344,26 @@ class RateLimitMiddleware { ## セキュリティのベストプラクティス -### 1. 強力な秘密鍵を使用 +### 1. 強力なシークレットキー を使用 ```php -// セキュアな秘密鍵を生成 (一度実行し、.env ファイルに保存) +// セキュアなシークレットキーを生成(一度実行し、.env ファイルに保存) $secretKey = base64_encode(random_bytes(32)); echo $secretKey; // これを .env ファイルに保存! ``` -### 2. 秘密鍵を環境変数に保存 +### 2. シークレットを環境変数に保存 ```php -// 秘密鍵をバージョン管理にコミットしないでください! +// シークレットをバージョン管理にコミットしないでください! // .env ファイルと vlucas/phpdotenv などのライブラリを使用 // .env ファイル: // JWT_SECRET=your-base64-encoded-secret-here // JWT_REFRESH_SECRET=another-base64-encoded-secret-here -// アプリの設定ファイル app/config/config.php にも秘密鍵を保存可能 -// ただし、設定ファイルはバージョン管理にコミットしないでください +// app/config/config.php ファイルを使用してシークレットを保存することも可能 +// 設定ファイルがバージョン管理にコミットされないことを確認 // return [ // 'jwt_secret' => 'your-base64-encoded-secret-here', // 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', @@ -376,38 +376,38 @@ echo $secretKey; // これを .env ファイルに保存! ### 3. 適切な有効期限を設定 ```php -// 良い習慣: 短期間のアクセス トークン +// 良い習慣: 短期間のアクセストークン 'exp' => time() + (15 * 60) // 15 分 -// リフレッシュ トークンの場合: 長い有効期限 +// リフレッシュトークンの場合: 長い有効期限 'exp' => time() + (7 * 24 * 60 * 60) // 7 日 ``` ### 4. 本番環境で HTTPS を使用 -JWT は **常に** HTTPS を介して送信してください。本番環境でプレーン HTTP を使用しないでください! +JWT は **常に** HTTPS で送信されるべきです。本番環境ではプレーン HTTP でトークンを送信しないでください! -### 5. トークン主張を検証 +### 5. トークンクレームを検証 -重要な主張を常に検証: +重要なクレームを常に検証: ```php $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); -// 期限切れのチェックはライブラリによって自動的に処理されます +// 期限切れのチェックはライブラリで自動的に処理されます // ただし、カスタム検証を追加可能: if ($decoded->iat > time()) { - throw new Exception('Token used before it was issued'); + throw new Exception('トークンが発行される前に使用されました'); } if (isset($decoded->nbf) && $decoded->nbf > time()) { - throw new Exception('Token not yet valid'); + throw new Exception('トークンがまだ有効ではありません'); } ``` ### 6. ログアウトのためのトークンブラックリストを検討 -追加のセキュリティのために、無効化されたトークンのブラックリストを維持: +追加のセキュリティのため、無効化されたトークンのブラックリストを維持: ```php Flight::route('POST /api/logout', function() { @@ -422,7 +422,7 @@ Flight::route('POST /api/logout', function() { // 有効期限までキャッシュ/Redis に保存 Flight::cache()->set("blacklist:$jwt", true, $ttl); - Flight::json(['message' => 'Successfully logged out']); + Flight::json(['message' => '正常にログアウトしました']); }); // JwtMiddleware に追加: @@ -431,19 +431,19 @@ public function before(array $params) { // ブラックリストをチェック if (Flight::cache()->get("blacklist:$jwt")) { - $this->app->jsonHalt(['error' => 'Token has been revoked'], 401); + $this->app->jsonHalt(['error' => 'トークンが取り消されました'], 401); } // ... トークンを検証 ... } ``` -## アルゴリズムと鍵の種類 +## アルゴリズムとキー タイプ Firebase JWT は複数のアルゴリズムをサポート: ### 対称アルゴリズム (HMAC) -- **HS256** (ほとんどのアプリで推奨): 単一の秘密鍵を使用 +- **HS256** (ほとんどのアプリに推奨): 単一のシークレットキー を使用 - **HS384**, **HS512**: より強力なバリエーション ```php @@ -469,17 +469,17 @@ $jwt = JWT::encode($payload, $privateKey, 'RS256'); $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); ``` -> **RSA を使用するタイミング**: 公開鍵を検証のために配布する必要がある場合 (例: マイクロサービス、サードパーティ統合) に RSA を使用。単一のアプリケーションの場合、HS256 がよりシンプルで十分です。 +> **RSA を使用するタイミング**: 検証のための公開鍵を配布する必要がある場合に RSA を使用(例: マイクロサービス、サードパーティ統合)。単一のアプリケーションの場合、HS256 がよりシンプルで十分です。 ## トラブルシューティング ### "Expired token" エラー -トークンの `exp` 主張が過去です。新しいトークンを発行するか、トークンリフレッシュを実装してください。 +トークンの `exp` クレームが過去です。新しいトークンを発行するか、トークン更新を実装してください。 ### "Signature verification failed" -- エンコードに使用したものと異なる秘密鍵でデコードしている -- トークンが改ざんされている -- サーバー間のクロックスキュー (レウェイバッファを追加) +- エンコードに使用したものと異なるシークレットキー でデコードしています +- トークンが改ざんされています +- サーバー間のクロックスキュー(leeway バッファを追加) ```php use Firebase\JWT\JWT; @@ -506,23 +506,23 @@ Firebase JWT ライブラリはこれらのコアメソッドを提供: - `JWT::encode(array $payload, string $key, string $alg)`: ペイロードから JWT を作成 - `JWT::decode(string $jwt, Key $key)`: JWT をデコードして検証 -- `JWT::urlsafeB64Encode(string $input)`: Base64 URL セーフエンコード -- `JWT::urlsafeB64Decode(string $input)`: Base64 URL セーフデコード -- `JWT::$leeway`: 検証のための時間レウェイを設定する静的プロパティ (秒単位) +- `JWT::urlsafeB64Encode(string $input)`: Base64 URL セーフエンコーディング +- `JWT::urlsafeB64Decode(string $input)`: Base64 URL セーフデコーディング +- `JWT::$leeway`: 検証のための時間 leeway を設定する静的プロパティ(秒単位) ## このライブラリを使用する理由は? -- **業界標準**: Firebase JWT は PHP で最も人気があり、広く信頼されている JWT ライブラリ +- **業界標準**: Firebase JWT は PHP 用の最も人気があり信頼されている JWT ライブラリ - **積極的なメンテナンス**: Google/Firebase チームによるメンテナンス - **セキュリティ重視**: 定期的な更新とセキュリティパッチ - **シンプルな API**: 理解しやすく実装しやすい -- **よくドキュメント化**: 広範なドキュメントとコミュニティサポート -- **柔軟**: 複数のアルゴリズムと設定可能なオプションをサポート +- **よくドキュメント化**: 豊富なドキュメントとコミュニティサポート +- **柔軟**: 複数のアルゴリズムと構成可能なオプションをサポート -## 関連項目 +## 関連資料 - [Firebase JWT Github リポジトリ](https://github.com/firebase/php-jwt) -- [JWT.io](https://jwt.io/) - JWT をデバッグおよびデコード +- [JWT.io](https://jwt.io/) - JWT をデバッグしてデコード - [RFC 7519](https://tools.ietf.org/html/rfc7519) - 公式 JWT 仕様 - [Flight ミドルウェアドキュメント](/learn/middleware) - [Flight セッションプラグイン](/awesome-plugins/session) - 従来のセッションベース認証用 diff --git a/content/v3/ja/awesome-plugins/runway.md b/content/v3/ja/awesome-plugins/runway.md index 2862ad72..2c233ac4 100644 --- a/content/v3/ja/awesome-plugins/runway.md +++ b/content/v3/ja/awesome-plugins/runway.md @@ -1,12 +1,12 @@ # Runway -Runway は、Flight アプリケーションを管理するのに役立つ CLI アプリケーションです。コントローラーを生成したり、全ルートを表示したり、その他さまざまな機能を提供します。これは優れた [adhocore/php-cli](https://github.com/adhocore/php-cli) ライブラリに基づいています。 +Runway は、Flight アプリケーションを管理するのに役立つ CLI アプリケーションです。コントローラーを生成したり、全ルートを表示したり、その他多くの機能を提供します。これは優れた [adhocore/php-cli](https://github.com/adhocore/php-cli) ライブラリを基にしています。 -コードを表示するには、[ここ](https://github.com/flightphp/runway)をクリックしてください。 +コードを見るには [こちら](https://github.com/flightphp/runway) をクリックしてください。 ## インストール -Composer でインストールします。 +Composer を使用してインストールします。 ```bash composer require flightphp/runway @@ -14,7 +14,7 @@ composer require flightphp/runway ## 基本設定 -Runway を初めて実行すると、`app/config/config.php` 内の `'runway'` キーから `runway` 設定を探します。 +Runway を初めて実行すると、`app/config/config.php` 内の `'runway'` キーから `runway` 設定を探そうとします。 ```php **注意** - **v1.2.0** 以降、`.runway-config.json` は非推奨です。設定を `app/config/config.php` に移行してください。`php runway config:migrate` コマンドで簡単に移行できます。 +> **注意** - **v1.2.0** 以降、`.runway-config.json` は非推奨です。設定を `app/config/config.php` に移行してください。これを簡単に実行するには、`php runway config:migrate` コマンドを使用できます。 ### プロジェクトルートの検出 @@ -38,11 +38,11 @@ Runway は、プロジェクトのルートを検出するのに十分賢いで Runway には、Flight アプリケーションを管理するためのいくつかのコマンドがあります。Runway を使用する簡単な方法は 2 つあります。 1. スケルトンプロジェクトを使用している場合、プロジェクトのルートから `php runway [command]` を実行できます。 -1. Composer を通じてインストールしたパッケージとして Runway を使用している場合、プロジェクトのルートから `vendor/bin/runway [command]` を実行できます。 +1. Composer を介してインストールしたパッケージとして Runway を使用している場合、プロジェクトのルートから `vendor/bin/runway [command]` を実行できます。 ### コマンドリスト -`php runway` コマンドを実行すると、すべての利用可能なコマンドのリストを表示できます。 +`php runway` コマンドを実行することで、利用可能なすべてのコマンドのリストを表示できます。 ```bash php runway @@ -50,7 +50,7 @@ php runway ### コマンドヘルプ -任意のコマンドに対して、`--help` フラグを渡すと、そのコマンドの使用方法についての詳細情報を取得できます。 +任意のコマンドに対して、`--help` フラグを渡すことでコマンドの使用方法に関する詳細情報を取得できます。 ```bash php runway routes --help @@ -60,7 +60,7 @@ php runway routes --help ### コントローラーの生成 -`runway.app_root` の設定に基づいて、指定された場所に `app/controllers/` ディレクトリ内のコントローラーを生成します。 +`runway.app_root` の設定に基づいて、場所が `app/controllers/` ディレクトリにコントローラーを生成します。 ```bash php runway make:controller MyController @@ -68,13 +68,13 @@ php runway make:controller MyController ### Active Record モデルの生成 -まず、[Active Record](/awesome-plugins/active-record) プラグインをインストールしていることを確認してください。`runway.app_root` の設定に基づいて、`app/records/` ディレクトリにレコードを生成します。 +まず、[Active Record](/awesome-plugins/active-record) プラグインをインストールしたことを確認してください。`runway.app_root` の設定に基づいて、場所が `app/records/` ディレクトリにレコードを生成します。 ```bash php runway make:record users ``` -たとえば、`users` テーブルに `id`、`name`、`email`、`created_at`、`updated_at` のスキーマがある場合、`app/records/UserRecord.php` ファイルに以下のようないファイルが作成されます: +たとえば、`users` テーブルに以下のスキーマがある場合:`id`、`name`、`email`、`created_at`、`updated_at`、`app/records/UserRecord.php` ファイルに以下の類似したファイルが作成されます: ```php [ - // アプリケーション ディレクトリの場所 + // アプリケーション ディレクトリが配置されている場所 'app_root' => 'app/', - // ルートインデックスファイルの場所のディレクトリ + // ルートインデックスファイルが配置されているディレクトリ 'index_root' => 'public/', - // 他のプロジェクトのルートの経路 + // 他のプロジェクトのルートへのパス 'root_paths' => [ '/home/user/different-project', '/var/www/another-project' ], - // ベースパスは通常設定する必要はありませんが、必要に応じて使用できます + // ベースパスは通常設定する必要はありませんが、必要に応じてここにあります 'base_paths' => [ - '/includes/libs/vendor', // vendor ディレクトリに独自の経路がある場合など + '/includes/libs/vendor', // vendor ディレクトリに非常に独自のパスがある場合など ], - // 最終パスは、プロジェクト内のコマンドファイルの検索場所 + // 最終パスは、プロジェクト内のコマンドファイルを検索する場所です 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // 完全なパスを追加したい場合(プロジェクトルートからの絶対または相対パス) + // フルパスを追加したい場合、問題ありません(プロジェクトルートからの絶対または相対パス) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -254,7 +254,7 @@ return [ ### 設定へのアクセス -設定値を効果的にアクセスする必要がある場合、`__construct` メソッドまたは `app()` メソッド経由でアクセスできます。また、`app/config/services.php` ファイルがある場合、そのサービスもコマンドで利用可能です。 +設定値に効果的にアクセスする必要がある場合、`__construct` メソッドまたは `app()` メソッド経由でアクセスできます。また、`app/config/services.php` ファイルがある場合、そのサービスもコマンドで利用可能であることに注意してください。 ```php public function execute() @@ -273,14 +273,14 @@ public function execute() ## AI ヘルパー ラッパー -Runway には、AI がコマンドを生成しやすくするためのヘルパー ラッパーがいくつかあります。Symfony Console に似た方法で `addOption` と `addArgument` を使用できます。AI ツールを使用してコマンドを生成する場合に役立ちます。 +Runway には、AI がコマンドを生成しやすくするためのヘルパー ラッパーがいくつかあります。Symfony Console に似た方法で `addOption` および `addArgument` を使用できます。AI ツールを使用してコマンドを生成する場合に役立ちます。 ```php public function __construct(array $config) { parent::__construct('make:example', 'ドキュメント用の例を作成', $config); - // name オプションは null 可能で、完全にオプションです + // name オプションは null 可能で、完全にオプションのデフォルトです $this->addOption('name', '例の名前', null); } ``` \ No newline at end of file diff --git a/content/v3/ja/learn/autoloading.md b/content/v3/ja/learn/autoloading.md index 8bc273b7..e749cd88 100644 --- a/content/v3/ja/learn/autoloading.md +++ b/content/v3/ja/learn/autoloading.md @@ -2,17 +2,17 @@ ## 概要 -オートローディングは、PHPの概念で、クラスをロードするためのディレクトリまたはディレクトリを指定します。これは、`require` や `include` を使用してクラスをロードするよりもはるかに有益です。また、Composerパッケージを使用するための要件でもあります。 +オートローディングは、PHPの概念で、クラスをロードするためのディレクトリまたはディレクトリを指定します。これにより、`require` や `include` を使用してクラスをロードするよりもはるかに利点があります。また、Composerパッケージを使用するための要件でもあります。 ## 理解 -デフォルトでは、`Flight` のクラスは Composer のおかげで自動的にオートロードされます。ただし、自分のクラスをオートロードしたい場合は、`Flight::path()` メソッドを使用してクラスをロードするためのディレクトリを指定できます。 +デフォルトでは、`Flight` クラスはComposerのおかげで自動的にオートロードされます。ただし、自分のクラスをオートロードしたい場合は、`Flight::path()` メソッドを使用してクラスをロードするディレクトリを指定できます。 -オートローダーを使用することで、コードを大幅に簡素化できます。ファイルの先頭に多数の `include` や `require` 文を記述して、そのファイルで使用されるすべてのクラスをキャプチャする代わりに、クラスを動的に呼び出すだけで自動的にインクルードされます。 +オートローダーを使用すると、コードを大幅に簡素化できます。ファイルの先頭に多数の `include` や `require` 文を記述して、そのファイルで使用されるすべてのクラスをキャプチャする代わりに、クラスを動的に呼び出すだけで自動的にインクルードされます。 ## 基本的な使用方法 -以下のディレクトリツリーがあると仮定しましょう: +以下のディレクトリツリーがあると仮定します: ```text # 例のパス @@ -22,7 +22,7 @@ │ ├── config │ ├── controllers - このプロジェクトのコントローラーを含む │ ├── translations -│ ├── UTILS - このアプリケーション専用のクラスを含む(後で例を示すために意図的に大文字) +│ ├── UTILS - このアプリケーション専用のクラスを含む(後述の例のために意図的にすべて大文字) │ └── views └── public └── css @@ -32,7 +32,7 @@ このドキュメントサイトと同じファイル構造であることに気づいたかもしれません。 -各ディレクトリをロードするための指定は以下のようになります: +各ディレクトリをこのように指定できます: ```php @@ -49,20 +49,20 @@ Flight::path(__DIR__.'/../app/utils/'); * app/controllers/MyController.php */ -// 名前空間は不要 +// 名前空間は必要ありません -// オートロードされるすべてのクラスは Pascal Case を推奨(各単語の先頭を大文字、スペースなし) +// オートロードされるクラスは、Pascal Case(各単語の先頭を大文字にし、スペースなし)で記述することを推奨します class MyController { public function index() { - // 何かを行う + // 何かを実行 } } ``` ## 名前空間 -名前空間を使用する場合、これは非常に簡単に実装できます。アプリケーションのルートディレクトリ(ドキュメントルートや `public/` フォルダではない)を指定するために `Flight::path()` メソッドを使用するべきです。 +名前空間を使用する場合、これは非常に簡単に実装できます。アプリケーションのルートディレクトリ(ドキュメントルートや `public/` フォルダではなく)を指定するために、`Flight::path()` メソッドを使用するべきです。 ```php @@ -74,25 +74,26 @@ class MyController { Flight::path(__DIR__.'/../'); ``` -これがコントローラーの例です。以下の例を見て、重要な情報のためにコメントに注意してください。 +これがコントローラーの例です。以下の例を見てください。ただし、重要な情報のためにコメントに注目してください。 ```php /** * app/controllers/MyController.php */ -// 名前空間は必須 -// 名前空間はディレクトリ構造と同じ -// 名前空間はディレクトリ構造と同じケースに従う -// 名前空間とディレクトリにはアンダースコアを含められない(Loader::setV2ClassLoading(false) を設定しない限り) +// 名前空間は必須です +// 名前空間はディレクトリ構造と同じです +// 名前空間はディレクトリ構造と同じケースに従う必要があります +// 名前空間とディレクトリにはアンダースコアを含めないでください(Loader::setV2ClassLoading(false) を設定しない限り) +// 名前空間はディレクトリ構造とケースに一致する必要があります namespace app\controllers; -// オートロードされるすべてのクラスは Pascal Case を推奨(各単語の先頭を大文字、スペースなし) -// 3.7.2 以降、Loader::setV2ClassLoading(false); を実行することでクラス名に Pascal_Snake_Case を使用可能 +// オートロードされるクラスは、Pascal Case(各単語の先頭を大文字にし、スペースなし)で記述することを推奨します +// 3.7.2以降、Loader::setV2ClassLoading(false); を実行することで、クラス名に Pascal_Snake_Case を使用できます class MyController { public function index() { - // 何かを行う + // 何かを実行 } } ``` @@ -105,21 +106,21 @@ utils ディレクトリのクラスをオートロードしたい場合、基 * app/UTILS/ArrayHelperUtil.php */ -// 名前空間はディレクトリ構造とケースに一致する必要がある(上記のファイルツリーのように UTILS ディレクトリはすべて大文字) +// 名前空間はディレクトリ構造とケースに一致する必要があります(上記のファイルツリーのように UTILS ディレクトリはすべて大文字です) namespace app\UTILS; class ArrayHelperUtil { public function changeArrayCase(array $array) { - // 何かを行う + // 何かを実行 } } ``` ## クラス名のアンダースコア -3.7.2 以降、`Loader::setV2ClassLoading(false);` を実行することで、クラス名に Pascal_Snake_Case を使用できます。 -これにより、クラス名にアンダースコアを使用できます。 +3.7.2以降、`Loader::setV2ClassLoading(false);` を実行することで、クラス名に Pascal_Snake_Case を使用できます。 +これにより、クラス名にアンダースコアを使用できます。 これは推奨されませんが、必要とする人向けに利用可能です。 ```php @@ -138,50 +139,50 @@ Loader::setV2ClassLoading(false); * app/controllers/My_Controller.php */ -// 名前空間は不要 +// 名前空間は必要ありません class My_Controller { public function index() { - // 何かを行う + // 何かを実行 } } ``` ## 関連項目 -- [ルーティング](/learn/routing) - ルートをコントローラーにマッピングし、ビューをレンダリングする方法。 -- [なぜフレームワークか?](/learn/why-frameworks) - Flight のようなフレームワークを使用する利点の理解。 +- [Routing](/learn/routing) - ルートをコントローラーにマッピングし、ビューをレンダリングする方法。 +- [Why a Framework?](/learn/why-frameworks) - Flight のようなフレームワークを使用する利点の理解。 ## トラブルシューティング -- 名前空間付きのクラスが見つからない理由がわからない場合、プロジェクトのルートディレクトリに `Flight::path()` を使用することを忘れずに。`app/` や `src/` ディレクトリや同等ではありません。 +- 名前空間付きのクラスが見つからない理由がわからない場合、プロジェクトのルートディレクトリに対して `Flight::path()` を使用することを忘れないでください。`app/` や `src/` ディレクトリや同等ではありません。 -### クラスが見つからない(オートローディングが動作しない) +### クラスが見つからない(オートローディングが機能しない) -これが発生しない理由はいくつか考えられます。以下に例を示しますが、[オートローディング](/learn/autoloading) セクションも確認してください。 +これが発生しない理由はいくつか考えられます。以下にいくつかの例を示しますが、[autoloading](/learn/autoloading) セクションも確認してください。 -#### ファイル名が不正 +#### ファイル名の誤り 最も一般的なのは、クラス名がファイル名と一致しないことです。 -`MyClass` という名前のクラスがある場合、ファイルは `MyClass.php` と名付けるべきです。`MyClass` というクラスがあり、ファイルが `myclass.php` の場合、オートローダーはそれを見つけられません。 +クラス名が `MyClass` の場合、ファイル名は `MyClass.php` であるべきです。クラス名が `MyClass` でファイル名が `myclass.php` の場合、オートローダーはそれを見つけられません。 -#### 名前空間が不正 -名前空間を使用している場合、名前空間はディレクトリ構造に一致するべきです。 +#### 名前空間の誤り +名前空間を使用している場合、名前空間はディレクトリ構造に一致する必要があります。 ```php // ...code... -// MyController が app/controllers ディレクトリにあり、名前空間付きの場合 -// これは動作しません。 +// MyController が app/controllers ディレクトリにあり、名前空間が付けられている場合 +// これは機能しません。 Flight::route('/hello', 'MyController->hello'); // これらのオプションのいずれかを選択する必要があります Flight::route('/hello', 'app\controllers\MyController->hello'); -// または上部に use 文がある場合 +// または、上部に use 文がある場合 use app\controllers\MyController; Flight::route('/hello', [ MyController::class, 'hello' ]); -// また、次のように書けます +// また、次のように記述できます Flight::route('/hello', MyController::class.'->hello'); // また... Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); @@ -189,8 +190,7 @@ Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); #### `path()` が定義されていない -スケルトンアプリでは、これは `config.php` ファイル内で定義されていますが、クラスが見つかるためには、`path()` -メソッドが定義されていることを確認する必要があります(おそらくディレクトリのルートに)。使用しようとする前に。 +スケルトンアプリでは、これは `config.php` ファイル内に定義されていますが、クラスが見つかるように、`path()` メソッドが定義されている(おそらくディレクトリのルートに対して)ことを確認する必要があります。それを使用する前に。 ```php // オートローダーにパスを追加 @@ -198,5 +198,5 @@ Flight::path(__DIR__.'/../'); ``` ## 変更履歴 -- v3.7.2 - `Loader::setV2ClassLoading(false);` を実行することでクラス名に Pascal_Snake_Case を使用可能 -- v2.0 - オートロード機能が追加 \ No newline at end of file +- v3.7.2 - `Loader::setV2ClassLoading(false);` を実行することで、クラス名に Pascal_Snake_Case を使用できます +- v2.0 - オートロード機能が追加されました。 \ No newline at end of file diff --git a/content/v3/ja/learn/learn.md b/content/v3/ja/learn/learn.md index c51e926b..30424284 100644 --- a/content/v3/ja/learn/learn.md +++ b/content/v3/ja/learn/learn.md @@ -1,91 +1,95 @@ # Flight について学ぶ -Flight は、PHP 向けの高速でシンプルで拡張可能なフレームワークです。非常に汎用性が高く、あらゆる種類のウェブアプリケーションを構築するために使用できます。 -シンプルさを念頭に置いて構築されており、理解しやすく使用しやすい方法で記述されています。 +Flight は、PHP 用の高速でシンプルで拡張可能なフレームワークです。非常に汎用性が高く、あらゆる種類のウェブアプリケーションを構築するために使用できます。 +シンプルさを念頭に置いて構築されており、理解しやすく使いやすい方法で記述されています。 -> **注意:** `Flight::` を静的変数として使用する例と、`$app->` Engine オブジェクトを使用する例の両方を見ることになります。これらは互換性があり、どちらも使用可能です。コントローラー/ミドルウェア内の `$app` および `$this->app` が Flight チームのおすすめのアプローチです。 +> **注意:** `Flight::` を静的変数として使用する例と、`$app->` エンジンオブジェクトを使用する例の両方を見ることになります。これらは互換性があり、どちらも使用可能です。コントローラー/ミドルウェア内の `$app` および `$this->app` が、Flight チームのおすすめのアプローチです。 ## コアコンポーネント -### [Routing](/learn/routing) +### [ルーティング](/learn/routing) -ウェブアプリケーションのルートを管理する方法を学びます。これにはルートのグループ化、ルートパラメータ、ミドルウェアが含まれます。 +ウェブアプリケーションのルートを管理する方法を学びます。これにはルートのグループ化、ルートパラメータ、ミドルウェアも含まれます。 -### [Middleware](/learn/middleware) +### [ミドルウェア](/learn/middleware) -アプリケーションのリクエストとレスポンスをフィルタリングするためにミドルウェアを使用する方法を学びます。 +アプリケーション内のリクエストとレスポンスをフィルタリングするためにミドルウェアを使用する方法を学びます。 -### [Autoloading](/learn/autoloading) +### [オートローディング](/learn/autoloading) アプリケーション内で独自のクラスをオートロードする方法を学びます。 -### [Requests](/learn/requests) +### [リクエスト](/learn/requests) -アプリケーションでリクエストとレスポンスを処理する方法を学びます。 +アプリケーション内でリクエストとレスポンスを処理する方法を学びます。 -### [Responses](/learn/responses) +### [レスポンス](/learn/responses) -ユーザーにレスポンスを送信する方法を学びます。 +ユーザーへのレスポンス送信方法を学びます。 -### [HTML Templates](/learn/templates) +### [HTML テンプレート](/learn/templates) ビルトインのビューエンジンを使用して HTML テンプレートをレンダリングする方法を学びます。 -### [Security](/learn/security) +### [セキュリティ](/learn/security) アプリケーションを一般的なセキュリティ脅威から保護する方法を学びます。 -### [Configuration](/learn/configuration) +### [構成](/learn/configuration) アプリケーション向けにフレームワークを構成する方法を学びます。 -### [Event Manager](/learn/events) +### [イベントマネージャー](/learn/events) イベントシステムを使用してアプリケーションにカスタムイベントを追加する方法を学びます。 -### [Extending Flight](/learn/extending) +### [Flight の拡張](/learn/extending) 独自のメソッドとクラスを追加してフレームワークを拡張する方法を学びます。 -### [Method Hooks and Filtering](/learn/filtering) +### [メソッドフックとフィルタリング](/learn/filtering) -メソッドと内部フレームワークメソッドにイベントフックを追加する方法を学びます。 +メソッドおよび内部フレームワークメソッドにイベントフックを追加する方法を学びます。 -### [Dependency Injection Container (DIC)](/learn/dependency-injection-container) +### [依存性注入コンテナ (DIC)](/learn/dependency-injection-container) 依存性注入コンテナ (DIC) を使用してアプリケーションの依存関係を管理する方法を学びます。 ## ユーティリティクラス -### [Collections](/learn/collections) +### [コレクション](/learn/collections) コレクションはデータを保持し、配列またはオブジェクトとしてアクセスしやすくするために使用されます。 -### [JSON Wrapper](/learn/json) +### [JSON ラッパー](/learn/json) JSON のエンコードとデコードを一貫させるためのシンプルな関数がいくつかあります。 -### [PDO Wrapper](/learn/pdo-wrapper) +### [SimplePdo](/learn/simple-pdo) -PDO は時に必要以上に頭痛の種になることがあります。このシンプルなラッパークラスにより、データベースとのやり取りが大幅に簡単になります。 +PDO は時に必要以上に頭痛の種となります。SimplePdo は、`insert()`、`update()`、`delete()`、`transaction()` などの便利なメソッドを備えたモダンな PDO ヘルパークラスで、データベース操作をはるかに簡単に行えます。 -### [Uploaded File Handler](/learn/uploaded-file) +### [PdoWrapper](/learn/pdo-wrapper) (非推奨) -アップロードされたファイルを管理し、パーマネントな場所に移動するのを支援するシンプルなクラスです。 +v3.18.0 以降、元の PDO ラッパーは非推奨です。代わりに [SimplePdo](/learn/simple-pdo) を使用してください。 + +### [アップロードファイルハンドラー](/learn/uploaded-file) + +アップロードされたファイルを管理し、パーマネントな場所に移動するためのシンプルなクラスです。 ## 重要な概念 -### [なぜフレームワークか?](/learn/why-frameworks) +### [なぜフレームワークを使うのか?](/learn/why-frameworks) フレームワークを使用する理由についての短い記事です。フレームワークを使用する前に、その利点を理解しておくのが良い考えです。 -さらに、[@lubiana](https://git.php.fail/lubiana) によって作成された優れたチュートリアルがあります。Flight について特に詳細に触れていませんが、 -このガイドはフレームワークを取り巻く主要な概念とその利点について理解するのに役立ちます。 -チュートリアルは [ここ](https://git.php.fail/lubiana/no-framework-tutorial/src/branch/master/README.md) から見つかります。 +さらに、[@lubiana](https://git.php.fail/lubiana) によって優れたチュートリアルが作成されています。Flight について特に詳細に触れていませんが、 +このガイドはフレームワークを囲む主要な概念とその利点について理解するのに役立ちます。 +チュートリアルは [こちら](https://git.php.fail/lubiana/no-framework-tutorial/src/branch/master/README.md) にあります。 ### [Flight を他のフレームワークと比較](/learn/flight-vs-another-framework) -Laravel、Slim、Fat-Free、または Symfony などの他のフレームワークから Flight に移行する場合、このページは両者の違いを理解するのに役立ちます。 +Laravel、Slim、Fat-Free、または Symfony などの他のフレームワークから Flight に移行する場合、このページで両者の違いを理解するのに役立ちます。 ## その他のトピック @@ -93,10 +97,10 @@ Laravel、Slim、Fat-Free、または Symfony などの他のフレームワー Flight のコードを堅牢にするためのユニットテストの方法を学ぶためのガイドに従ってください。 -### [AI & Developer Experience](/learn/ai) +### [AI & 開発者エクスペリエンス](/learn/ai) -Flight が AI ツールと現代の開発者ワークフローと連携して、より速くスマートにコーディングするのにどのように役立つかを学びます。 +Flight が AI ツールとモダンな開発者ワークフローと連携して、より速く賢くコーディングするのにどのように役立つかを学びます。 ### [v2 から v3 への移行](/learn/migrating-to-v3) -後方互換性は大部分維持されていますが、v2 から v3 への移行時に知っておくべきいくつかの変更点があります。 \ No newline at end of file +後方互換性は主に維持されていますが、v2 から v3 への移行時に知っておくべき変更点がいくつかあります。 \ No newline at end of file diff --git a/content/v3/ja/learn/pdo_wrapper.md b/content/v3/ja/learn/pdo_wrapper.md index 495f82d1..60df83d9 100644 --- a/content/v3/ja/learn/pdo_wrapper.md +++ b/content/v3/ja/learn/pdo_wrapper.md @@ -1,20 +1,24 @@ -# PdoWrapper PDO ヘルパー クラス +# PdoWrapper PDO ヘルパークラス + +> **警告** +> +> **非推奨:** `PdoWrapper` は Flight v3.18.0 以降非推奨です。将来的なバージョンで削除されることはありませんが、後方互換性のためメンテナンスされます。代わりに [SimplePdo](/learn/simple-pdo) を使用してください。これは同じ機能を提供し、共通のデータベース操作のための追加のヘルパーメソッドも提供します。 ## 概要 -Flight の `PdoWrapper` クラスは、PDO を使用してデータベースを扱うための便利なヘルパーです。共通のデータベースタスクを簡素化し、結果を取得するための便利なメソッドを追加し、結果を [Collections](/learn/collections) として返して簡単にアクセスできるようにします。また、クエリログとアプリケーション パフォーマンス監視 (APM) をサポートし、高度なユースケースに対応します。 +Flight の `PdoWrapper` クラスは、PDO を使用してデータベースを操作するための親しみやすいヘルパーです。共通のデータベースタスクを簡素化し、結果を取得するための便利なメソッドを追加し、結果を [Collections](/learn/collections) として返して簡単にアクセスできるようにします。また、クエリログとアプリケーションのパフォーマンス監視 (APM) を高度なユースケースでサポートします。 ## 理解 -PHP でデータベースを扱う場合、特に PDO を直接使用すると冗長になりがちです。`PdoWrapper` は PDO を拡張し、クエリの実行、結果の取得、結果の処理をはるかに簡単にします。プリペアドステートメントやフェッチモードを扱う必要がなくなり、共通タスクのためのシンプルなメソッドが利用でき、すべての行が Collection として返されるため、配列やオブジェクト記法を使用できます。 +PHP でデータベースを操作する場合、特に PDO を直接使用すると冗長になることがあります。`PdoWrapper` は PDO を拡張し、クエリ、取得、結果の処理をはるかに簡単にします。準備されたステートメントやフェッチモードを扱う代わりに、共通のタスクのためのシンプルなメソッドが得られ、すべての行が Collection として返されるため、配列またはオブジェクト表記を使用できます。 -`PdoWrapper` を Flight で共有サービスとして登録し、アプリケーションのどこからでも `Flight::db()` を使用して利用できます。 +`PdoWrapper` を Flight で共有サービスとして登録し、`Flight::db()` を介してアプリケーションのどこでも使用できます。 ## 基本的な使用方法 ### PDO ヘルパーの登録 -まず、Flight に `PdoWrapper` クラスを登録します: +まず、`PdoWrapper` クラスを Flight に登録します: ```php Flight::register('db', \flight\database\PdoWrapper::class, [ @@ -27,7 +31,7 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ ]); ``` -これで、どこからでも `Flight::db()` を使用してデータベース接続を取得できます。 +これで、`Flight::db()` をどこでも使用してデータベース接続を取得できます。 ### クエリの実行 @@ -35,7 +39,7 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ `function runQuery(string $sql, array $params = []): PDOStatement` -INSERT や UPDATE、または結果を手動でフェッチしたい場合に使用します: +INSERT や UPDATE、または結果を手動で取得したい場合に使用します: ```php $db = Flight::db(); @@ -56,7 +60,7 @@ $db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]); `function fetchField(string $sql, array $params = []): mixed` -データベースから単一の値を取得します: +データベースから単一の値を入手します: ```php $count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']); @@ -66,7 +70,7 @@ $count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", `function fetchRow(string $sql, array $params = []): Collection` -単一の行を Collection (配列/オブジェクトアクセス) として取得します: +単一の行を Collection (配列/オブジェクトアクセス) として入手します: ```php $user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); @@ -79,7 +83,7 @@ echo $user->name; `function fetchAll(string $sql, array $params = []): array` -すべての行を Collections の配列として取得します: +すべての行を Collection の配列として入手します: ```php $users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); @@ -103,7 +107,7 @@ $users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", ['1,2,3'] ## 高度な使用方法 -### クエリログ & APM +### クエリログと APM クエリのパフォーマンスを追跡したい場合、登録時に APM 追跡を有効にします: @@ -113,13 +117,13 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ ]); ``` -クエリを実行した後、手動でログを記録できますが、APM が有効な場合は自動的にログが記録されます: +クエリを実行した後、手動でログを記録できますが、APM が有効な場合は自動的にログを記録します: ```php Flight::db()->logQueries(); ``` -これにより、接続とクエリメトリクスを含むイベント (`flight.db.queries`) がトリガーされ、Flight のイベントシステムを使用してリッスンできます。 +これはイベント (`flight.db.queries`) をトリガーし、接続とクエリメトリクスを含み、Flight のイベントシステムを使用してリッスンできます。 ### 完全な例 @@ -137,7 +141,7 @@ Flight::route('/users', function () { // 単一のユーザーを取得 $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); - // 単一の値を取得 + // 単一の値を入手 $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); // 特別な IN() 構文 @@ -154,7 +158,7 @@ Flight::route('/users', function () { // ユーザーを削除 Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]); - // 影響を受けた行数を表示 + // 影響を受けた行数を入手 $statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']); $affected_rows = $statement->rowCount(); }); @@ -166,10 +170,10 @@ Flight::route('/users', function () { ## トラブルシューティング -- データベース接続エラーが発生した場合、DSN、ユーザー名、パスワード、オプションを確認してください。 -- すべての行は Collections として返されます。プレーンな配列が必要な場合は、`$collection->getData()` を使用してください。 +- データベース接続に関するエラーが発生した場合、DSN、ユーザー名、パスワード、オプションを確認してください。 +- すべての行は Collection として返されます。プレーンな配列が必要な場合は、`$collection->getData()` を使用してください。 - `IN (?)` クエリの場合、配列またはカンマ区切りの文字列を渡すことを確認してください。 ## 変更履歴 -- v3.2.0 - 基本的なクエリとフェッチメソッドを備えた PdoWrapper の初回リリース。 \ No newline at end of file +- v3.2.0 - 基本的なクエリとフェッチメソッドを含む PdoWrapper の初期リリース。 \ No newline at end of file diff --git a/content/v3/ja/learn/simple_pdo.md b/content/v3/ja/learn/simple_pdo.md new file mode 100644 index 00000000..928297b4 --- /dev/null +++ b/content/v3/ja/learn/simple_pdo.md @@ -0,0 +1,320 @@ +# SimplePdo PDO ヘルパークラス + +## 概要 + +Flight の `SimplePdo` クラスは、PDO を使用したデータベース操作のためのモダンで機能豊富なヘルパーです。`PdoWrapper` を拡張し、`insert()`、`update()`、`delete()`、およびトランザクションなどの一般的なデータベース操作のための便利なヘルパーメソッドを追加します。データベースタスクを簡素化し、結果を [Collections](/learn/collections) として返して簡単なアクセスを可能にし、高度なユースケースのためのクエリログとアプリケーションのパフォーマンス監視 (APM) をサポートします。 + +## 理解 + +`SimplePdo` クラスは、PHP でのデータベース操作をはるかに簡単に設計されています。プリペアドステートメント、フェッチモード、冗長な SQL 操作を扱う代わりに、一般的なタスクのためのクリーンでシンプルなメソッドが得られます。各行は Collection として返されるため、配列表記 (`$row['name']`) とオブジェクト表記 (`$row->name`) の両方を使用できます。 + +このクラスは `PdoWrapper` のスーパーセットであり、`PdoWrapper` のすべての機能に加えて、コードをよりクリーンで保守しやすくする追加のヘルパーメソッドを含みます。現在 `PdoWrapper` を使用している場合、`SimplePdo` へのアップグレードは `PdoWrapper` を拡張しているため簡単です。 + +Flight で `SimplePdo` を共有サービスとして登録し、`Flight::db()` を使用してアプリのどこからでも使用できます。 + +## 基本的な使用方法 + +### SimplePdo の登録 + +まず、Flight に `SimplePdo` クラスを登録します: + +```php +Flight::register('db', \flight\database\SimplePdo::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 + ] +]); +``` + +> **注意** +> +> `PDO::ATTR_DEFAULT_FETCH_MODE` を指定しない場合、`SimplePdo` は自動的に `PDO::FETCH_ASSOC` に設定します。 + +これで、どこからでも `Flight::db()` を使用してデータベース接続を取得できます。 + +### クエリの実行 + +#### `runQuery()` + +`function runQuery(string $sql, array $params = []): PDOStatement` + +INSERT、UPDATE、または結果を手動でフェッチする場合に使用します: + +```php +$db = Flight::db(); +$statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']); +while ($row = $statement->fetch()) { + // $row は配列です +} +``` + +書き込みにも使用できます: + +```php +$db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); +$db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]); +``` + +#### `fetchField()` + +`function fetchField(string $sql, array $params = []): mixed` + +データベースから単一の値を入手します: + +```php +$count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']); +``` + +#### `fetchRow()` + +`function fetchRow(string $sql, array $params = []): ?Collection` + +単一の行を Collection (配列/オブジェクトアクセス) として入手します: + +```php +$user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); +echo $user['name']; +// または +echo $user->name; +``` + +> **ヒント** +> +> `SimplePdo` は、`fetchRow()` クエリにすでに存在しない場合に自動的に `LIMIT 1` を追加し、クエリをより効率的にします。 + +#### `fetchAll()` + +`function fetchAll(string $sql, array $params = []): array` + +すべての行を Collections の配列として入手します: + +```php +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); +foreach ($users as $user) { + echo $user['name']; + // または + echo $user->name; +} +``` + +#### `fetchColumn()` + +`function fetchColumn(string $sql, array $params = []): array` + +単一の列を配列としてフェッチします: + +```php +$ids = Flight::db()->fetchColumn("SELECT id FROM users WHERE active = ?", [1]); +// 戻り値: [1, 2, 3, 4, 5] +``` + +#### `fetchPairs()` + +`function fetchPairs(string $sql, array $params = []): array` + +結果をキー-バリューペア (最初の列をキー、2番目の列を値) としてフェッチします: + +```php +$userNames = Flight::db()->fetchPairs("SELECT id, name FROM users"); +// 戻り値: [1 => 'John', 2 => 'Jane', 3 => 'Bob'] +``` + +### `IN()` プレースホルダーの使用 + +`IN()` 句で単一の `?` を使用し、配列を渡すことができます: + +```php +$ids = [1, 2, 3]; +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); +``` + +## ヘルパーメソッド + +`SimplePdo` の `PdoWrapper` に対する主な利点の1つは、一般的なデータベース操作のための便利なヘルパーメソッドの追加です。 + +### `insert()` + +`function insert(string $table, array $data): string` + +1つまたは複数の行を挿入し、最後の挿入 ID を返します。 + +**単一の挿入:** + +```php +$id = Flight::db()->insert('users', [ + 'name' => 'John', + 'email' => 'john@example.com' +]); +``` + +**一括挿入:** + +```php +$id = Flight::db()->insert('users', [ + ['name' => 'John', 'email' => 'john@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'], +]); +``` + +### `update()` + +`function update(string $table, array $data, string $where, array $whereParams = []): int` + +行を更新し、影響を受けた行の数を返します: + +```php +$affected = Flight::db()->update( + 'users', + ['name' => 'Jane', 'email' => 'jane@example.com'], + 'id = ?', + [1] +); +``` + +> **注意** +> +> SQLite の `rowCount()` は、データが実際に変更された行の数を返します。行を既存の値と同じ値で更新した場合、`rowCount()` は 0 を返します。これは、`PDO::MYSQL_ATTR_FOUND_ROWS` を使用した MySQL の動作とは異なります。 + +### `delete()` + +`function delete(string $table, string $where, array $whereParams = []): int` + +行を削除し、削除された行の数を返します: + +```php +$deleted = Flight::db()->delete('users', 'id = ?', [1]); +``` + +### `transaction()` + +`function transaction(callable $callback): mixed` + +トランザクション内でコールバックを実行します。トランザクションは成功時に自動的にコミットされ、エラー時にロールバックされます: + +```php +$result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John']); + $db->insert('logs', ['action' => 'user_created']); + return $db->lastInsertId(); +}); +``` + +コールバック内で例外が発生した場合、トランザクションは自動的にロールバックされ、例外が再スローされます。 + +## 高度な使用方法 + +### クエリログと APM + +クエリのパフォーマンスを追跡したい場合、登録時に APM 追跡を有効にします: + +```php +Flight::register('db', \flight\database\SimplePdo::class, [ + 'mysql:host=localhost;dbname=cool_db_name', + 'user', + 'pass', + [/* PDO options */], + [ + 'trackApmQueries' => true, + 'maxQueryMetrics' => 1000 + ] +]); +``` + +クエリを実行した後、手動でログを記録できますが、有効にされている場合 APM は自動的にログを記録します: + +```php +Flight::db()->logQueries(); +``` + +これにより、接続とクエリメトリクスを含むイベント (`flight.db.queries`) がトリガーされ、Flight のイベントシステムを使用してリッスンできます。 + +### 完全な例 + +```php +Flight::route('/users', function () { + // すべてのユーザーを取得 + $users = Flight::db()->fetchAll('SELECT * FROM users'); + + // すべてのユーザーをストリーム + $statement = Flight::db()->runQuery('SELECT * FROM users'); + while ($user = $statement->fetch()) { + echo $user['name']; + } + + // 単一のユーザーを取得 + $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); + + // 単一の値を入手 + $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); + + // 単一の列を取得 + $ids = Flight::db()->fetchColumn('SELECT id FROM users'); + + // キー-バリューペアを取得 + $userNames = Flight::db()->fetchPairs('SELECT id, name FROM users'); + + // 特別な IN() 構文 + $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); + + // 新しいユーザーを挿入 + $id = Flight::db()->insert('users', [ + 'name' => 'Bob', + 'email' => 'bob@example.com' + ]); + + // ユーザーを一括挿入 + Flight::db()->insert('users', [ + ['name' => 'Bob', 'email' => 'bob@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'] + ]); + + // ユーザーを更新 + $affected = Flight::db()->update('users', ['name' => 'Bob'], 'id = ?', [123]); + + // ユーザーを削除 + $deleted = Flight::db()->delete('users', 'id = ?', [123]); + + // トランザクションを使用 + $result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John', 'email' => 'john@example.com']); + $db->insert('audit_log', ['action' => 'user_created']); + return $db->lastInsertId(); + }); +}); +``` + +## PdoWrapper からの移行 + +現在 `PdoWrapper` を使用している場合、`SimplePdo` への移行は簡単です: + +1. **登録を更新:** + ```php + // 旧 + Flight::register('db', \flight\database\PdoWrapper::class, [ /* ... */ ]); + + // 新 + Flight::register('db', \flight\database\SimplePdo::class, [ /* ... */ ]); + ``` + +2. **すべての既存の `PdoWrapper` メソッドが `SimplePdo` で動作** - 破壊的な変更はありません。既存のコードは引き続き動作します。 + +3. **新しいヘルパーメソッドをオプションで使用** - `insert()`、`update()`、`delete()`、`transaction()` を使用してコードを簡素化します。 + +## 関連項目 + +- [Collections](/learn/collections) - 簡単なデータアクセスに Collection クラスを使用する方法を学びます。 +- [PdoWrapper](/learn/pdo-wrapper) - レガシー PDO ヘルパークラス (非推奨)。 + +## トラブルシューティング + +- データベース接続に関するエラーが発生した場合、DSN、ユーザー名、パスワード、オプションを確認してください。 +- すべての行は Collections として返されます - プレーン配列が必要な場合、`$collection->getData()` を使用してください。 +- `IN (?)` クエリの場合、配列を渡すことを確認してください。 +- 長時間実行プロセスでクエリログによるメモリの問題が発生している場合、`maxQueryMetrics` オプションを調整してください。 + +## 変更履歴 + +- v3.18.0 - insert、update、delete、およびトランザクションのためのヘルパーメソッド付き SimplePdo の初期リリース。 \ No newline at end of file diff --git a/content/v3/ko/awesome-plugins/awesome_plugins.md b/content/v3/ko/awesome-plugins/awesome_plugins.md index 6a5f3a4e..474ddff6 100644 --- a/content/v3/ko/awesome-plugins/awesome_plugins.md +++ b/content/v3/ko/awesome-plugins/awesome_plugins.md @@ -1,36 +1,36 @@ # 멋진 플러그인 -Flight는 놀라울 정도로 확장 가능합니다. Flight 애플리케이션에 기능을 추가하는 데 사용할 수 있는 여러 플러그인이 있습니다. 일부는 Flight 팀에서 공식적으로 지원하며, 다른 일부는 시작하는 데 도움을 주는 마이크로/라이트 라이브러리입니다. +Flight는 놀라울 정도로 확장 가능합니다. Flight 애플리케이션에 기능을 추가하는 데 사용할 수 있는 여러 플러그인이 있습니다. 일부는 Flight 팀에서 공식적으로 지원하며, 다른 일부는 시작하는 데 도움이 되는 마이크로/라이트 라이브러리입니다. ## API 문서화 -API 문서화는 모든 API에 필수적입니다. 개발자들이 API와 상호 작용하는 방법을 이해하고 반환되는 것을 예상할 수 있도록 도와줍니다. Flight 프로젝트에 대한 API 문서화를 생성하는 데 도움이 되는 몇 가지 도구가 있습니다. +API 문서화는 모든 API에 필수적입니다. 개발자들이 API와 상호 작용하는 방법을 이해하고 반환되는 것을 예상할 수 있도록 돕습니다. Flight 프로젝트에 대한 API 문서화를 생성하는 데 도움이 되는 몇 가지 도구가 있습니다. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber가 작성한 블로그 포스트로, API 우선 접근 방식을 사용하여 FlightPHP와 함께 OpenAPI 사양을 사용하는 방법에 대해 설명합니다. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Daniel Schreiber가 작성한 블로그 포스트로, OpenAPI 사양을 FlightPHP와 함께 사용하여 API 우선 접근 방식을 통해 API를 구축하는 방법에 대해 설명합니다. - [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI는 Flight 프로젝트에 대한 API 문서화를 생성하는 데 도움이 되는 훌륭한 도구입니다. 사용하기 매우 쉽고 필요에 맞게 사용자 지정할 수 있습니다. 이는 Swagger 문서화를 생성하는 데 도움이 되는 PHP 라이브러리입니다. ## 애플리케이션 성능 모니터링 (APM) -애플리케이션 성능 모니터링 (APM)은 모든 애플리케이션에 필수적입니다. 애플리케이션이 어떻게 작동하는지 이해하고 병목 현상이 어디에 있는지 파악하는 데 도움을 줍니다. Flight와 함께 사용할 수 있는 여러 APM 도구가 있습니다. -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM은 Flight 애플리케이션을 모니터링하는 데 사용할 수 있는 간단한 APM 라이브러리입니다. 애플리케이션의 성능을 모니터링하고 병목 현상을 식별하는 데 도움을 줄 수 있습니다. +애플릭케이션 성능 모니터링 (APM)은 모든 애플리케이션에 필수적입니다. 애플리케이션이 어떻게 작동하는지 이해하고 병목 현상이 어디에 있는지 파악하는 데 도움이 됩니다. Flight와 함께 사용할 수 있는 여러 APM 도구가 있습니다. +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM은 Flight 애플리케이션을 모니터링하는 데 사용할 수 있는 간단한 APM 라이브러리입니다. 애플리케이션의 성능을 모니터링하고 병목 현상을 식별하는 데 도움이 됩니다. -## 비동기 +## Async Flight는 이미 빠른 프레임워크이지만, 터보 엔진을 장착하면 모든 것이 더 재미있고 (도전적) 됩니다! -- [flightphp/async](/awesome-plugins/async) - 공식 Flight Async 라이브러리입니다. 이 라이브러리는 애플리케이션에 비동기 처리를 추가하는 간단한 방법입니다. Swoole/Openswoole을 내부적으로 사용하여 작업을 비동기적으로 실행하는 간단하고 효과적인 방법을 제공합니다. +- [flightphp/async](/awesome-plugins/async) - 공식 Flight Async 라이브러리. 이 라이브러리는 애플리케이션에 비동기 처리를 추가하는 간단한 방법입니다. Swoole/Openswoole을 내부적으로 사용하여 작업을 비동기적으로 실행하는 간단하고 효과적인 방법을 제공합니다. ## 권한 부여/권한 권한 부여와 권한은 누가 무엇에 접근할 수 있는지에 대한 제어가 필요한 모든 애플리케이션에 필수적입니다. -- official [flightphp/permissions](/awesome-plugins/permissions) - 공식 Flight Permissions 라이브러리입니다. 이 라이브러리는 애플리케이션에 사용자 및 애플리케이션 수준의 권한을 추가하는 간단한 방법입니다. +- official [flightphp/permissions](/awesome-plugins/permissions) - 공식 Flight Permissions 라이브러리. 이 라이브러리는 애플리케이션에 사용자 및 애플리케이션 수준의 권한을 추가하는 간단한 방법입니다. ## 인증 인증은 사용자 ID를 확인하고 API 엔드포인트를 보호해야 하는 애플리케이션에 필수적입니다. -- [firebase/php-jwt](/awesome-plugins/jwt) - PHP용 JSON Web Token (JWT) 라이브러리입니다. Flight 애플리케이션에서 토큰 기반 인증을 구현하는 간단하고 안전한 방법입니다. 상태 비저장 API 인증, 미들웨어를 사용한 라우트 보호, OAuth 스타일의 권한 부여 흐름 구현에 완벽합니다. +- [firebase/php-jwt](/awesome-plugins/jwt) - PHP용 JSON Web Token (JWT) 라이브러리. Flight 애플리케이션에 토큰 기반 인증을 구현하는 간단하고 안전한 방법입니다. 상태 비저장 API 인증, 미들웨어를 사용한 경로 보호, OAuth 스타일의 권한 부여 흐름 구현에 완벽합니다. ## 캐싱 @@ -40,13 +40,13 @@ Flight는 이미 빠른 프레임워크이지만, 터보 엔진을 장착하면 ## CLI -CLI 애플리케이션은 애플리케이션과 상호 작용하는 훌륭한 방법입니다. 컨트롤러 생성, 모든 라우트 표시 등에 사용할 수 있습니다. +CLI 애플리케이션은 애플리케이션과 상호 작용하는 훌륭한 방법입니다. 컨트롤러 생성, 모든 경로 표시 등에 사용할 수 있습니다. -- official [flightphp/runway](/awesome-plugins/runway) - Runway는 Flight 애플리케이션을 관리하는 데 도움을 주는 CLI 애플리케이션입니다. +- official [flightphp/runway](/awesome-plugins/runway) - Runway는 Flight 애플리케이션을 관리하는 데 도움이 되는 CLI 애플리케이션입니다. ## 쿠키 -쿠키는 클라이언트 측에서 작은 데이터 조각을 저장하는 훌륭한 방법입니다. 사용자 선호도, 애플리케이션 설정 등을 저장하는 데 사용할 수 있습니다. +쿠키는 클라이언트 측에 작은 데이터 조각을 저장하는 훌륭한 방법입니다. 사용자 선호도, 애플리케이션 설정 등을 저장하는 데 사용할 수 있습니다. - [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie는 쿠키를 관리하는 간단하고 효과적인 방법을 제공하는 PHP 라이브러리입니다. @@ -54,49 +54,50 @@ CLI 애플리케이션은 애플리케이션과 상호 작용하는 훌륭한 디버깅은 로컬 환경에서 개발할 때 필수적입니다. 디버깅 경험을 향상시킬 수 있는 몇 가지 플러그인이 있습니다. -- [tracy/tracy](/awesome-plugins/tracy) - Flight와 함께 사용할 수 있는 완전한 기능을 갖춘 오류 핸들러입니다. 애플리케이션을 디버깅하는 데 도움을 주는 여러 패널이 있습니다. 확장하기 쉽고 자체 패널을 추가할 수도 있습니다. -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) 오류 핸들러와 함께 사용되며, Flight 프로젝트에 특화된 디버깅을 돕기 위해 몇 가지 추가 패널을 제공하는 플러그인입니다. +- [tracy/tracy](/awesome-plugins/tracy) - Flight와 함께 사용할 수 있는 완전한 기능을 갖춘 오류 핸들러입니다. 애플리케이션을 디버깅하는 데 도움이 되는 여러 패널이 있습니다. 확장하기 매우 쉽고 자체 패널을 추가할 수도 있습니다. +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - [Tracy](/awesome-plugins/tracy) 오류 핸들러와 함께 사용되며, 이 플러그인은 Flight 프로젝트에 특화된 디버깅을 돕기 위해 몇 가지 추가 패널을 추가합니다. ## 데이터베이스 -데이터베이스는 대부분의 애플리케이션의 핵심입니다. 데이터를 저장하고 검색하는 방법입니다. 일부 데이터베이스 라이브러리는 쿼리를 작성하는 단순한 래퍼이고, 일부는 완전한 ORM입니다. +데이터베이스는 대부분의 애플리케이션의 핵심입니다. 데이터를 저장하고 검색하는 방법입니다. 일부 데이터베이스 라이브러리는 쿼리를 작성하는 단순한 래퍼이고, 일부는 완전한 ORMs입니다. -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 코어의 일부인 공식 Flight PDO Wrapper입니다. 쿼리를 작성하고 실행하는 과정을 단순화하는 데 도움을 주는 간단한 래퍼입니다. ORM이 아닙니다. -- official [flightphp/active-record](/awesome-plugins/active-record) - 공식 Flight ActiveRecord ORM/Mapper입니다. 데이터베이스에서 데이터를 쉽게 검색하고 저장하는 훌륭한 작은 라이브러리입니다. -- [byjg/php-migration](/awesome-plugins/migrations) - 프로젝트의 모든 데이터베이스 변경 사항을 추적하는 플러그인입니다. +- official [flightphp/core SimplePdo](/learn/simple-pdo) - 코어의 일부인 공식 Flight PDO 도우미. `insert()`, `update()`, `delete()`, `transaction()`과 같은 편리한 도우미 메서드를 가진 현대적인 래퍼로 데이터베이스 작업을 단순화합니다. 모든 결과는 유연한 배열/객체 접근을 위해 컬렉션으로 반환됩니다. ORM이 아니며, PDO를 더 잘 작업하는 방법일 뿐입니다. +- deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 코어의 일부인 공식 Flight PDO 래퍼 (v3.18.0부터 deprecated). 대신 SimplePdo를 사용하세요. +- official [flightphp/active-record](/awesome-plugins/active-record) - 공식 Flight ActiveRecord ORM/Mapper. 데이터베이스에서 데이터를 쉽게 검색하고 저장하는 훌륭한 작은 라이브러리입니다. +- [byjg/php-migration](/awesome-plugins/migrations) - 프로젝트의 모든 데이터베이스 변경 사항을 추적하는 플러그인. ## 암호화 -암호화는 민감한 데이터를 저장하는 모든 애플리케이션에 필수적입니다. 데이터를 암호화하고 복호화하는 것은 그리 어렵지 않지만, 암호화 키를 적절히 저장하는 것은 [어렵습니다](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [있습니다](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [입니다](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). 가장 중요한 것은 암호화 키를 공개 디렉토리에 저장하거나 코드 저장소에 커밋하지 않는 것입니다. +암호화는 민감한 데이터를 저장하는 모든 애플리케이션에 필수적입니다. 데이터를 암호화하고 복호화하는 것은 어렵지 않지만, 암호화 키를 적절히 저장하는 [것은](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [어렵](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [습니다](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). 가장 중요한 것은 암호화 키를 공개 디렉토리에 저장하지 않거나 코드 저장소에 커밋하지 않는 것입니다. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - 데이터를 암호화하고 복호화하는 데 사용할 수 있는 라이브러리입니다. 데이터를 암호화하고 복호화하는 데 시작하기가 상당히 간단합니다. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - 데이터를 암호화하고 복호화하는 데 사용할 수 있는 라이브러리입니다. 데이터를 암호화하고 복호화하기 시작하는 것이 상당히 간단합니다. ## 작업 큐 -작업 큐는 작업을 비동기적으로 처리하는 데 매우 유용합니다. 이메일 보내기, 이미지 처리 또는 실시간으로 수행할 필요가 없는 모든 작업에 사용할 수 있습니다. +작업 큐는 작업을 비동기적으로 처리하는 데 매우 도움이 됩니다. 이메일 보내기, 이미지 처리 또는 실시간으로 수행할 필요가 없는 모든 작업에 사용할 수 있습니다. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue는 작업을 비동기적으로 처리하는 데 사용할 수 있는 라이브러리입니다. beanstalkd, MySQL/MariaDB, SQLite, PostgreSQL과 함께 사용할 수 있습니다. ## 세션 -세션은 API에는 별로 유용하지 않지만, 웹 애플리케이션을 구축할 때 상태와 로그인 정보를 유지하는 데 필수적일 수 있습니다. +세션은 API에는 정말 유용하지 않지만 웹 애플리케이션을 구축할 때 상태와 로그인 정보를 유지하는 데 필수적일 수 있습니다. -- official [flightphp/session](/awesome-plugins/session) - 공식 Flight Session 라이브러리입니다. 세션 데이터를 저장하고 검색하는 데 사용할 수 있는 간단한 세션 라이브러리입니다. PHP의 내장 세션 처리를 사용합니다. +- official [flightphp/session](/awesome-plugins/session) - 공식 Flight Session 라이브러리. 세션 데이터를 저장하고 검색하는 데 사용할 수 있는 간단한 세션 라이브러리입니다. PHP의 내장 세션 처리를 사용합니다. - [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 세션 관리자 (비차단, 플래시, 세그먼트, 세션 암호화). 세션 데이터의 선택적 암호화/복호화를 위해 PHP open_ssl을 사용합니다. ## 템플릿 템플릿은 UI가 있는 모든 웹 애플리케이션의 핵심입니다. Flight와 함께 사용할 수 있는 여러 템플릿 엔진이 있습니다. -- deprecated [flightphp/core View](/learn#views) - 코어의 일부인 매우 기본적인 템플릿 엔진입니다. 프로젝트에 몇 페이지 이상이 있다면 사용하지 않는 것이 좋습니다. -- [latte/latte](/awesome-plugins/latte) - Latte는 사용하기 매우 쉽고 Twig나 Smarty보다 PHP 구문에 더 가까운 느낌의 완전한 기능을 갖춘 템플릿 엔진입니다. 확장하기 쉽고 자체 필터와 함수를 추가할 수도 있습니다. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate는 자산 컴파일, 템플릿 상속, 변수 처리 기능을 가진 강력한 PHP 템플릿 엔진입니다. 자동 CSS/JS 최소화, 캐싱, Base64 인코딩, 선택적 Flight PHP 프레임워크 통합을 제공합니다. +- deprecated [flightphp/core View](/learn#views) - 코어의 일부인 매우 기본적인 템플릿 엔진입니다. 프로젝트에 몇 페이지 이상이 있으면 사용하지 않는 것이 좋습니다. +- [latte/latte](/awesome-plugins/latte) - Latte는 사용하기 매우 쉽고 Twig이나 Smarty보다 PHP 구문에 더 가까운 느낌의 완전한 기능을 갖춘 템플릿 엔진입니다. 확장하기 매우 쉽고 자체 필터와 함수를 추가할 수도 있습니다. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate는 에셋 컴파일, 템플릿 상속, 변수 처리 기능을 가진 강력한 PHP 템플릿 엔진입니다. 자동 CSS/JS 최소화, 캐싱, Base64 인코딩, 선택적 Flight PHP 프레임워크 통합을 특징으로 합니다. ## WordPress 통합 WordPress 프로젝트에서 Flight를 사용하고 싶으신가요? 이를 위한 편리한 플러그인이 있습니다! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 이 WordPress 플러그인은 WordPress와 함께 Flight를 실행할 수 있게 합니다. WordPress 사이트에 사용자 지정 API, 마이크로서비스 또는 전체 앱을 Flight 프레임워크를 사용하여 추가하는 데 완벽합니다. 두 세계의 장점을 모두 누리고 싶다면 매우 유용합니다! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 이 WordPress 플러그인은 Flight를 WordPress와 함께 실행할 수 있게 합니다. WordPress 사이트에 사용자 지정 API, 마이크로서비스 또는 전체 앱을 Flight 프레임워크를 사용하여 추가하는 데 완벽합니다. 두 세계의 장점을 모두 누리고 싶다면 매우 유용합니다! ## 기여 diff --git a/content/v3/ko/awesome-plugins/jwt.md b/content/v3/ko/awesome-plugins/jwt.md index 4c23b8f3..44d33e65 100644 --- a/content/v3/ko/awesome-plugins/jwt.md +++ b/content/v3/ko/awesome-plugins/jwt.md @@ -1,12 +1,12 @@ -# Firebase JWT - JSON Web Token 인증을 위한 Flight +# Firebase JWT - JSON Web Token 인증 -JWT (JSON Web Tokens)는 애플리케이션과 클라이언트 간에 클레임을 나타내는 컴팩트하고 URL-안전한 방법입니다. 서버 측 세션 저장소가 필요 없는 stateless API 인증에 완벽합니다! 이 가이드는 [Firebase JWT](https://github.com/firebase/php-jwt)를 Flight와 통합하여 안전한 토큰 기반 인증을 구현하는 방법을 보여줍니다. +JWT (JSON Web Tokens)는 애플리케이션과 클라이언트 간의 클레임을 표현하는 컴팩트하고 URL 안전한 방법입니다. 서버 측 세션 저장소가 필요 없는 stateless API 인증에 완벽합니다! 이 가이드는 [Firebase JWT](https://github.com/firebase/php-jwt)를 Flight와 통합하여 안전한 토큰 기반 인증을 구현하는 방법을 보여줍니다. 전체 문서와 세부 사항은 [Github 저장소](https://github.com/firebase/php-jwt)를 방문하세요. ## JWT란 무엇인가? -JSON Web Token은 세 부분을 포함하는 문자열입니다: +JSON Web Token은 세 부분으로 구성된 문자열입니다: 1. **헤더**: 토큰에 대한 메타데이터 (알고리즘, 유형) 2. **페이로드**: 데이터 (사용자 ID, 역할, 만료 등) 3. **서명**: 진위성을 확인하기 위한 암호화 서명 @@ -16,10 +16,10 @@ JSON Web Token은 세 부분을 포함하는 문자열입니다: ### JWT를 사용하는 이유는? - **Stateless**: 서버 측 세션 저장소가 필요 없음—마이크로서비스와 API에 완벽 -- **확장성**: 세션 affinity 요구사항이 없어 로드 밸런서와 잘 작동 -- **크로스 도메인**: 다른 도메인과 서비스 간에 사용 가능 -- **모바일 친화적**: 쿠키가 잘 작동하지 않는 모바일 앱에 좋음 -- **표준화**: 산업 표준 접근법 (RFC 7519) +- **확장 가능**: 세션 affinity 요구 사항이 없어 로드 밸런서와 잘 작동 +- **크로스 도메인**: 다른 도메인과 서비스 간에 사용할 수 있음 +- **모바일 친화적**: 쿠키가 잘 작동하지 않는 모바일 앱에 훌륭 +- **표준화**: 산업 표준 접근 방식 (RFC 7519) ## 설치 @@ -31,7 +31,7 @@ composer require firebase/php-jwt ## 기본 사용법 -JWT 생성 및 확인의 간단한 예제입니다: +JWT 생성 및 검증의 간단한 예제입니다: ```php use Firebase\JWT\JWT; @@ -52,7 +52,7 @@ $payload = [ $jwt = JWT::encode($payload, $secretKey, 'HS256'); echo "Token: " . $jwt; -// 토큰 확인 및 디코딩 +// 토큰 검증 및 디코딩 try { $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); echo "User ID: " . $decoded->user_id; @@ -61,11 +61,11 @@ try { } ``` -## Flight를 위한 JWT 미들웨어 (권장 접근법) +## Flight를 위한 JWT 미들웨어 (권장 접근 방식) -Flight에서 JWT를 가장 일반적이고 유용하게 사용하는 방법은 API 경로를 보호하는 **미들웨어**입니다. 여기 완전하고 프로덕션 준비된 예제가 있습니다: +Flight에서 JWT를 사용하는 가장 일반적이고 유용한 방법은 API 경로를 보호하는 **미들웨어**입니다. 완전하고 프로덕션 준비된 예제입니다: -### 1단계: JWT 미들웨어 클래스 생성 +### 단계 1: JWT 미들웨어 클래스 생성 ```php // app/middleware/JwtMiddleware.php @@ -82,14 +82,14 @@ class JwtMiddleware { public function __construct(Engine $app) { $this->app = $app; - // 비밀 키를 app/config/config.php에 저장하세요. 하드코딩하지 마세요! + // 비밀 키를 app/config/config.php에 저장하세요, 하드코딩하지 마세요! $this->secretKey = $app->get('config')['jwt_secret']; } public function before(array $params) { $authHeader = $this->app->request()->getHeader('Authorization'); - // Authorization 헤더 존재 확인 + // Authorization 헤더 존재 여부 확인 if (empty($authHeader)) { $this->app->jsonHalt(['error' => 'No authorization token provided'], 401); } @@ -102,10 +102,10 @@ class JwtMiddleware { $jwt = $matches[1]; try { - // 토큰 디코딩 및 확인 + // 토큰 디코딩 및 검증 $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); - // 라우트 핸들러에서 사용할 사용자 데이터를 요청에 저장 + // 라우트 핸들러에서 사용하기 위해 사용자 데이터를 요청에 저장 $this->app->request()->data->user = $decoded; } catch (ExpiredException $e) { @@ -119,7 +119,7 @@ class JwtMiddleware { } ``` -### 2단계: 구성에 JWT 비밀 등록 +### 단계 2: 구성에 JWT 비밀 키 등록 ```php // app/config/config.php @@ -128,13 +128,13 @@ return [ ]; // app/config/bootstrap.php 또는 index.php -// 구성에 앱을 노출하려면 이 줄을 추가하세요 +// 구성 파일을 앱에 노출하려면 이 줄을 추가하세요 $app->set('config', $config); ``` > **보안 주의**: 비밀 키를 하드코딩하지 마세요! 프로덕션에서는 환경 변수를 사용하세요. -### 3단계: 미들웨어로 경로 보호 +### 단계 3: 미들웨어로 경로 보호 ```php // 단일 경로 보호 @@ -145,7 +145,7 @@ Flight::route('GET /api/user/profile', function() { 'username' => $user->username, 'role' => $user->role ]); -})->addMiddleware( JwtMiddleware::class); +})->addMiddleware(JwtMiddleware::class); // 전체 경로 그룹 보호 (더 일반적!) Flight::group('/api', function() { @@ -162,7 +162,7 @@ Flight::group('/api', function() { ### 1. 로그인 엔드포인트 (토큰 생성) -성공적인 인증 후 JWT를 생성하는 경로를 만드세요: +인증 성공 후 JWT를 생성하는 경로를 만드세요: ```php Flight::route('POST /api/login', function() { @@ -170,7 +170,7 @@ Flight::route('POST /api/login', function() { $username = $data->username ?? ''; $password = $data->password ?? ''; - // 자격 증명 확인 (예제 - 자체 로직 사용!) + // 자격 증명 검증 (예제 - 자체 로직 사용!) $user = validateUserCredentials($username, $password); if (!$user) { @@ -197,7 +197,7 @@ Flight::route('POST /api/login', function() { }); function validateUserCredentials($username, $password) { - // 데이터베이스 조회 및 비밀번호 확인 로직 + // 데이터베이스 조회 및 비밀번호 검증은 여기에 // 예제: $db = Flight::db(); $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); @@ -213,13 +213,13 @@ function validateUserCredentials($username, $password) { } ``` -### 2. 토큰 새로고침 흐름 +### 2. 토큰 갱신 흐름 -장기 세션을 위한 새로고침 토큰 시스템을 구현하세요: +장기 세션을 위한 리프레시 토큰 시스템을 구현하세요: ```php Flight::route('POST /api/login', function() { - // ... 자격 증명 확인 ... + // ... 자격 증명 검증 ... $secretKey = Flight::get('config')['jwt_secret']; $refreshSecret = Flight::get('config')['jwt_refresh_secret']; @@ -232,7 +232,7 @@ Flight::route('POST /api/login', function() { 'exp' => time() + (15 * 60) ], $secretKey, 'HS256'); - // 장기 새로고침 토큰 (7일) + // 장기 리프레시 토큰 (7일) $refreshToken = JWT::encode([ 'user_id' => $user->id, 'type' => 'refresh', @@ -254,7 +254,7 @@ Flight::route('POST /api/refresh', function() { try { $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); - // 새로고침 토큰인지 확인 + // 리프레시 토큰인지 확인 if ($decoded->type !== 'refresh') { Flight::jsonHalt(['error' => 'Invalid token type'], 401); } @@ -347,7 +347,7 @@ class RateLimitMiddleware { ### 1. 강력한 비밀 키 사용 ```php -// 안전한 비밀 키 생성 (한 번 실행 후 .env 파일에 저장) +// 안전한 비밀 키 생성 (한 번 실행하고 .env 파일에 저장) $secretKey = base64_encode(random_bytes(32)); echo $secretKey; // .env 파일에 저장하세요! ``` @@ -362,7 +362,7 @@ echo $secretKey; // .env 파일에 저장하세요! // JWT_SECRET=your-base64-encoded-secret-here // JWT_REFRESH_SECRET=another-base64-encoded-secret-here -// app/config/config.php 파일에도 비밀을 저장할 수 있습니다 +// 앱 구성 파일을 사용하여 비밀 저장할 수도 있음 // 구성 파일이 버전 제어에 커밋되지 않도록 하세요 // return [ // 'jwt_secret' => 'your-base64-encoded-secret-here', @@ -376,26 +376,26 @@ $secretKey = getenv('JWT_SECRET'); ### 3. 적절한 만료 시간 설정 ```php -// 모범 사례: 단기 액세스 토큰 +// 좋은 관행: 단기 액세스 토큰 'exp' => time() + (15 * 60) // 15분 -// 새로고침 토큰: 더 긴 만료 +// 리프레시 토큰: 더 긴 만료 'exp' => time() + (7 * 24 * 60 * 60) // 7일 ``` ### 4. 프로덕션에서 HTTPS 사용 -JWT는 **항상** HTTPS를 통해 전송해야 합니다. 프로덕션에서 평문 HTTP로 토큰을 보내지 마세요! +JWT는 **항상** HTTPS를 통해 전송되어야 합니다. 프로덕션에서 평문 HTTP로 토큰을 보내지 마세요! -### 5. 토큰 클레임 확인 +### 5. 토큰 클레임 검증 -중요한 클레임을 항상 확인하세요: +중요한 클레임을 항상 검증하세요: ```php $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); // 만료 확인은 라이브러리에서 자동 처리 -// 하지만 사용자 지정 확인을 추가할 수 있습니다: +// 하지만 사용자 지정 검증 추가 가능: if ($decoded->iat > time()) { throw new Exception('Token used before it was issued'); } @@ -434,7 +434,7 @@ public function before(array $params) { $this->app->jsonHalt(['error' => 'Token has been revoked'], 401); } - // ... 토큰 확인 ... + // ... 토큰 검증 ... } ``` @@ -469,15 +469,15 @@ $jwt = JWT::encode($payload, $privateKey, 'RS256'); $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); ``` -> **RSA를 사용할 때**: 확인을 위해 공개 키를 배포해야 할 때 사용 (예: 마이크로서비스, 타사 통합). 단일 애플리케이션의 경우 HS256이 더 간단하고 충분합니다. +> **RSA를 사용할 때**: 검증을 위해 공개 키를 배포해야 할 때 사용 (예: 마이크로서비스, 타사 통합). 단일 애플리케이션의 경우 HS256이 더 간단하고 충분합니다. ## 문제 해결 -### "만료된 토큰" 오류 -토큰의 `exp` 클레임이 과거입니다. 새 토큰을 발급하거나 토큰 새로고침을 구현하세요. +### "Expired token" 오류 +토큰의 `exp` 클레임이 과거입니다. 새 토큰을 발급하거나 토큰 갱신을 구현하세요. -### "서명 확인 실패" -- 인코딩에 사용한 비밀 키와 다른 키로 디코딩 +### "Signature verification failed" +- 인코딩에 사용한 비밀 키와 다른 키로 디코딩 중 - 토큰이 변조됨 - 서버 간 시계 왜곡 (leeway 버퍼 추가) @@ -505,19 +505,19 @@ fetch('/api/users', { Firebase JWT 라이브러리는 다음 핵심 메서드를 제공합니다: - `JWT::encode(array $payload, string $key, string $alg)`: 페이로드에서 JWT 생성 -- `JWT::decode(string $jwt, Key $key)`: JWT 디코딩 및 확인 -- `JWT::urlsafeB64Encode(string $input)`: Base64 URL-안전 인코딩 -- `JWT::urlsafeB64Decode(string $input)`: Base64 URL-안전 디코딩 -- `JWT::$leeway`: 확인을 위한 시간 여유 설정 정적 속성 (초 단위) +- `JWT::decode(string $jwt, Key $key)`: JWT 디코딩 및 검증 +- `JWT::urlsafeB64Encode(string $input)`: Base64 URL 안전 인코딩 +- `JWT::urlsafeB64Decode(string $input)`: Base64 URL 안전 디코딩 +- `JWT::$leeway`: 검증을 위한 시간 여유 설정 (초 단위) 정적 속성 ## 이 라이브러리를 사용하는 이유는? - **산업 표준**: Firebase JWT는 PHP에서 가장 인기 있고 신뢰받는 JWT 라이브러리 -- **활성 유지보수**: Google/Firebase 팀이 유지보수 -- **보안 중심**: 정기 업데이트 및 보안 패치 +- **활성 유지보수**: Google/Firebase 팀에서 유지보수 +- **보안 중심**: 정기 업데이트와 보안 패치 - **간단한 API**: 이해하고 구현하기 쉬움 - **잘 문서화됨**: 광범위한 문서와 커뮤니티 지원 -- **유연성**: 여러 알고리즘 및 구성 가능한 옵션 지원 +- **유연함**: 여러 알고리즘과 구성 가능한 옵션 지원 ## 관련 자료 diff --git a/content/v3/ko/awesome-plugins/runway.md b/content/v3/ko/awesome-plugins/runway.md index 25bb2794..071fee97 100644 --- a/content/v3/ko/awesome-plugins/runway.md +++ b/content/v3/ko/awesome-plugins/runway.md @@ -1,18 +1,18 @@ # Runway -Runway는 Flight 애플리케이션을 관리하는 데 도움을 주는 CLI 애플리케이션입니다. 컨트롤러를 생성하고, 모든 경로를 표시하며, 그 외 더 많은 기능을 제공합니다. 이는 우수한 [adhocore/php-cli](https://github.com/adhocore/php-cli) 라이브러리를 기반으로 합니다. +Runway는 Flight 애플리케이션을 관리하는 데 도움이 되는 CLI 애플리케이션입니다. 컨트롤러를 생성하고, 모든 경로를 표시하며, 그 외 더 많은 기능을 제공합니다. 이는 우수한 [adhocore/php-cli](https://github.com/adhocore/php-cli) 라이브러리를 기반으로 합니다. -코드 보기 위해 [여기](https://github.com/flightphp/runway)를 클릭하세요. +코드 보기: [여기](https://github.com/flightphp/runway)를 클릭하세요. -## 설치 +## Installation -Composer를 사용하여 설치하세요. +composer를 사용하여 설치하세요. ```bash composer require flightphp/runway ``` -## 기본 구성 +## Basic Configuration Runway를 처음 실행할 때, `app/config/config.php`의 `'runway'` 키를 통해 `runway` 구성을 찾으려고 시도합니다. @@ -27,48 +27,48 @@ return [ ]; ``` -> **참고** - **v1.2.0**부터 `.runway-config.json`은 더 이상 사용되지 않습니다. 구성을 `app/config/config.php`로 이전하세요. `php runway config:migrate` 명령으로 쉽게 할 수 있습니다. +> **NOTE** - **v1.2.0**부터 `.runway-config.json`은 더 이상 사용되지 않습니다. 구성을 `app/config/config.php`로 마이그레이션하세요. `php runway config:migrate` 명령으로 쉽게 할 수 있습니다. -### 프로젝트 루트 감지 +### Project Root Detection -Runway는 하위 디렉토리에서 실행하더라도 프로젝트 루트를 충분히 스마트하게 감지합니다. `composer.json`, `.git`, 또는 `app/config/config.php`와 같은 지표를 찾아 프로젝트 루트가 어디인지 결정합니다. 따라서 프로젝트의 어디서든 Runway 명령을 실행할 수 있습니다! +Runway는 하위 디렉토리에서 실행하더라도 프로젝트 루트를 감지할 수 있을 만큼 똑똑합니다. `composer.json`, `.git`, 또는 `app/config/config.php`와 같은 지표를 찾아 프로젝트 루트를 결정합니다. 따라서 프로젝트의 어디서나 Runway 명령을 실행할 수 있습니다! -## 사용법 +## Usage -Runway는 Flight 애플리케이션을 관리하는 데 사용할 수 있는 여러 명령을 가지고 있습니다. Runway를 사용하는 두 가지 쉬운 방법이 있습니다. +Runway에는 Flight 애플리케이션을 관리하는 데 사용할 수 있는 여러 명령이 있습니다. Runway를 사용하는 두 가지 쉬운 방법이 있습니다. -1. 스켈레톤 프로젝트를 사용 중이라면 프로젝트 루트에서 `php runway [command]`를 실행할 수 있습니다. -1. Composer를 통해 설치된 패키지로 Runway를 사용 중이라면 프로젝트 루트에서 `vendor/bin/runway [command]`를 실행할 수 있습니다. +1. 스켈레톤 프로젝트를 사용 중이라면, 프로젝트 루트에서 `php runway [command]`를 실행할 수 있습니다. +1. composer를 통해 설치된 패키지로 Runway를 사용 중이라면, 프로젝트 루트에서 `vendor/bin/runway [command]`를 실행할 수 있습니다. -### 명령 목록 +### Command List -`php runway` 명령을 실행하여 사용 가능한 모든 명령 목록을 볼 수 있습니다. +`php runway` 명령을 실행하여 모든 사용 가능한 명령 목록을 볼 수 있습니다. ```bash php runway ``` -### 명령 도움말 +### Command Help -모든 명령에 대해 `--help` 플래그를 전달하여 명령 사용 방법에 대한 자세한 정보를 얻을 수 있습니다. +어떤 명령에 대해서든 `--help` 플래그를 전달하여 명령 사용 방법에 대한 더 많은 정보를 얻을 수 있습니다. ```bash php runway routes --help ``` -다음은 몇 가지 예입니다: +다음은 몇 가지 예시입니다: -### 컨트롤러 생성 +### Generate a Controller -`runway.app_root`의 구성에 기반하여 `app/controllers/` 디렉토리에 컨트롤러를 생성합니다. +`runway.app_root`의 구성에 따라, `app/controllers/` 디렉토리에 컨트롤러를 생성합니다. ```bash php runway make:controller MyController ``` -### Active Record 모델 생성 +### Generate an Active Record Model -먼저 [Active Record](/awesome-plugins/active-record) 플러그인이 설치되었는지 확인하세요. `runway.app_root`의 구성에 기반하여 `app/records/` 디렉토리에 레코드를 생성합니다. +먼저 [Active Record](/awesome-plugins/active-record) 플러그인을 설치했는지 확인하세요. `runway.app_root`의 구성에 따라, `app/records/` 디렉토리에 레코드를 생성합니다. ```bash php runway make:record users @@ -84,7 +84,7 @@ declare(strict_types=1); namespace app\records; /** - * users 테이블에 대한 ActiveRecord 클래스. + * ActiveRecord class for the users table. * @link https://docs.flightphp.com/awesome-plugins/active-record * * @property int $id @@ -92,20 +92,20 @@ namespace app\records; * @property string $email * @property string $created_at * @property string $updated_at - * // $relations 배열에 정의한 후 관계를 여기에 추가할 수도 있습니다 - * @property CompanyRecord $company 관계의 예 + * // you could also add relationships here once you define them in the $relations array + * @property CompanyRecord $company Example of a relationship */ class UserRecord extends \flight\ActiveRecord { /** - * @var array $relations 모델의 관계 설정 + * @var array $relations Set the relationships for the model * https://docs.flightphp.com/awesome-plugins/active-record#relationships */ protected array $relations = []; /** - * 생성자 - * @param mixed $databaseConnection 데이터베이스 연결 + * Constructor + * @param mixed $databaseConnection The connection to the database */ public function __construct($databaseConnection) { @@ -114,15 +114,15 @@ class UserRecord extends \flight\ActiveRecord } ``` -### 모든 경로 표시 +### Display All Routes -현재 Flight에 등록된 모든 경로를 표시합니다. +이것은 현재 Flight에 등록된 모든 경로를 표시합니다. ```bash php runway routes ``` -특정 경로만 보려면 플래그를 전달하여 경로를 필터링할 수 있습니다. +특정 경로만 보려면, 경로를 필터링하는 플래그를 전달할 수 있습니다. ```bash # GET 경로만 표시 @@ -134,11 +134,11 @@ php runway routes --post # 등. ``` -## Runway에 사용자 지정 명령 추가 +## Adding Custom Commands to Runway -Flight용 패키지를 생성하거나 프로젝트에 사용자 지정 명령을 추가하려면 `src/commands/`, `flight/commands/`, `app/commands/`, 또는 `commands/` 디렉토리를 프로젝트/패키지에 생성하세요. 추가 사용자 지정이 필요하다면 아래 구성 섹션을 참조하세요. +Flight용 패키지를 만들거나 프로젝트에 사용자 지정 명령을 추가하려면, 프로젝트/패키지에 `src/commands/`, `flight/commands/`, `app/commands/`, 또는 `commands/` 디렉토리를 생성하여 할 수 있습니다. 추가 사용자 지정이 필요하면 아래 구성 섹션을 참조하세요. -명령을 생성하려면 `AbstractBaseCommand` 클래스를 확장하고 최소한 `__construct` 메서드와 `execute` 메서드를 구현하세요. +명령을 생성하려면 `AbstractBaseCommand` 클래스를 확장하고, 최소한 `__construct` 메서드와 `execute` 메서드를 구현하세요. ```php $config app/config/config.php의 구성 + * @param array $config Config from app/config/config.php */ public function __construct(array $config) { - parent::__construct('make:example', '문서화를 위한 예제 생성', $config); - $this->argument('', '재미있는 GIF의 이름'); + parent::__construct('make:example', 'Create an example for the documentation', $config); + $this->argument('', 'The name of the funny gif'); } /** - * 함수 실행 + * Executes the function * * @return void */ @@ -169,30 +169,30 @@ class ExampleCommand extends AbstractBaseCommand { $io = $this->app()->io(); - $io->info('예제 생성 중...'); + $io->info('Creating example...'); - // 여기에 무언가 수행 + // Do something here - $io->ok('예제 생성됨!'); + $io->ok('Example created!'); } } ``` -Flight 애플리케이션에 사용자 지정 명령을 구축하는 방법에 대한 자세한 정보는 [adhocore/php-cli 문서](https://github.com/adhocore/php-cli)를 참조하세요! +Flight 애플리케이션에 사용자 지정 명령을 구축하는 방법에 대한 자세한 정보는 [adhocore/php-cli Documentation](https://github.com/adhocore/php-cli)을 참조하세요! -## 구성 관리 +## Configuration Management -`v1.2.0`부터 구성이 `app/config/config.php`로 이동되었으므로 구성 관리를 위한 몇 가지 도우미 명령이 있습니다. +`v1.2.0`부터 구성이 `app/config/config.php`로 이동되었으므로, 구성을 관리하는 몇 가지 도우미 명령이 있습니다. -### 이전 구성 이전 +### Migrate Old Config -이전 `.runway-config.json` 파일이 있다면 다음 명령으로 `app/config/config.php`로 쉽게 이전할 수 있습니다: +이전 `.runway-config.json` 파일이 있다면, 다음 명령으로 `app/config/config.php`로 쉽게 마이그레이션할 수 있습니다: ```bash php runway config:migrate ``` -### 구성 값 설정 +### Set Configuration Value `config:set` 명령을 사용하여 구성 값을 설정할 수 있습니다. 파일을 열지 않고 구성 값을 업데이트하려는 경우 유용합니다. @@ -200,7 +200,7 @@ php runway config:migrate php runway config:set app_root "app/" ``` -### 구성 값 가져오기 +### Get Configuration Value `config:get` 명령을 사용하여 구성 값을 가져올 수 있습니다. @@ -208,41 +208,41 @@ php runway config:set app_root "app/" php runway config:get app_root ``` -## 모든 Runway 구성 +## All Runway Configurations -Runway 구성을 사용자 지정해야 한다면 `app/config/config.php`에 이러한 값을 설정할 수 있습니다. 아래는 설정할 수 있는 추가 구성입니다: +Runway 구성을 사용자 지정해야 한다면, `app/config/config.php`에 이러한 값을 설정할 수 있습니다. 아래는 설정할 수 있는 몇 가지 추가 구성입니다: ```php [ - // 애플리케이션 디렉토리가 위치한 곳 + // This is where your application directory is located 'app_root' => 'app/', - // 루트 인덱스 파일이 위치한 디렉토리 + // This is the directory where your root index file is located 'index_root' => 'public/', - // 다른 프로젝트의 루트 경로들 + // These are the paths to the roots of other projects 'root_paths' => [ '/home/user/different-project', '/var/www/another-project' ], - // 기본 경로는 구성할 필요가 거의 없지만, 필요하다면 여기에 있습니다 + // Base paths most likely don't need to be configured, but it's here if you want it 'base_paths' => [ - '/includes/libs/vendor', // 벤더 디렉토리 등에 정말 독특한 경로가 있는 경우 + '/includes/libs/vendor', // if you have a really unique path for your vendor directory or something ], - // 최종 경로는 프로젝트 내 명령 파일을 검색할 위치 + // Final paths are locations within a project to search for the command files 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // 전체 경로를 추가하려면 (프로젝트 루트에 대한 절대 또는 상대 경로) + // If you want to just add the full path, go right ahead (absolute or relative to project root) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -252,35 +252,35 @@ return [ ]; ``` -### 구성 접근 +### Accessing Configuration -구성 값을 효과적으로 접근해야 한다면 `__construct` 메서드나 `app()` 메서드를 통해 접근할 수 있습니다. 또한 `app/config/services.php` 파일이 있는 경우 해당 서비스도 명령에 사용할 수 있습니다. +구성 값을 효과적으로 액세스해야 한다면, `__construct` 메서드나 `app()` 메서드를 통해 액세스할 수 있습니다. 또한 `app/config/services.php` 파일이 있는 경우, 해당 서비스도 명령에서 사용할 수 있습니다. ```php public function execute() { $io = $this->app()->io(); - // 구성 접근 + // Access configuration $app_root = $this->config['runway']['app_root']; - // 데이터베이스 연결 같은 서비스 접근 + // Access services like maybe a database connection $database = $this->config['database'] // ... } ``` -## AI 도우미 래퍼 +## AI Helper Wrappers -Runway에는 AI가 명령을 생성하기 쉽게 하는 몇 가지 도우미 래퍼가 있습니다. Symfony Console과 유사하게 `addOption`과 `addArgument`를 사용할 수 있습니다. AI 도구를 사용하여 명령을 생성할 때 유용합니다. +Runway에는 AI가 명령을 생성하기 쉽게 하는 몇 가지 도우미 래퍼가 있습니다. Symfony Console과 유사하게 `addOption`과 `addArgument`를 사용할 수 있습니다. AI 도구를 사용하여 명령을 생성하는 경우 유용합니다. ```php public function __construct(array $config) { - parent::__construct('make:example', '문서화를 위한 예제 생성', $config); + parent::__construct('make:example', 'Create an example for the documentation', $config); - // name 옵션은 null이고 완전히 선택적입니다 - $this->addOption('name', '예제의 이름', null); + // The mode argument is nullable and defaults to completely optional + $this->addOption('name', 'The name of the example', null); } ``` \ No newline at end of file diff --git a/content/v3/ko/learn/autoloading.md b/content/v3/ko/learn/autoloading.md index a36452c0..c18fbcc8 100644 --- a/content/v3/ko/learn/autoloading.md +++ b/content/v3/ko/learn/autoloading.md @@ -1,18 +1,18 @@ -# 자동 로딩 +# Autoloading ## 개요 -자동 로딩은 PHP에서 클래스들을 로드하기 위해 디렉토리 또는 디렉토리들을 지정하는 개념입니다. 이는 `require`나 `include`를 사용하여 클래스들을 로드하는 것보다 훨씬 더 유익합니다. 또한 Composer 패키지를 사용하는 데 필수적입니다. +Autoloading은 PHP에서 클래스들을 로드할 디렉토리 또는 디렉토리들을 지정하는 개념입니다. 이는 `require`나 `include`를 사용하여 클래스들을 로드하는 것보다 훨씬 유익합니다. 또한 Composer 패키지를 사용하는 데 필수적입니다. ## 이해 -기본적으로 모든 `Flight` 클래스는 Composer 덕분에 자동으로 자동 로딩됩니다. 그러나 자신의 클래스들을 자동 로딩하려면 `Flight::path()` 메서드를 사용하여 클래스들을 로드할 디렉토리를 지정할 수 있습니다. +기본적으로 `Flight`의 모든 클래스는 Composer 덕분에 자동으로 autoload됩니다. 그러나 자신의 클래스들을 autoload하려면 `Flight::path()` 메서드를 사용하여 클래스들을 로드할 디렉토리를 지정할 수 있습니다. -자동 로더를 사용하면 코드를 상당히 단순화할 수 있습니다. 파일 상단에 사용되는 모든 클래스들을 캡처하기 위해 수많은 `include`나 `require` 문으로 시작하는 대신, 클래스들을 동적으로 호출하면 자동으로 포함됩니다. +Autoloader를 사용하면 코드를 상당히 단순화할 수 있습니다. 파일 상단에 사용되는 모든 클래스들을 캡처하기 위해 수많은 `include`나 `require` 문으로 시작하는 대신, 클래스들을 동적으로 호출하면 자동으로 포함됩니다. ## 기본 사용법 -다음과 같은 디렉토리 트리를 가지고 있다고 가정해 보겠습니다: +다음과 같은 디렉토리 트리가 있다고 가정해 보겠습니다: ```text # 예시 경로 @@ -30,9 +30,9 @@ └── index.php ``` -이것이 이 문서 사이트의 파일 구조와 동일하다는 것을 눈치챘을 수 있습니다. +이것이 이 문서 사이트의 파일 구조와 동일하다는 것을 눈치채셨을 수 있습니다. -각 디렉토리를 다음과 같이 로드할 수 있도록 지정할 수 있습니다: +각 디렉토리를 다음과 같이 지정하여 로드할 수 있습니다: ```php @@ -40,7 +40,7 @@ * public/index.php */ -// 자동 로더에 경로 추가 +// Autoloader에 경로 추가 Flight::path(__DIR__.'/../app/controllers/'); Flight::path(__DIR__.'/../app/utils/'); @@ -51,7 +51,7 @@ Flight::path(__DIR__.'/../app/utils/'); // 네임스페이싱 불필요 -// 모든 자동 로딩된 클래스들은 Pascal Case(각 단어 대문자, 공백 없음)로 하는 것을 권장 +// 모든 autoload된 클래스들은 Pascal Case(각 단어의 첫 글자 대문자, 공백 없음)로 하는 것을 권장 class MyController { public function index() { @@ -62,7 +62,7 @@ class MyController { ## 네임스페이스 -네임스페이스를 사용한다면 이를 구현하는 것이 매우 쉬워집니다. `Flight::path()` 메서드를 사용하여 애플리케이션의 루트 디렉토리(문서 루트나 `public/` 폴더가 아님)를 지정해야 합니다. +네임스페이스가 있는 경우, 이를 구현하는 것이 매우 쉽습니다. `Flight::path()` 메서드를 사용하여 애플리케이션의 루트 디렉토리(문서 루트나 `public/` 폴더가 아님)를 지정해야 합니다. ```php @@ -70,11 +70,11 @@ class MyController { * public/index.php */ -// 자동 로더에 경로 추가 +// Autoloader에 경로 추가 Flight::path(__DIR__.'/../'); ``` -이제 컨트롤러가 어떻게 보일지 예시를 보세요. 아래 예시를 보지만 중요한 정보에 대한 주석에 주의하세요. +이제 컨트롤러가 어떻게 보일지 확인해 보세요. 아래 예시를 보시되, 중요한 정보가 있는 주석에 주의하세요. ```php /** @@ -84,11 +84,11 @@ Flight::path(__DIR__.'/../'); // 네임스페이스 필수 // 네임스페이스는 디렉토리 구조와 동일 // 네임스페이스는 디렉토리 구조와 동일한 대소문자를 따라야 함 -// 네임스페이스와 디렉토리는 밑줄을 가질 수 없음 (Loader::setV2ClassLoading(false)가 설정되지 않은 한) +// 네임스페이스와 디렉토리는 언더스코어를 가질 수 없음 (Loader::setV2ClassLoading(false)가 설정되지 않은 한) namespace app\controllers; -// 모든 자동 로딩된 클래스들은 Pascal Case(각 단어 대문자, 공백 없음)로 하는 것을 권장 -// 3.7.2부터 Loader::setV2ClassLoading(false)를 실행하여 클래스 이름에 Pascal_Snake_Case를 사용할 수 있음 +// 모든 autoload된 클래스들은 Pascal Case(각 단어의 첫 글자 대문자, 공백 없음)로 하는 것을 권장 +// 3.7.2 버전부터 Loader::setV2ClassLoading(false)를 실행하여 클래스 이름에 Pascal_Snake_Case를 사용할 수 있음 class MyController { public function index() { @@ -97,7 +97,7 @@ class MyController { } ``` -utils 디렉토리의 클래스를 자동 로딩하려면 기본적으로 동일한 작업을 합니다: +utils 디렉토리의 클래스를 autoload하려면 기본적으로 동일한 작업을 수행합니다: ```php @@ -105,7 +105,7 @@ utils 디렉토리의 클래스를 자동 로딩하려면 기본적으로 동일 * app/UTILS/ArrayHelperUtil.php */ -// 네임스페이스는 디렉토리 구조와 대소문자를 일치시켜야 함 (위 파일 트리의 UTILS 디렉토리가 대문자임을 주의 +// 네임스페이스는 디렉토리 구조와 대소문자를 일치시켜야 함 (위 파일 트리에서 UTILS 디렉토리가 대문자임을 유의 // 위 파일 트리와 같이) namespace app\UTILS; @@ -117,11 +117,11 @@ class ArrayHelperUtil { } ``` -## 클래스 이름의 밑줄 +## 클래스 이름의 언더스코어 -3.7.2부터 `Loader::setV2ClassLoading(false);`를 실행하여 클래스 이름에 Pascal_Snake_Case를 사용할 수 있습니다. -이는 클래스 이름에 밑줄을 허용합니다. -권장되지 않지만 필요로 하는 사람들을 위해 제공됩니다. +3.7.2 버전부터 `Loader::setV2ClassLoading(false);`를 실행하여 클래스 이름에 Pascal_Snake_Case를 사용할 수 있습니다. +이렇게 하면 클래스 이름에 언더스코어를 사용할 수 있습니다. +이는 권장되지 않지만, 필요로 하는 사람들을 위해 제공됩니다. ```php use flight\core\Loader; @@ -130,7 +130,7 @@ use flight\core\Loader; * public/index.php */ -// 자동 로더에 경로 추가 +// Autoloader에 경로 추가 Flight::path(__DIR__.'/../app/controllers/'); Flight::path(__DIR__.'/../app/utils/'); Loader::setV2ClassLoading(false); @@ -149,29 +149,29 @@ class My_Controller { } ``` -## 관련 항목 -- [라우팅](/learn/routing) - 라우트를 컨트롤러에 매핑하고 뷰를 렌더링하는 방법. -- [왜 프레임워크인가?](/learn/why-frameworks) - Flight 같은 프레임워크를 사용하는 이점 이해. +## 관련 자료 +- [Routing](/learn/routing) - 라우트를 컨트롤러에 매핑하고 뷰를 렌더링하는 방법. +- [Why a Framework?](/learn/why-frameworks) - Flight와 같은 프레임워크를 사용하는 이점 이해. ## 문제 해결 -- 네임스페이스된 클래스들이 발견되지 않는 이유를 파악하지 못한다면, 프로젝트의 루트 디렉토리에 `Flight::path()`를 사용해야 하며, `app/`나 `src/` 디렉토리나 이에 상응하는 것이 아님을 기억하세요. +- 네임스페이스가 있는 클래스들이 발견되지 않는 이유를 파악할 수 없다면, 프로젝트의 루트 디렉토리에 `Flight::path()`를 사용해야 하며, `app/`나 `src/` 디렉토리나 이에 상응하는 것을 사용하지 말아야 한다는 점을 기억하세요. -### 클래스 발견되지 않음 (자동 로딩 작동 안 함) +### 클래스 발견되지 않음 (autoloading 작동 안 함) -이 문제가 발생하지 않는 몇 가지 이유가 있을 수 있습니다. 아래에 몇 가지 예시가 있지만 [자동 로딩](/learn/autoloading) 섹션도 확인하세요. +이 문제가 발생하는 이유는 몇 가지가 있을 수 있습니다. 아래에 몇 가지 예시를 들었지만, [autoloading](/learn/autoloading) 섹션도 확인하세요. #### 잘못된 파일 이름 -가장 흔한 것은 클래스 이름이 파일 이름과 일치하지 않는 것입니다. +가장 흔한 이유는 클래스 이름이 파일 이름과 일치하지 않는 것입니다. -`MyClass`라는 이름의 클래스가 있다면 파일은 `MyClass.php`로 명명되어야 합니다. `MyClass`라는 클래스 이름과 `myclass.php`라는 파일 이름이라면 자동 로더가 이를 찾을 수 없습니다. +`MyClass`라는 이름의 클래스가 있다면 파일 이름은 `MyClass.php`여야 합니다. `MyClass`라는 클래스 이름과 `myclass.php`라는 파일 이름이라면 autoloader가 이를 찾을 수 없습니다. #### 잘못된 네임스페이스 -네임스페이스를 사용한다면 네임스페이스가 디렉토리 구조와 일치해야 합니다. +네임스페이스를 사용하는 경우, 네임스페이스가 디렉토리 구조와 일치해야 합니다. ```php // ...코드... -// MyController가 app/controllers 디렉토리에 있고 네임스페이스된 경우 +// MyController가 app/controllers 디렉토리에 있고 네임스페이스가 있는 경우 // 이는 작동하지 않습니다. Flight::route('/hello', 'MyController->hello'); @@ -190,14 +190,13 @@ Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); #### `path()` 정의되지 않음 -스켈레톤 앱에서 이는 `config.php` 파일 내부에 정의되어 있지만, 클래스들이 발견되도록 하려면 `path()` -메서드가 정의되어 있는지 확인해야 합니다 (아마도 디렉토리의 루트로). +스켈레톤 앱에서는 `config.php` 파일 내부에 정의되어 있지만, 클래스들이 발견되도록 하려면 `path()` 메서드가 정의되어 있어야 합니다(아마도 디렉토리의 루트로). 사용 전에 이를 확인하세요. ```php -// 자동 로더에 경로 추가 +// Autoloader에 경로 추가 Flight::path(__DIR__.'/../'); ``` ## 변경 로그 - v3.7.2 - `Loader::setV2ClassLoading(false);`를 실행하여 클래스 이름에 Pascal_Snake_Case 사용 가능 -- v2.0 - 자동 로딩 기능 추가. \ No newline at end of file +- v2.0 - Autoload 기능 추가. \ No newline at end of file diff --git a/content/v3/ko/learn/learn.md b/content/v3/ko/learn/learn.md index 3e3137ab..e1844363 100644 --- a/content/v3/ko/learn/learn.md +++ b/content/v3/ko/learn/learn.md @@ -1,9 +1,9 @@ -# Flight에 대해 알아보세요 +# Flight에 대해 알아보기 -Flight는 PHP를 위한 빠르고 간단하며 확장 가능한 프레임워크입니다. 매우 다재다능하며 모든 종류의 웹 애플리케이션을 구축하는 데 사용할 수 있습니다. +Flight는 PHP를 위한 빠르고 간단하며 확장 가능한 프레임워크입니다. 매우 다재다능하며 모든 종류의 웹 애플리케이션을 구축하는 데 사용할 수 있습니다. 단순성을 염두에 두고 구축되었으며 이해하고 사용하기 쉬운 방식으로 작성되었습니다. -> **참고:** `Flight::`를 정적 변수로 사용하는 예제와 `$app->` Engine 객체를 사용하는 예제를 볼 수 있습니다. 둘 다 서로 호환되며 작동합니다. 컨트롤러/미들웨어에서 `$app`과 `$this->app`은 Flight 팀에서 권장하는 접근 방식입니다. +> **참고:** `Flight::`를 정적 변수로 사용하는 예제와 `$app->` Engine 객체를 사용하는 예제를 볼 수 있습니다. 둘 다 서로 호환되며 작동합니다. 컨트롤러/미들웨어에서 `$app` 및 `$this->app`은 Flight 팀에서 권장하는 접근 방식입니다. ## 핵심 구성 요소 @@ -37,7 +37,7 @@ Flight는 PHP를 위한 빠르고 간단하며 확장 가능한 프레임워크 ### [구성](/learn/configuration) -애플리케이션을 위해 프레임워크를 구성하는 방법을 알아보세요. +애플리케이션에 맞게 프레임워크를 구성하는 방법을 알아보세요. ### [이벤트 관리자](/learn/events) @@ -53,7 +53,7 @@ Flight는 PHP를 위한 빠르고 간단하며 확장 가능한 프레임워크 ### [의존성 주입 컨테이너 (DIC)](/learn/dependency-injection-container) -의존성 주입 컨테이너(DIC)를 사용하여 애플리케이션의 의존성을 관리하는 방법을 알아보세요. +의존성 주입 컨테이너 (DIC)를 사용하여 애플리케이션의 의존성을 관리하는 방법을 알아보세요. ## 유틸리티 클래스 @@ -63,11 +63,15 @@ Flight는 PHP를 위한 빠르고 간단하며 확장 가능한 프레임워크 ### [JSON 래퍼](/learn/json) -JSON 인코딩과 디코딩을 일관되게 만들기 위한 몇 가지 간단한 함수가 있습니다. +JSON 인코딩 및 디코딩을 일관되게 만들기 위한 간단한 함수 몇 가지가 있습니다. -### [PDO 래퍼](/learn/pdo-wrapper) +### [SimplePdo](/learn/simple-pdo) -PDO는 때때로 불필요한 골칫거리를 초래할 수 있습니다. 이 간단한 래퍼 클래스는 데이터베이스와 상호 작용을 훨씬 쉽게 만들어줍니다. +PDO는 때때로 불필요한 골칫거리를 더할 수 있습니다. SimplePdo는 `insert()`, `update()`, `delete()`, `transaction()` 같은 편리한 메서드를 가진 현대적인 PDO 도우미 클래스입니다. 데이터베이스 작업을 훨씬 쉽게 만듭니다. + +### [PdoWrapper](/learn/pdo-wrapper) (사용 중단됨) + +원래 PDO 래퍼는 v3.18.0부터 사용 중단되었습니다. 대신 [SimplePdo](/learn/simple-pdo)를 사용하세요. ### [업로드된 파일 핸들러](/learn/uploaded-file) @@ -79,13 +83,13 @@ PDO는 때때로 불필요한 골칫거리를 초래할 수 있습니다. 이 프레임워크를 사용하는 이유에 대한 짧은 기사입니다. 프레임워크를 사용하기 전에 그 이점을 이해하는 것이 좋습니다. -또한 [@lubiana](https://git.php.fail/lubiana)에 의해 훌륭한 튜토리얼이 만들어졌습니다. Flight에 대해 구체적으로 자세히 다루지는 않지만, -이 가이드는 프레임워크를 둘러싼 주요 개념과 사용 이유에 대한 이해를 돕습니다. +추가로 [@lubiana](https://git.php.fail/lubiana)에 의해 훌륭한 튜토리얼이 만들어졌습니다. Flight에 대해 구체적으로 자세히 다루지는 않지만, +이 가이드는 프레임워크를 둘러싼 주요 개념과 그 이점을 이해하는 데 도움이 될 것입니다. 튜토리얼은 [여기](https://git.php.fail/lubiana/no-framework-tutorial/src/branch/master/README.md)에서 찾을 수 있습니다. ### [Flight와 다른 프레임워크 비교](/learn/flight-vs-another-framework) -Laravel, Slim, Fat-Free 또는 Symfony와 같은 다른 프레임워크에서 Flight로 이전하는 경우, 이 페이지가 두 프레임워크 간의 차이점을 이해하는 데 도움이 됩니다. +Laravel, Slim, Fat-Free 또는 Symfony 같은 다른 프레임워크에서 Flight로 마이그레이션 중이라면, 이 페이지가 두 프레임워크 간의 차이점을 이해하는 데 도움이 될 것입니다. ## 기타 주제 @@ -95,8 +99,8 @@ Flight 코드를 견고하게 단위 테스트하는 방법을 배우기 위해 ### [AI & 개발자 경험](/learn/ai) -Flight가 AI 도구와 현대 개발 워크플로와 함께 작동하여 더 빠르고 스마트하게 코딩하는 방법을 알아보세요. +Flight가 AI 도구와 현대적인 개발 워크플로와 함께 작동하여 더 빠르고 스마트하게 코딩하는 방법을 알아보세요. -### [v2 -> v3 이전](/learn/migrating-to-v3) +### [v2 -> v3 마이그레이션](/learn/migrating-to-v3) -하위 호환성이 대부분 유지되었지만, v2에서 v3로 이전할 때 알아야 할 몇 가지 변경 사항이 있습니다. \ No newline at end of file +하위 호환성이 대부분 유지되었지만, v2에서 v3로 마이그레이션할 때 알아야 할 몇 가지 변경 사항이 있습니다. \ No newline at end of file diff --git a/content/v3/ko/learn/pdo_wrapper.md b/content/v3/ko/learn/pdo_wrapper.md index 7a73d2e6..af6bfda9 100644 --- a/content/v3/ko/learn/pdo_wrapper.md +++ b/content/v3/ko/learn/pdo_wrapper.md @@ -1,20 +1,24 @@ # PdoWrapper PDO 도우미 클래스 +> **경고** +> +> **사용 중단됨:** `PdoWrapper`는 Flight v3.18.0부터 사용 중단되었습니다. 향후 버전에서 제거되지 않지만, 이전 호환성을 위해 유지될 것입니다. 동일한 기능에 더해 일반적인 데이터베이스 작업을 위한 추가 도우미 메서드를 제공하는 [SimplePdo](/learn/simple-pdo)를 대신 사용하십시오. + ## 개요 -Flight의 `PdoWrapper` 클래스는 PDO를 사용하여 데이터베이스 작업을 수행하는 데 친근한 도우미입니다. 일반적인 데이터베이스 작업을 간소화하고, 결과를 가져오는 데 유용한 메서드를 추가하며, 결과를 쉽게 접근할 수 있도록 [Collections](/learn/collections)로 반환합니다. 또한 고급 사용 사례를 위해 쿼리 로깅과 애플리케이션 성능 모니터링(APM)을 지원합니다. +Flight의 `PdoWrapper` 클래스는 PDO를 사용하여 데이터베이스 작업을 수행하는 데 친근한 도우미입니다. 일반적인 데이터베이스 작업을 간소화하고, 결과를 가져오는 데 유용한 메서드를 추가하며, 결과를 [Collections](/learn/collections)으로 반환하여 쉽게 접근할 수 있습니다. 또한 쿼리 로깅과 애플리케이션 성능 모니터링(APM)을 지원하여 고급 사용 사례를 처리합니다. ## 이해하기 -PHP에서 데이터베이스를 사용하는 것은 PDO를 직접 사용할 때 특히 장황할 수 있습니다. `PdoWrapper`는 PDO를 확장하여 쿼리, 가져오기, 결과 처리 작업을 훨씬 쉽게 만드는 메서드를 추가합니다. 준비된 문장과 가져오기 모드를 다루는 대신, 일반적인 작업에 대한 간단한 메서드를 사용하며, 모든 행이 Collection으로 반환되므로 배열 또는 객체 표기법을 사용할 수 있습니다. +PHP에서 PDO를 직접 사용하면 데이터베이스 작업이 다소 장황할 수 있습니다. `PdoWrapper`는 PDO를 확장하여 쿼리, 결과 가져오기, 결과 처리 작업을 훨씬 쉽게 만드는 메서드를 추가합니다. 준비된 문장과 가져오기 모드를 다루는 대신 일반적인 작업을 위한 간단한 메서드를 얻고, 모든 행이 Collection으로 반환되므로 배열 또는 객체 표기법을 사용할 수 있습니다. -Flight에서 `PdoWrapper`를 공유 서비스로 등록한 후, 앱의 어디서나 `Flight::db()`를 통해 사용할 수 있습니다. +`PdoWrapper`를 Flight에서 공유 서비스로 등록할 수 있으며, 그 후 앱의 어디서나 `Flight::db()`를 통해 사용할 수 있습니다. ## 기본 사용법 -### PDO 도우미 등록 +### PDO 도우미 등록하기 -먼저 Flight에 `PdoWrapper` 클래스를 등록합니다: +먼저 Flight에 `PdoWrapper` 클래스를 등록하십시오: ```php Flight::register('db', \flight\database\PdoWrapper::class, [ @@ -27,15 +31,15 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ ]); ``` -이제 어디서나 `Flight::db()`를 사용하여 데이터베이스 연결을 가져올 수 있습니다. +이제 어디서나 `Flight::db()`를 사용하여 데이터베이스 연결을 얻을 수 있습니다. -### 쿼리 실행 +### 쿼리 실행하기 #### `runQuery()` `function runQuery(string $sql, array $params = []): PDOStatement` -INSERT, UPDATE 또는 결과를 수동으로 가져오고 싶을 때 사용합니다: +INSERT, UPDATE 또는 결과를 수동으로 가져오고 싶을 때 사용하십시오: ```php $db = Flight::db(); @@ -66,7 +70,7 @@ $count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", `function fetchRow(string $sql, array $params = []): Collection` -단일 행을 Collection(배열/객체 접근)으로 가져옵니다: +Collection(배열/객체 접근)으로 단일 행을 가져옵니다: ```php $user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); @@ -90,7 +94,7 @@ foreach ($users as $user) { } ``` -### `IN()` 플레이스홀더 사용 +### `IN()` 플레이스홀더 사용하기 `IN()` 절에서 단일 `?`를 사용하고 배열 또는 쉼표로 구분된 문자열을 전달할 수 있습니다: @@ -105,11 +109,11 @@ $users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", ['1,2,3'] ### 쿼리 로깅 & APM -쿼리 성능을 추적하려면 등록 시 APM 추적을 활성화합니다: +쿼리 성능을 추적하려면 등록 시 APM 추적을 활성화하십시오: ```php Flight::register('db', \flight\database\PdoWrapper::class, [ - 'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [/* 옵션 */], true // 마지막 매개변수가 APM을 활성화합니다 + 'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [/* options */], true // 마지막 매개변수가 APM을 활성화합니다 ]); ``` @@ -119,7 +123,7 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ Flight::db()->logQueries(); ``` -이것은 연결 및 쿼리 메트릭과 함께 이벤트(`flight.db.queries`)를 발생시키며, Flight의 이벤트 시스템을 사용하여 이를 수신할 수 있습니다. +이것은 연결 및 쿼리 메트릭스가 포함된 이벤트(`flight.db.queries`)를 발생시키며, Flight의 이벤트 시스템을 사용하여 이를 수신할 수 있습니다. ### 전체 예제 @@ -160,15 +164,15 @@ Flight::route('/users', function () { }); ``` -## 관련 항목 +## 관련 자료 -- [Collections](/learn/collections) - 쉬운 데이터 접근을 위한 Collection 클래스 사용법을 알아보세요. +- [Collections](/learn/collections) - 쉬운 데이터 접근을 위한 Collection 클래스 사용법을 알아보십시오. ## 문제 해결 -- 데이터베이스 연결 오류가 발생하면 DSN, 사용자 이름, 비밀번호 및 옵션을 확인하세요. -- 모든 행은 Collection으로 반환됩니다. 일반 배열이 필요하면 `$collection->getData()`를 사용하세요. -- `IN (?)` 쿼리의 경우 배열 또는 쉼표로 구분된 문자열을 전달했는지 확인하세요. +- 데이터베이스 연결 오류가 발생하면 DSN, 사용자 이름, 비밀번호 및 옵션을 확인하십시오. +- 모든 행은 Collection으로 반환됩니다—일반 배열이 필요하면 `$collection->getData()`를 사용하십시오. +- `IN (?)` 쿼리의 경우 배열 또는 쉼표로 구분된 문자열을 전달했는지 확인하십시오. ## 변경 로그 diff --git a/content/v3/ko/learn/simple_pdo.md b/content/v3/ko/learn/simple_pdo.md new file mode 100644 index 00000000..2269213b --- /dev/null +++ b/content/v3/ko/learn/simple_pdo.md @@ -0,0 +1,320 @@ +# SimplePdo PDO 헬퍼 클래스 + +## 개요 + +Flight의 `SimplePdo` 클래스는 PDO를 사용하여 데이터베이스 작업을 수행하기 위한 현대적이고 기능이 풍부한 헬퍼입니다. 이는 `PdoWrapper`를 확장하며, `insert()`, `update()`, `delete()` 및 트랜잭션과 같은 일반적인 데이터베이스 작업을 위한 편리한 헬퍼 메서드를 추가합니다. 데이터베이스 작업을 단순화하고, 결과를 쉽게 접근할 수 있도록 [Collections](/learn/collections)로 반환하며, 고급 사용 사례를 위해 쿼리 로깅과 애플리케이션 성능 모니터링(APM)을 지원합니다. + +## 이해 + +`SimplePdo` 클래스는 PHP에서 데이터베이스 작업을 훨씬 쉽게 만들도록 설계되었습니다. 준비된 문장, 가져오기 모드 및 장황한 SQL 작업을 다루는 대신, 일반적인 작업을 위한 깨끗하고 간단한 메서드를 얻을 수 있습니다. 모든 행은 Collection으로 반환되므로 배열 표기법(`$row['name']`)과 객체 표기법(`$row->name`)을 모두 사용할 수 있습니다. + +이 클래스는 `PdoWrapper`의 상위 집합으로, `PdoWrapper`의 모든 기능을 포함하며 코드가 더 깨끗하고 유지보수하기 쉽게 만드는 추가 헬퍼 메서드를 제공합니다. 현재 `PdoWrapper`를 사용 중이라면 `SimplePdo`로 업그레이드하는 것이 간단합니다. 왜냐하면 이는 `PdoWrapper`를 확장하기 때문입니다. + +Flight에서 `SimplePdo`를 공유 서비스로 등록할 수 있으며, 앱의 어디서나 `Flight::db()`를 통해 사용할 수 있습니다. + +## 기본 사용법 + +### SimplePdo 등록 + +먼저 Flight에 `SimplePdo` 클래스를 등록합니다: + +```php +Flight::register('db', \flight\database\SimplePdo::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 + ] +]); +``` + +> **노트** +> +> `PDO::ATTR_DEFAULT_FETCH_MODE`를 지정하지 않으면 `SimplePdo`가 자동으로 `PDO::FETCH_ASSOC`로 설정합니다. + +이제 어디서나 `Flight::db()`를 사용하여 데이터베이스 연결을 얻을 수 있습니다. + +### 쿼리 실행 + +#### `runQuery()` + +`function runQuery(string $sql, array $params = []): PDOStatement` + +INSERT, UPDATE 또는 결과를 수동으로 가져오고 싶을 때 사용합니다: + +```php +$db = Flight::db(); +$statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']); +while ($row = $statement->fetch()) { + // $row는 배열입니다 +} +``` + +쓰기 작업에도 사용할 수 있습니다: + +```php +$db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); +$db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]); +``` + +#### `fetchField()` + +`function fetchField(string $sql, array $params = []): mixed` + +데이터베이스에서 단일 값을 가져옵니다: + +```php +$count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']); +``` + +#### `fetchRow()` + +`function fetchRow(string $sql, array $params = []): ?Collection` + +단일 행을 Collection(배열/객체 접근)으로 가져옵니다: + +```php +$user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); +echo $user['name']; +// 또는 +echo $user->name; +``` + +> **팁** +> +> `SimplePdo`는 `fetchRow()` 쿼리에 `LIMIT 1`이 이미 없으면 자동으로 추가하여 쿼리를 더 효율적으로 만듭니다. + +#### `fetchAll()` + +`function fetchAll(string $sql, array $params = []): array` + +모든 행을 Collection 배열로 가져옵니다: + +```php +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); +foreach ($users as $user) { + echo $user['name']; + // 또는 + echo $user->name; +} +``` + +#### `fetchColumn()` + +`function fetchColumn(string $sql, array $params = []): array` + +단일 열을 배열로 가져옵니다: + +```php +$ids = Flight::db()->fetchColumn("SELECT id FROM users WHERE active = ?", [1]); +// 반환: [1, 2, 3, 4, 5] +``` + +#### `fetchPairs()` + +`function fetchPairs(string $sql, array $params = []): array` + +결과를 키-값 쌍(첫 번째 열을 키로, 두 번째를 값으로)으로 가져옵니다: + +```php +$userNames = Flight::db()->fetchPairs("SELECT id, name FROM users"); +// 반환: [1 => 'John', 2 => 'Jane', 3 => 'Bob'] +``` + +### `IN()` 플레이스홀더 사용 + +`IN()` 절에서 단일 `?`를 사용하고 배열을 전달할 수 있습니다: + +```php +$ids = [1, 2, 3]; +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); +``` + +## 헬퍼 메서드 + +`SimplePdo`의 `PdoWrapper`에 대한 주요 장점 중 하나는 일반적인 데이터베이스 작업을 위한 편리한 헬퍼 메서드의 추가입니다. + +### `insert()` + +`function insert(string $table, array $data): string` + +하나 이상의 행을 삽입하고 마지막 삽입 ID를 반환합니다. + +**단일 삽입:** + +```php +$id = Flight::db()->insert('users', [ + 'name' => 'John', + 'email' => 'john@example.com' +]); +``` + +**대량 삽입:** + +```php +$id = Flight::db()->insert('users', [ + ['name' => 'John', 'email' => 'john@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'], +]); +``` + +### `update()` + +`function update(string $table, array $data, string $where, array $whereParams = []): int` + +행을 업데이트하고 영향을 받은 행 수를 반환합니다: + +```php +$affected = Flight::db()->update( + 'users', + ['name' => 'Jane', 'email' => 'jane@example.com'], + 'id = ?', + [1] +); +``` + +> **노트** +> +> SQLite의 `rowCount()`는 데이터가 실제로 변경된 행 수를 반환합니다. 이미 동일한 값으로 행을 업데이트하면 `rowCount()`가 0을 반환합니다. 이는 `PDO::MYSQL_ATTR_FOUND_ROWS`를 사용할 때 MySQL의 동작과 다릅니다. + +### `delete()` + +`function delete(string $table, string $where, array $whereParams = []): int` + +행을 삭제하고 삭제된 행 수를 반환합니다: + +```php +$deleted = Flight::db()->delete('users', 'id = ?', [1]); +``` + +### `transaction()` + +`function transaction(callable $callback): mixed` + +트랜잭션 내에서 콜백을 실행합니다. 트랜잭션은 성공 시 자동 커밋되거나 오류 시 롤백됩니다: + +```php +$result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John']); + $db->insert('logs', ['action' => 'user_created']); + return $db->lastInsertId(); +}); +``` + +콜백 내에서 예외가 발생하면 트랜잭션이 자동으로 롤백되고 예외가 다시 발생합니다. + +## 고급 사용법 + +### 쿼리 로깅 & APM + +쿼리 성능을 추적하려면 등록 시 APM 추적을 활성화합니다: + +```php +Flight::register('db', \flight\database\SimplePdo::class, [ + 'mysql:host=localhost;dbname=cool_db_name', + 'user', + 'pass', + [/* PDO 옵션 */], + [ + 'trackApmQueries' => true, + 'maxQueryMetrics' => 1000 + ] +]); +``` + +쿼리를 실행한 후 수동으로 로깅할 수 있지만, 활성화되면 APM이 자동으로 로깅합니다: + +```php +Flight::db()->logQueries(); +``` + +이것은 연결 및 쿼리 메트릭과 함께 이벤트(`flight.db.queries`)를 트리거하며, Flight의 이벤트 시스템을 사용하여 이를 수신할 수 있습니다. + +### 전체 예제 + +```php +Flight::route('/users', function () { + // 모든 사용자 가져오기 + $users = Flight::db()->fetchAll('SELECT * FROM users'); + + // 모든 사용자 스트림 + $statement = Flight::db()->runQuery('SELECT * FROM users'); + while ($user = $statement->fetch()) { + echo $user['name']; + } + + // 단일 사용자 가져오기 + $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); + + // 단일 값 가져오기 + $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); + + // 단일 열 가져오기 + $ids = Flight::db()->fetchColumn('SELECT id FROM users'); + + // 키-값 쌍 가져오기 + $userNames = Flight::db()->fetchPairs('SELECT id, name FROM users'); + + // 특수 IN() 구문 + $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); + + // 새 사용자 삽입 + $id = Flight::db()->insert('users', [ + 'name' => 'Bob', + 'email' => 'bob@example.com' + ]); + + // 대량 사용자 삽입 + Flight::db()->insert('users', [ + ['name' => 'Bob', 'email' => 'bob@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'] + ]); + + // 사용자 업데이트 + $affected = Flight::db()->update('users', ['name' => 'Bob'], 'id = ?', [123]); + + // 사용자 삭제 + $deleted = Flight::db()->delete('users', 'id = ?', [123]); + + // 트랜잭션 사용 + $result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John', 'email' => 'john@example.com']); + $db->insert('audit_log', ['action' => 'user_created']); + return $db->lastInsertId(); + }); +}); +``` + +## PdoWrapper에서 마이그레이션 + +현재 `PdoWrapper`를 사용 중이라면 `SimplePdo`로 마이그레이션하는 것이 간단합니다: + +1. **등록 업데이트:** + ```php + // 이전 + Flight::register('db', \flight\database\PdoWrapper::class, [ /* ... */ ]); + + // 새 + Flight::register('db', \flight\database\SimplePdo::class, [ /* ... */ ]); + ``` + +2. **기존 `PdoWrapper` 메서드가 `SimplePdo`에서 모두 작동** - 변경 사항이 없습니다. 기존 코드가 계속 작동합니다. + +3. **새 헬퍼 메서드 선택적으로 사용** - 코드를 단순화하기 위해 `insert()`, `update()`, `delete()`, `transaction()`을 사용하기 시작하세요. + +## 관련 자료 + +- [Collections](/learn/collections) - 쉬운 데이터 접근을 위한 Collection 클래스 사용법을 배웁니다. +- [PdoWrapper](/learn/pdo-wrapper) - 레거시 PDO 헬퍼 클래스 (사용 중단됨). + +## 문제 해결 + +- 데이터베이스 연결 오류가 발생하면 DSN, 사용자 이름, 비밀번호 및 옵션을 확인하세요. +- 모든 행은 Collection으로 반환됩니다—일반 배열이 필요하면 `$collection->getData()`를 사용하세요. +- `IN (?)` 쿼리의 경우 배열을 전달했는지 확인하세요. +- 장기 실행 프로세스에서 쿼리 로깅으로 인한 메모리 문제를 겪는다면 `maxQueryMetrics` 옵션을 조정하세요. + +## 변경 로그 + +- v3.18.0 - insert, update, delete 및 트랜잭션 헬퍼 메서드가 포함된 SimplePdo의 초기 릴리스. \ No newline at end of file diff --git a/content/v3/lv/awesome-plugins/awesome_plugins.md b/content/v3/lv/awesome-plugins/awesome_plugins.md index 1f5c3a43..8fe779d7 100644 --- a/content/v3/lv/awesome-plugins/awesome_plugins.md +++ b/content/v3/lv/awesome-plugins/awesome_plugins.md @@ -1,103 +1,104 @@ # Lieliski spraudņi -Flight ir neticami paplašināms. Ir vairāki spraudņi, ko var izmantot, lai pievienotu funkcionalitāti jūsu Flight lietojumprogrammai. Daži no tiem oficiāli atbalsta Flight komanda, bet citi ir mikro/lite bibliotēkas, lai palīdzētu jums sākt. +Flight ir neticami paplašināms. Ir vairāki spraudņi, ko var izmantot, lai pievienotu funkcionalitāti jūsu Flight aplikācijai. Daži no tiem oficiāli atbalsta Flight Team, bet citi ir mikro/lite bibliotēkas, lai palīdzētu jums sākt. ## API dokumentācija -API dokumentācija ir izšķiroša jebkurai API. Tā palīdz izstrādātājiem saprast, kā mijiedarboties ar jūsu API un ko sagaidīt pretī. Ir pieejami vairāki rīki, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. +API dokumentācija ir izšķiroša jebkuram API. Tā palīdz izstrādātājiem saprast, kā mijiedarboties ar jūsu API un ko sagaidīt pretī. Ir pieejami vairāki rīki, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Bloga ieraksts, ko uzrakstījis Daniels Šraibers par to, kā izmantot OpenAPI specifikāciju ar FlightPHP, lai izveidotu jūsu API, izmantojot API pirmo pieeju. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ir lielisks rīks, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. To ir ļoti viegli izmantot, un to var pielāgot jūsu vajadzībām. Šī ir PHP bibliotēka, lai palīdzētu ģenerēt Swagger dokumentāciju. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Bloga ieraksts, ko uzrakstījis Daniels Šreibers, par to, kā izmantot OpenAPI specifikāciju ar FlightPHP, lai izveidotu jūsu API, izmantojot API pirmo pieeju. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI ir lielisks rīks, lai palīdzētu ģenerēt API dokumentāciju jūsu Flight projektiem. To ir ļoti viegli izmantot un var pielāgot jūsu vajadzībām. Šī ir PHP bibliotēka, lai palīdzētu ģenerēt Swagger dokumentāciju. -## Lietojumprogrammas veiktspējas uzraudzība (APM) +## Aplikācijas veiktspējas uzraudzība (APM) -Lietojumprogrammas veiktspējas uzraudzība (APM) ir izšķiroša jebkurai lietojumprogrammai. Tā palīdz jums saprast, kā darbojas jūsu lietojumprogramma un kur ir pudeles kakli. Ir vairāki APM rīki, ko var izmantot ar Flight. -- oficiāls [flightphp/apm](/awesome-plugins/apm) - Flight APM ir vienkārša APM bibliotēka, ko var izmantot, lai uzraudzītu jūsu Flight lietojumprogrammas. To var izmantot, lai uzraudzītu jūsu lietojumprogrammas veiktspēju un palīdzētu identificēt pudeles kaklus. +Aplikācijas veiktspējas uzraudzība (APM) ir izšķiroša jebkurai aplikācijai. Tā palīdz saprast, kā jūsu aplikācija darbojas un kur ir pudeles kakli. Ir vairāki APM rīki, ko var izmantot ar Flight. +- oficiāls [flightphp/apm](/awesome-plugins/apm) - Flight APM ir vienkārša APM bibliotēka, ko var izmantot, lai uzraudzītu jūsu Flight aplikācijas. To var izmantot, lai uzraudzītu jūsu aplikācijas veiktspēju un palīdzētu identificēt pudeles kaklus. ## Async -Flight jau ir ātrs ietvars, bet, pievienojot tam turbīnas dzinēju, viss kļūst jautrāks (un izaicinošāks)! +Flight jau ir ātrs ietvars, bet pievienojot tam turbīnas dzinēju, viss kļūst jautrāks (un izaicinājums)! -- [flightphp/async](/awesome-plugins/async) - Oficiālā Flight Async bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot asinhrono apstrādi jūsu lietojumprogrammai. Tā izmanto Swoole/Openswoole zem pārsega, lai nodrošinātu vienkāršu un efektīvu veidu, kā palaist uzdevumus asinhroni. +- [flightphp/async](/awesome-plugins/async) - Oficiālā Flight Async bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot asinhrono apstrādi jūsu aplikācijai. Tā izmanto Swoole/Openswoole zem motora, lai nodrošinātu vienkāršu un efektīvu veidu, kā palaist uzdevumus asinhroni. ## Autorizācija/Atslēgas -Autorizācija un atļaujas ir izšķirošas jebkurai lietojumprogrammai, kurai nepieciešami kontroles, lai noteiktu, kas var piekļūt kam. +Autorizācija un atļaujas ir izšķirošas jebkurai aplikācijai, kas prasa kontroli par to, kas var piekļūt kam. -- oficiāls [flightphp/permissions](/awesome-plugins/permissions) - Oficiālā Flight Permissions bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot lietotāja un lietojumprogrammas līmeņa atļaujas jūsu lietojumprogrammai. +- oficiāls [flightphp/permissions](/awesome-plugins/permissions) - Oficiālā Flight Permissions bibliotēka. Šī bibliotēka ir vienkāršs veids, kā pievienot lietotāja un aplikācijas līmeņa atļaujas jūsu aplikācijai. ## Autentifikācija -Autentifikācija ir būtiska lietojumprogrammām, kurām jāpārbauda lietotāja identitāte un jānodrošina droši API galapunkti. +Autentifikācija ir būtiska aplikācijām, kas vajag pārbaudīt lietotāja identitāti un nodrošināt drošus API galapunktus. -- [firebase/php-jwt](/awesome-plugins/jwt) - JSON Web Token (JWT) bibliotēka PHP. Vienkāršs un drošs veids, kā ieviest tokenu balstītu autentifikāciju jūsu Flight lietojumprogrammās. Ideāli piemērots bezstāvokļa API autentifikācijai, maršrutu aizsardzībai ar starpprogrammatūru un OAuth stila autorizācijas plūsmu ieviešanai. +- [firebase/php-jwt](/awesome-plugins/jwt) - JSON Web Token (JWT) bibliotēka PHP. Vienkāršs un drošs veids, kā ieviest tokenu balstītu autentifikāciju jūsu Flight aplikācijās. Ideāli piemērots bezstāvokļa API autentifikācijai, aizsargājot maršrutus ar starprogrammatūru un īstenojot OAuth stila autorizācijas plūsmas. ## Kešošana -Kešošana ir lielisks veids, kā paātrināt jūsu lietojumprogrammu. Ir vairākas kešošanas bibliotēkas, ko var izmantot ar Flight. +Kešošana ir lielisks veids, kā paātrināt jūsu aplikāciju. Ir vairāki kešošanas bibliotēkas, ko var izmantot ar Flight. -- oficiāls [flightphp/cache](/awesome-plugins/php-file-cache) - Gaisma, vienkārša un neatkarīga PHP failu kešošanas klase +- oficiāls [flightphp/cache](/awesome-plugins/php-file-cache) - Viegls, vienkāršs un neatkarīgs PHP failu kešošanas klase ## CLI -CLI lietojumprogrammas ir lielisks veids, kā mijiedarboties ar jūsu lietojumprogrammu. Jūs varat izmantot tās, lai ģenerētu kontrolierus, parādītu visus maršrutus un vairāk. +CLI aplikācijas ir lielisks veids, kā mijiedarboties ar jūsu aplikāciju. Jūs varat izmantot tās, lai ģenerētu kontrolierus, parādītu visus maršrutus un vairāk. -- oficiāls [flightphp/runway](/awesome-plugins/runway) - Runway ir CLI lietojumprogramma, kas palīdz jums pārvaldīt jūsu Flight lietojumprogrammas. +- oficiāls [flightphp/runway](/awesome-plugins/runway) - Runway ir CLI aplikācija, kas palīdz pārvaldīt jūsu Flight aplikācijas. ## Sīkfaili -Sīkfaili ir lielisks veids, kā uzglabāt mazas datu daļas klienta pusē. Tos var izmantot, lai uzglabātu lietotāja preferences, lietojumprogrammas iestatījumus un vairāk. +Sīkfaili ir lielisks veids, kā uzglabāt mazas datu daļas klientu pusē. Tos var izmantot, lai uzglabātu lietotāja preferences, aplikācijas iestatījumus un vairāk. -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie ir PHP bibliotēka, kas nodrošina vienkāršu un efektīvu veidu, kā pārvaldīt sīkfaius. +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie ir PHP bibliotēka, kas nodrošina vienkāršu un efektīvu veidu, kā pārvaldīt sīkfailus. ## Kļūdu labošana -Kļūdu labošana ir izšķiroša, kad jūs izstrādājat savā lokālajā vidē. Ir daži spraudņi, kas var uzlabot jūsu kļūdu labošanas pieredzi. +Kļūdu labošana ir izšķiroša, kad jūs attīstāt savā lokālajā vidē. Ir daži spraudņi, kas var uzlabot jūsu kļūdu labošanas pieredzi. -- [tracy/tracy](/awesome-plugins/tracy) - Šis ir pilnvērtīgs kļūdu apstrādātājs, ko var izmantot ar Flight. Tam ir vairāki paneļi, kas var palīdzēt jums labot kļūdas jūsu lietojumprogrammā. To ir arī ļoti viegli paplašināt un pievienot savus paneļus. -- oficiāls [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Izmantojot ar [Tracy](/awesome-plugins/tracy) kļūdu apstrādātāju, šis spraudnis pievieno dažus papildu paneļus, lai palīdzētu ar kļūdu labošanu tieši Flight projektiem. +- [tracy/tracy](/awesome-plugins/tracy) - Šis ir pilnvērtīgs kļūdu apstrādātājs, ko var izmantot ar Flight. Tam ir vairāki paneļi, kas var palīdzēt labot kļūdas jūsu aplikācijā. To ir arī ļoti viegli paplašināt un pievienot savus paneļus. +- oficiāls [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Izmantojot ar [Tracy](/awesome-plugins/tracy) kļūdu apstrādātāju, šis spraudnis pievieno dažus papildu paneļus, lai palīdzētu ar kļūdu labošanu specifiski Flight projektiem. ## Datubāzes -Datubāzes ir kodols lielākajai daļai lietojumprogrammu. Tādējādi jūs uzglabājat un izgūstat datus. Dažas datubāzu bibliotēkas ir vienkārši apvalki vaicājumu rakstīšanai, bet dažas ir pilnvērtīgas ORM. +Datubāzes ir kodols lielākajai daļai aplikāciju. Tā ir veids, kā uzglabāt un izgūt datus. Dažas datubāzu bibliotēkas ir vienkārši apvalki vaicājumu rakstīšanai, bet dažas ir pilnvērtīgas ORM. -- oficiāls [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Oficiālais Flight PDO apvalks, kas ir daļa no kodola. Šis ir vienkāršs apvalks, lai palīdzētu vienkāršot vaicājumu rakstīšanas un izpildes procesu. Tas nav ORM. -- oficiāls [flightphp/active-record](/awesome-plugins/active-record) - Oficiālā Flight ActiveRecord ORM/Kartētājs. Lieliska maza bibliotēka, lai viegli izgūtu un uzglabātu datus jūsu datubāzē. +- oficiāls [flightphp/core SimplePdo](/learn/simple-pdo) - Oficiālais Flight PDO Palīgs, kas ir kodola daļa. Šis ir moderns apvalks ar ērtām palīgmēģodēm, piemēram, `insert()`, `update()`, `delete()` un `transaction()`, lai vienkāršotu datubāzes operācijas. Visi rezultāti tiek atgriezti kā Kolekcijas elastīgai masīvu/objektu piekļuvei. Nav ORM, tikai labāks veids, kā strādāt ar PDO. +- novecojis [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Oficiālais Flight PDO Apvalks, kas ir kodola daļa (novecojis no v3.18.0). Izmantojiet SimplePdo vietā. +- oficiāls [flightphp/active-record](/awesome-plugins/active-record) - Oficiālā Flight ActiveRecord ORM/Mapper. Lieliska maza bibliotēka, lai viegli izgūtu un uzglabātu datus jūsu datubāzē. - [byjg/php-migration](/awesome-plugins/migrations) - Spraudnis, lai sekotu visām datubāzes izmaiņām jūsu projektā. ## Šifrēšana -Šifrēšana ir izšķiroša jebkurai lietojumprogrammai, kas uzglabā sensitīvus datus. Datu šifrēšana un dešifrēšana nav pārāk grūta, bet pareiza šifrēšanas atslēgas uzglabāšana [var](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [būt](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [grūta](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Visnozīmīgākais ir nekad neuzglabāt savu šifrēšanas atslēgu publiskā direktorijā vai neiekļaut to jūsu koda repozitorijā. +Šifrēšana ir izšķiroša jebkurai aplikācijai, kas uzglabā sensitīvus datus. Datu šifrēšana un dešifrēšana nav pārāk grūta, bet pareiza šifrēšanas atslēgas uzglabāšana [var](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [būt](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [grūti](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Visnozīmīgākais ir nekad neuzglabāt jūsu šifrēšanas atslēgu publiskā direktorijā vai neiekļaut to jūsu koda repozitorijā. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Šī ir bibliotēka, ko var izmantot, lai šifrētu un dešifrētu datus. Sākšana un palaišana ir diezgan vienkārša, lai sāktu šifrēt un dešifrēt datus. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - Šī ir bibliotēka, ko var izmantot, lai šifrētu un dešifrētu datus. Sākšana ir diezgan vienkārša, lai sāktu šifrēt un dešifrēt datus. -## Darba rinda +## Darbu rinda -Darba rindas ir patiešām noderīgas, lai asinhroni apstrādātu uzdevumus. Tas var būt e-pasta sūtīšana, attēlu apstrāde vai jebkas, kam nav jāveic reāllaikā. +Darbu rindas ir patiešām noderīgas, lai asinhroni apstrādātu uzdevumus. Tas var būt e-pasta sūtīšana, attēlu apstrāde vai jebkas, kas nav jāveic reāllaikā. - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue ir bibliotēka, ko var izmantot, lai apstrādātu darbus asinhroni. To var izmantot ar beanstalkd, MySQL/MariaDB, SQLite un PostgreSQL. ## Sesija -Sesijas nav īsti noderīgas API, bet, veidojot tīmekļa lietojumprogrammu, sesijas var būt izšķirošas stāvokļa un pieteikšanās informācijas uzturēšanai. +Sesijas nav īsti noderīgas API, bet veidojot tīmekļa aplikāciju, sesijas var būt izšķirošas, lai uzturētu stāvokli un pieteikšanās informāciju. - oficiāls [flightphp/session](/awesome-plugins/session) - Oficiālā Flight Session bibliotēka. Šī ir vienkārša sesijas bibliotēka, ko var izmantot, lai uzglabātu un izgūtu sesijas datus. Tā izmanto PHP iebūvēto sesijas apstrādi. -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session pārvaldnieks (nebloķējošs, zibspuldze, segments, sesijas šifrēšana). Izmanto PHP open_ssl izvēles šifrēšanai/dešifrēšanai sesijas datiem. +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (nebloķējošs, zibspuldze, segments, sesijas šifrēšana). Izmanto PHP open_ssl opcionālai sesijas datu šifrēšanai/dešifrēšanai. ## Veidnes -Veidnes ir kodols jebkurai tīmekļa lietojumprogrammai ar lietotāja interfeisu. Ir vairāki veidņu dzinēji, ko var izmantot ar Flight. +Veidnes ir kodols jebkurai tīmekļa aplikācijai ar lietotāja saskarni. Ir vairāki veidņu dzinēji, ko var izmantot ar Flight. -- novecojis [flightphp/core View](/learn#views) - Šis ir ļoti pamata veidņu dzinējs, kas ir daļa no kodola. Nav ieteicams izmantot, ja jūsu projektā ir vairāk nekā pāris lapas. +- novecojis [flightphp/core View](/learn#views) - Šis ir ļoti pamata veidņu dzinējs, kas ir kodola daļa. Nav ieteicams izmantot, ja jūsu projektā ir vairāk nekā pāris lapas. - [latte/latte](/awesome-plugins/latte) - Latte ir pilnvērtīgs veidņu dzinējs, kas ir ļoti viegli lietojams un jūtas tuvāk PHP sintaksei nekā Twig vai Smarty. To ir arī ļoti viegli paplašināt un pievienot savus filtrus un funkcijas. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate ir jaudīgs PHP veidņu dzinējs ar resursu kompilāciju, veidņu mantošanu un mainīgo apstrādi. Funkcijas ietver automātisku CSS/JS minimizāciju, kešošanu, Base64 kodēšanu un izvēles Flight PHP ietvara integrāciju. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate ir jaudīgs PHP veidņu dzinējs ar resursu kompilāciju, veidnes mantošanu un mainīgo apstrādi. Funkcijas ietver automātisku CSS/JS minimizāciju, kešošanu, Base64 kodēšanu un opcionālu Flight PHP ietvara integrāciju. ## WordPress integrācija -Vai vēlaties izmantot Flight savā WordPress projektā? Tam ir ērts spraudnis! +Vai vēlaties izmantot Flight savā WordPress projektā? Ir ērts spraudnis tam! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Šis WordPress spraudnis ļauj palaist Flight tieši blakus WordPress. Tas ir ideāli piemērots, lai pievienotu pielāgotas API, mikroservisus vai pat pilnvērtīgas lietojumprogrammas jūsu WordPress vietnē, izmantojot Flight ietvaru. Ļoti noderīgi, ja vēlaties labāko no abām pasaulēm! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Šis WordPress spraudnis ļauj palaist Flight tieši blakus WordPress. Tas ir ideāli piemērots, lai pievienotu pielāgotus API, mikroservisu vai pat pilnas aplikācijas jūsu WordPress vietnē, izmantojot Flight ietvaru. Ļoti noderīgi, ja vēlaties labāko no abām pasaulēm! ## Iesaiste -Vai jums ir spraudnis, ko vēlaties dalīties? Iesniedziet pieprasījumu, lai pievienotu to sarakstam! \ No newline at end of file +Vai jums ir spraudnis, ko vēlaties dalīties? Iesniedziet pull request, lai pievienotu to sarakstam! \ No newline at end of file diff --git a/content/v3/lv/awesome-plugins/jwt.md b/content/v3/lv/awesome-plugins/jwt.md index b206c5d0..36b0032a 100644 --- a/content/v3/lv/awesome-plugins/jwt.md +++ b/content/v3/lv/awesome-plugins/jwt.md @@ -1,24 +1,24 @@ -# Firebase JWT - JSON Web Token autentifikācija Flight +# Firebase JWT - JSON Web Token autentifikācija -JWT (JSON Web Tokens) ir kompakts, URL-drošs veids, kā pārstāvēt pretenzijas starp jūsu lietojumprogrammu un klientu. Tie ir ideāli piemēroti bezstāvokļa API autentifikācijai — nav vajadzīga servera puses sesiju uzglabāšana! Šis ceļvedis parāda, kā integrēt [Firebase JWT](https://github.com/firebase/php-jwt) ar Flight drošai, tokenu balstītai autentifikācijai. +JWT (JSON Web Tokens) ir kompakts, URL-drošs veids, kā attēlot apgalvojumus starp jūsu lietojumprogrammu un klientu. Tie ir ideāli piemēroti bezstāvokļa API autentifikācijai — nav nepieciešama servera puses sesijas uzglabāšana! Šis ceļvedis parāda, kā integrēt [Firebase JWT](https://github.com/firebase/php-jwt) ar Flight drošai, tokenu balstītai autentifikācijai. Apmeklējiet [Github krātuvi](https://github.com/firebase/php-jwt), lai iegūtu pilnu dokumentāciju un detaļas. ## Kas ir JWT? JSON Web Token ir virkne, kas satur trīs daļas: -1. **Virsnieks**: Metadati par tokenu (algoritms, tips) +1. **Galvene**: Metadati par tokenu (algoritms, tips) 2. **Ladējums**: Jūsu dati (lietotāja ID, lomas, termiņš utt.) -3. **Paraksts**: Kriptogrāfiskais paraksts autentiskuma pārbaudei +3. **Paraksts**: Kriptogrāfisks paraksts autentiskuma pārbaudei -Piemērs JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (izskatās pēc muļķībām, bet tas ir strukturēti dati!) +Piemērs JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (izskatās kā neskaidrs teksts, bet tas ir strukturēti dati!) ### Kāpēc izmantot JWT? -- **Bezstāvoklis**: Nav vajadzīga servera puses sesiju uzglabāšana — ideāli piemērots mikroservisiem un API -- **Mērogojams**: Labi darbojas ar slodzes līdzsvarotājjiem, jo nav sesiju saistības prasības -- **Pārrobežu**: Var izmantot dažādās domēnos un servisos -- **Mobilajām ierīcēm draudzīgs**: Lieliski piemērots mobilajām lietojumprogrammām, kur sīkfaili var nedarboties labi +- **Bezstāvokļa**: Nav nepieciešama servera puses sesijas uzglabāšana — ideāli piemērots mikroservisiem un API +- **Izmērojams**: Labi darbojas ar slodzes līdzsvarotājiem, jo nav sesijas saistības prasības +- **Pārrobežu**: Var izmantot dažādās domēnos un servisā +- **Mobilajām ierīcēm draudzīgs**: Lieliski piemērots mobilajām lietotnēm, kur cepumi var nedarboties labi - **Standartizēts**: Nozares standarta pieeja (RFC 7519) ## Instalēšana @@ -31,13 +31,13 @@ composer require firebase/php-jwt ## Pamata izmantošana -Šeit ir ātrs piemērs tokena izveidei un pārbaudei: +Šeit ir ātrs piemērs JWT izveidei un pārbaudei: ```php use Firebase\JWT\JWT; use Firebase\JWT\Key; -// Jūsu slepenā atslēga (TURĒT TO DROŠU!) +// Jūsu slepenā atslēga (SAGLABĀJIE TO DROŠU!) $secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; // Izveidojiet tokenu @@ -46,7 +46,7 @@ $payload = [ 'username' => 'johndoe', 'role' => 'admin', 'iat' => time(), // Izsniegts - 'exp' => time() + 3600 // Beidzas pēc 1 stundas + 'exp' => time() + 3600 // Beigsies pēc 1 stundas ]; $jwt = JWT::encode($payload, $secretKey, 'HS256'); @@ -61,9 +61,9 @@ try { } ``` -## JWT starpprogrammatūra Flight (Ieteicamais pieeja) +## JWT starpprogrammatūra Flight (Ieteicamā pieeja) -Visizplatītākais un noderīgākais veids, kā izmantot JWT ar Flight, ir kā **starpprogrammatūru**, lai aizsargātu jūsu API maršrutus. Šeit ir pilnīgs, ražošanai gatavs piemērs: +Biežākais un noderīgākais veids, kā izmantot JWT ar Flight, ir kā **starpprogrammatūru**, lai aizsargātu jūsu API maršrutus. Šeit ir pilnīgs, ražošanai gatavs piemērs: ### 1. solis: Izveidojiet JWT starpprogrammatūras klasi @@ -82,14 +82,14 @@ class JwtMiddleware { public function __construct(Engine $app) { $this->app = $app; - // Uzglabājiet savu slepeno atslēgu app/config/config.php, nevis cietkodus! + // Saglabājiet savu slepeno atslēgu app/config/config.php, nevis cietkodus! $this->secretKey = $app->get('config')['jwt_secret']; } public function before(array $params) { $authHeader = $this->app->request()->getHeader('Authorization'); - // Pārbaudiet, vai pastāv autorizācijas virsraksts + // Pārbaudiet, vai pastāv Authorization galvene if (empty($authHeader)) { $this->app->jsonHalt(['error' => 'Nav nodrošināts autorizācijas tokens'], 401); } @@ -105,7 +105,7 @@ class JwtMiddleware { // Atšifrējiet un pārbaudiet tokenu $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); - // Uzglabājiet lietotāja datus pieprasījumā, lai izmantotu maršruta apstrādātājos + // Saglabājiet lietotāja datus pieprasījumā, lai izmantotu maršruta apstrādātājos $this->app->request()->data->user = $decoded; } catch (ExpiredException $e) { @@ -128,7 +128,7 @@ return [ ]; // app/config/bootstrap.php vai index.php -// pārliecinieties, ka pievienojat šo rindu, ja vēlaties pakļaut konfigurāciju lietojumprogrammai +// pārliecinieties, ka pievienojat šo rindu, ja vēlaties pakļaut konfigurāciju lietotnei $app->set('config', $config); ``` @@ -145,7 +145,7 @@ Flight::route('GET /api/user/profile', function() { 'username' => $user->username, 'role' => $user->role ]); -})->addMiddleware( JwtMiddleware::class); +})->addMiddleware(JwtMiddleware::class); // Aizsargājiet veselu maršrutu grupu (biežāk!) Flight::group('/api', function() { @@ -158,9 +158,9 @@ Flight::group('/api', function() { Lai iegūtu vairāk detaļu par starpprogrammatūru, skatiet [starpprogrammatūras dokumentāciju](/learn/middleware). -## Izplatīti izmantošanas gadījumi +## Biežas izmantošanas gadījumi -### 1. Pieteikšanās galapunkts (Tokena ģenerēšana) +### 1. Pieteikšanās galapunkts (Tokenu ģenerēšana) Izveidojiet maršrutu, kas ģenerē JWT pēc veiksmīgas autentifikācijas: @@ -213,9 +213,9 @@ function validateUserCredentials($username, $password) { } ``` -### 2. Tokena atjaunošanas plūsma +### 2. Tokenu atjaunošanas plūsma -Īstenojiet atjaunošanas tokena sistēmu ilgstošām sesijām: +Implementējiet atjaunošanas tokenu sistēmu ilgstošām sesijām: ```php Flight::route('POST /api/login', function() { @@ -224,7 +224,7 @@ Flight::route('POST /api/login', function() { $secretKey = Flight::get('config')['jwt_secret']; $refreshSecret = Flight::get('config')['jwt_refresh_secret']; - // Īstermiņa piekļuves tokens (15 minūtes) + // Īsa mūža piekļuves tokens (15 minūtes) $accessToken = JWT::encode([ 'user_id' => $user->id, 'type' => 'access', @@ -232,7 +232,7 @@ Flight::route('POST /api/login', function() { 'exp' => time() + (15 * 60) ], $secretKey, 'HS256'); - // Ilgtermiņa atjaunošanas tokens (7 dienas) + // Ilga mūža atjaunošanas tokens (7 dienas) $refreshToken = JWT::encode([ 'user_id' => $user->id, 'type' => 'refresh', @@ -309,16 +309,16 @@ class JwtRoleMiddleware { } } -// Lietojums: Tikai administratora maršruts +// Lietojums: Administrātora tikai maršruts Flight::route('DELETE /api/users/@id', function($id) { - // Dzēst lietotāja loģiku + // Dzēst lietotāja loģika })->addMiddleware([ JwtMiddleware::class, new JwtRoleMiddleware(Flight::app(), ['admin']) ]); ``` -### 4. Publiska API ar ātruma ierobežošanu pēc lietotāja +### 4. Publiskais API ar ātruma ierobežošanu pa lietotāju Izmantojiet JWT, lai izsekotu un ierobežotu ātrumu lietotājiem bez sesijām: @@ -330,7 +330,7 @@ class RateLimitMiddleware { $userId = $user ? $user->user_id : Flight::request()->ip; $cacheKey = "rate_limit:$userId"; - // Pārliecinieties, ka iestatāt kešatmiņas servisu app/config/services.php + // Pārliecinieties, ka iestatāt kešošanas servisu app/config/services.php $requests = Flight::cache()->get($cacheKey, 0); if ($requests >= 100) { // 100 pieprasījumi stundā @@ -344,39 +344,39 @@ class RateLimitMiddleware { ## Drošības labākās prakses -### 1. Izmantojiet spēcīgas slepenās atslēgas +### 1. Izmantojiet stipras slepenās atslēgas ```php -// Ģenerējiet drošu slepeno atslēgu (palaižiet vienreiz, saglabājiet .env failā) +// Ģenerējiet drošu slepeno atslēgu (izpildiet vienreiz, saglabājiet .env failā) $secretKey = base64_encode(random_bytes(32)); -echo $secretKey; // Uzglabājiet to savā .env failā! +echo $secretKey; // Saglabājiet to savā .env failā! ``` -### 2. Uzglabājiet noslēpumus vides mainīgajos +### 2. Saglabājiet noslēpumus vides mainīgajos ```php -// Nekad neapņemiet noslēpumus versiju kontrolē! +// Nekad neiekļaujiet noslēpumus versiju kontrolē! // Izmantojiet .env failu un bibliotēku, piemēram, vlucas/phpdotenv // .env fails: // JWT_SECRET=your-base64-encoded-secret-here // JWT_REFRESH_SECRET=another-base64-encoded-secret-here -// Varat arī izmantot app/config/config.php failu, lai uzglabātu savus noslēpumus -// tikai pārliecinieties, ka konfigurācijas fails nav apņemts versiju kontrolē +// Jūs varat arī izmantot app/config/config.php failu, lai saglabātu savus noslēpumus +// tikai pārliecinieties, ka konfigurācijas fails nav iekļauts versiju kontrolē // return [ // 'jwt_secret' => 'your-base64-encoded-secret-here', // 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', // ]; -// Savā lietojumprogrammā: +// Savā lietotnē: $secretKey = getenv('JWT_SECRET'); ``` -### 3. Iestatiet piemērotus termiņu laikus +### 3. Iestatiet piemērotus termiņus ```php -// Labā prakse: īstermiņa piekļuves tokeni +// Labā prakse: īsa mūža piekļuves tokeni 'exp' => time() + (15 * 60) // 15 minūtes // Atjaunošanas tokeniem: ilgāks termiņš @@ -387,15 +387,15 @@ $secretKey = getenv('JWT_SECRET'); JWT vienmēr jāpārsūta pār HTTPS. Nekad nesūtiet tokenus pār vienkāršu HTTP ražošanā! -### 5. Validējiet tokena pretenzijas +### 5. Validējiet tokena apgalvojumus -Vienmēr validējiet pretenzijas, kas jums rūp: +Vienmēr validējiet apgalvojumus, kas jums rūp: ```php $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); -// Pārbaudiet termiņu, ko bibliotēka automātiski apstrādā -// Bet varat pievienot pielāgotas validācijas: +// Pārbaude par termiņu tiek apstrādāta automātiski bibliotēkas +// Bet jūs varat pievienot pielāgotas validācijas: if ($decoded->iat > time()) { throw new Exception('Tokens izmantots pirms izsniegšanas'); } @@ -405,7 +405,7 @@ if (isset($decoded->nbf) && $decoded->nbf > time()) { } ``` -### 6. Apsveriet tokena melno sarakstu izrakstīšanai +### 6. Apsveriet tokenu melno sarakstu izrakstīšanai Papildu drošībai uzturiet nederīgu tokenu melno sarakstu: @@ -419,7 +419,7 @@ Flight::route('POST /api/logout', function() { $decoded = Flight::request()->data->user; $ttl = $decoded->exp - time(); - // Uzglabājiet kešatmiņā/redis līdz termiņam + // Saglabājiet kešā/redis līdz termiņam Flight::cache()->set("blacklist:$jwt", true, $ttl); Flight::json(['message' => 'Veiksmīgi izrakstījies']); @@ -443,8 +443,8 @@ public function before(array $params) { Firebase JWT atbalsta vairākus algoritmus: ### Simetriskie algoritmi (HMAC) -- **HS256** (Ieteicams lielākajai daļai lietojumprogrammu): Izmanto vienu slepeno atslēgu -- **HS384**, **HS512**: Spēcīgākas variācijas +- **HS256** (Ieteicams lielākajai daļai lietotņu): Izmanto vienu slepeno atslēgu +- **HS384**, **HS512**: Stiprāki varianti ```php $jwt = JWT::encode($payload, $secretKey, 'HS256'); @@ -452,8 +452,8 @@ $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); ``` ### Asimetriskie algoritmi (RSA/ECDSA) -- **RS256**, **RS384**, **RS512**: Izmanto publisko/privāto atslēgu pārus -- **ES256**, **ES384**, **ES512**: Elipses līknes variācijas +- **RS256**, **RS384**, **RS512**: Izmanto publiskās/privātās atslēgu pārus +- **ES256**, **ES384**, **ES512**: Elipses līknes varianti ```php // Ģenerējiet atslēgas: openssl genrsa -out private.key 2048 @@ -469,27 +469,27 @@ $jwt = JWT::encode($payload, $privateKey, 'RS256'); $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); ``` -> **Kad izmantot RSA**: Izmantojiet RSA, kad nepieciešams izplatīt publisko atslēgu pārbaudei (piem., mikroservisi, trešo pušu integrācijas). Vienai lietojumprogrammai HS256 ir vienkāršāks un pietiekams. +> **Kad izmantot RSA**: Izmantojiet RSA, kad jums jāizplata publiskā atslēga pārbaudei (piem., mikroservisi, trešo pušu integrācijas). Vienai lietotnei HS256 ir vienkāršāks un pietiekams. ## Traucējummeklēšana ### "Beidzies tokens" kļūda -Jūsu tokena `exp` pretenzija ir pagātnē. Izsniedziet jaunu tokenu vai īstenojiet tokena atjaunošanu. +Jūsu tokena `exp` apgalvojums ir pagātnē. Izsniedziet jaunu tokenu vai implementējiet tokenu atjaunošanu. ### "Paraksta pārbaude neizdevās" - Jūs izmantojat citu slepeno atslēgu atšifrēšanai nekā kodēšanai - Tokens ir modificēts -- Laika nobīde starp serveriem (pievienojiet atlaidzes buferi) +- Laika nobīde starp serveriem (pievienojiet buferi) ```php use Firebase\JWT\JWT; -JWT::$leeway = 60; // Ļauj 60 sekunžu laika nobīdi +JWT::$leeway = 60; // Atļaujiet 60 sekunžu laika nobīdi $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); ``` ### Tokens netiek nosūtīts pieprasījumos -Pārliecinieties, ka jūsu klients nosūta `Authorization` virsrakstu: +Pārliecinieties, ka jūsu klients nosūta `Authorization` galveni: ```javascript // JavaScript piemērs @@ -502,30 +502,30 @@ fetch('/api/users', { ## Metodes -Firebase JWT bibliotēka nodrošina šīs pamata metodes: +Firebase JWT bibliotēka nodrošina šīs pamatmetodes: - `JWT::encode(array $payload, string $key, string $alg)`: Izveido JWT no ladējuma - `JWT::decode(string $jwt, Key $key)`: Atšifrē un pārbauda JWT -- `JWT::urlsafeB64Encode(string $input)`: Base64 URL-droša kodēšana -- `JWT::urlsafeB64Decode(string $input)`: Base64 URL-droša atšifrēšana -- `JWT::$leeway`: Statiska īpašība, lai iestatītu laika atlaidzi validācijai (sekundēs) +- `JWT::urlsafeB64Encode(string $input)`: Base64 URL-drošs kodējums +- `JWT::urlsafeB64Decode(string $input)`: Base64 URL-drošs atšifrējums +- `JWT::$leeway`: Statiska īpašība, lai iestatītu laika buferi validācijai (sekundēs) ## Kāpēc izmantot šo bibliotēku? -- **Nozares standarts**: Firebase JWT ir populārākā un plaši uzticamā JWT bibliotēka PHP +- **Nozares standarts**: Firebase JWT ir populārākā un visvairāk uzticamā JWT bibliotēka PHP - **Aktīva uzturēšana**: Uztur Google/Firebase komanda -- **Uz drošību orientēta**: Regulāras atjauninājumi un drošības labojumi -- **Vienkārša API**: Viegli saprotama un īstenojama +- **Drošībai veltīta**: Regulāri atjauninājumi un drošības labojumi +- **Vienkārša API**: Viegli saprast un ieviest - **Labu dokumentēšana**: Plaša dokumentācija un kopienas atbalsts -- **Elastīga**: Atbalsta vairākus algoritmus un konfigurējamās opcijas +- **Elastīga**: Atbalsta vairākus algoritmus un konfigurējamu opciju ## Skatīt arī - [Firebase JWT Github krātuve](https://github.com/firebase/php-jwt) -- [JWT.io](https://jwt.io/) - Kļūdu labošana un JWT atšifrēšana +- [JWT.io](https://jwt.io/) - Debugošana un atšifrēšana JWT - [RFC 7519](https://tools.ietf.org/html/rfc7519) - Oficiālā JWT specifikācija -- [Flight starpprogrammatūras dokumentācija](/learn/middleware) -- [Flight sesijas spraudnis](/awesome-plugins/session) - Tradicionālai sesiju balstītai autentifikācijai +- [Flight Starpprogrammatūras dokumentācija](/learn/middleware) +- [Flight Sesijas spraudnis](/awesome-plugins/session) - Tradicionālai sesiju balstītai autentifikācijai ## Licence diff --git a/content/v3/lv/awesome-plugins/runway.md b/content/v3/lv/awesome-plugins/runway.md index 550ab583..fddae8dc 100644 --- a/content/v3/lv/awesome-plugins/runway.md +++ b/content/v3/lv/awesome-plugins/runway.md @@ -1,10 +1,10 @@ -# Runway +# Lidlaukums -Runway ir CLI lietojumprogramma, kas palīdz pārvaldīt jūsu Flight lietojumprogrammas. Tā var ģenerēt kontrolierus, parādīt visas maršrutus un vairāk. Tā ir balstīta uz izcilo [adhocore/php-cli](https://github.com/adhocore/php-cli) bibliotēku. +Lidlaukums ir CLI lietojumprogramma, kas palīdz pārvaldīt jūsu Flight lietojumprogrammas. Tā var ģenerēt kontrolierus, parādīt visas maršrutus un vairāk. Tā ir balstīta uz izcilo [adhocore/php-cli](https://github.com/adhocore/php-cli) bibliotēku. Noklikšķiniet [šeit](https://github.com/flightphp/runway), lai skatītu kodu. -## Instalācija +## Instalēšana Instalējiet ar composer. @@ -14,7 +14,7 @@ composer require flightphp/runway ## Pamata konfigurācija -Pirmo reizi palaižot Runway, tā mēģinās atrast `runway` konfigurāciju `app/config/config.php` caur `'runway'` atslēgu. +Pirmo reizi palaižot Lidlaukumu, tas mēģinās atrast `runway` konfigurāciju `app/config/config.php` caur `'runway'` atslēgu. ```php **PIEZĪME** - Sākot ar **v1.2.0**, `.runway-config.json` ir novecojis. Lūdzu, migrējiet savu konfigurāciju uz `app/config/config.php`. Jūs varat to izdarīt viegli ar komandu `php runway config:migrate`. +> **PIEZĪME** - Kopš **v1.2.0**, `.runway-config.json` ir atcelts. Lūdzu, migrējiet savu konfigurāciju uz `app/config/config.php`. Jūs varat to izdarīt viegli ar `php runway config:migrate` komandu. ### Projekta saknes noteikšana -Runway ir pietiekami gudra, lai noteiktu jūsu projekta sakni, pat ja jūs to palaižat no apakšdirektorijas. Tā meklē indikatorus, piemēram, `composer.json`, `.git` vai `app/config/config.php`, lai noteiktu, kur ir projekta sakne. Tas nozīmē, ka jūs varat palaidīt Runway komandas no jebkuras vietas jūsu projektā! +Lidlaukums ir pietiekami gudrs, lai noteiktu jūsu projekta sakni, pat ja jūs to palaižat no apakšdirektorijas. Tas meklē indikatorus, piemēram, `composer.json`, `.git` vai `app/config/config.php`, lai noteiktu, kur ir projekta sakne. Tas nozīmē, ka jūs varat palaidīt Lidlaukuma komandas no jebkuras vietas jūsu projektā! -## Lietošana +## Lietojums -Runway ir vairākas komandas, kuras jūs varat izmantot, lai pārvaldītu jūsu Flight lietojumprogrammu. Ir divi viegli veidi, kā izmantot Runway. +Lidlaukumam ir vairākas komandas, kuras jūs varat izmantot, lai pārvaldītu jūsu Flight lietojumprogrammu. Ir divi viegli veidi, kā izmantot Lidlaukumu. 1. Ja jūs izmantojat skeletu projektu, jūs varat palaidīt `php runway [command]` no jūsu projekta saknes. -1. Ja jūs izmantojat Runway kā paketi, kas instalēta caur composer, jūs varat palaidīt `vendor/bin/runway [command]` no jūsu projekta saknes. +1. Ja jūs izmantojat Lidlaukumu kā paketi, kas instalēta caur composer, jūs varat palaidīt `vendor/bin/runway [command]` no jūsu projekta saknes. ### Komandu saraksts -Jūs varat skatīt visu pieejamo komandu sarakstu, palaižot komandu `php runway`. +Jūs varat skatīt visu pieejamo komandu sarakstu, palaižot `php runway` komandu. ```bash php runway @@ -50,7 +50,7 @@ php runway ### Komandu palīdzība -Jebkurai komandai jūs varat pievienot karodziņu `--help`, lai iegūtu vairāk informācijas par to, kā izmantot komandu. +Jebkurai komandai jūs varat pievienot `--help` karodziņu, lai iegūtu vairāk informācijas par to, kā izmantot komandu. ```bash php runway routes --help @@ -74,7 +74,7 @@ Vispirms pārliecinieties, ka esat instalējis [Active Record](/awesome-plugins/ php runway make:record users ``` -Ja, piemēram, jums ir `users` tabula ar šādu shēmu: `id`, `name`, `email`, `created_at`, `updated_at`, fails, līdzīgs šim, tiks izveidots `app/records/UserRecord.php` failā: +Ja, piemēram, jums ir `users` tabula ar šādu shēmu: `id`, `name`, `email`, `created_at`, `updated_at`, fails, līdzīgs sekojošajam, tiks izveidots `app/records/UserRecord.php` failā: ```php argument('', 'Jautrā gif nosaukums'); + $this->argument('', 'Smieklīgā gif nosaukums'); } /** @@ -178,15 +178,15 @@ class ExampleCommand extends AbstractBaseCommand } ``` -Skatiet [adhocore/php-cli Dokumentāciju](https://github.com/adhocore/php-cli), lai iegūtu vairāk informācijas par to, kā izveidot savas pielāgotas komandas savai Flight lietojumprogrammai! +Skatiet [adhocore/php-cli Dokumentāciju](https://github.com/adhocore/php-cli), lai iegūtu vairāk informācijas par to, kā izveidot savas pielāgotas komandas jūsu Flight lietojumprogrammā! ## Konfigurācijas pārvaldība -Tā kā konfigurācija ir pārcelta uz `app/config/config.php` sākot ar `v1.2.0`, ir dažas palīglomas, lai pārvaldītu konfigurāciju. +Tā kā konfigurācija ir pārcelta uz `app/config/config.php` kopš `v1.2.0`, ir dažas palīpkomandas konfigurācijas pārvaldībai. ### Migrēt veco konfigurāciju -Ja jums ir vecs `.runway-config.json` fails, jūs varat viegli to migrēt uz `app/config/config.php` ar šādu komandu: +Ja jums ir vecs `.runway-config.json` fails, jūs varat viegli to migrēt uz `app/config/config.php` ar sekojošo komandu: ```bash php runway config:migrate @@ -194,7 +194,7 @@ php runway config:migrate ### Iestatīt konfigurācijas vērtību -Jūs varat iestatīt konfigurācijas vērtību, izmantojot `config:set` komandu. Tas ir noderīgi, ja vēlaties atjaunināt konfigurācijas vērtību, neizmantojot failu. +Jūs varat iestatīt konfigurācijas vērtību, izmantojot `config:set` komandu. Tas ir noderīgi, ja vēlaties atjaunināt konfigurācijas vērtību bez faila atvēršanas. ```bash php runway config:set app_root "app/" @@ -208,9 +208,9 @@ Jūs varat iegūt konfigurācijas vērtību, izmantojot `config:get` komandu. php runway config:get app_root ``` -## Visas Runway konfigurācijas +## Visas Lidlaukuma konfigurācijas -Ja jums vajadzīga pielāgošana Runway konfigurācijai, jūs varat iestatīt šīs vērtības `app/config/config.php`. Zemāk ir dažas papildu konfigurācijas, kuras jūs varat iestatīt: +Ja jums vajadzīga konfigurācijas pielāgošana Lidlaukumam, jūs varat iestatīt šīs vērtības `app/config/config.php`. Zemāk ir dažas papildu konfigurācijas, kuras jūs varat iestatīt: ```php [ - // Šī ir vieta, kur atrodas jūsu lietojumprogrammas direktorija + // Šī ir jūsu lietojumprogrammas direktorijas atrašanās vieta 'app_root' => 'app/', // Šī ir direktorija, kur atrodas jūsu saknes indeksa fails @@ -233,7 +233,7 @@ return [ // Bāzes ceļi, visticamāk, nav jākonfigurē, bet tas ir šeit, ja vēlaties 'base_paths' => [ - '/includes/libs/vendor', // ja jums ir patiesi unikāls ceļš uz jūsu vendor direktoriju vai kaut ko + '/includes/libs/vendor', // ja jums ir patiešām unikāls ceļš uz jūsu vendor direktoriju vai kaut ko ], // Galīgie ceļi ir atrašanās vietas projektā, kur meklēt komandu failus @@ -252,9 +252,9 @@ return [ ]; ``` -### Piekļuve konfigurācijai +### Konfigurācijas piekļuve -Ja jums vajadzīga efektīva piekļuve konfigurācijas vērtībām, jūs varat piekļūt tām caur `__construct` metodi vai `app()` metodi. Ir arī svarīgi atzīmēt, ka, ja jums ir `app/config/services.php` fails, šie servisi būs pieejami jūsu komandai. +Ja jums vajadzīga efektīva konfigurācijas vērtību piekļuve, jūs varat piekļūt tām caur `__construct` metodi vai `app()` metodi. Ir arī svarīgi atzīmēt, ka, ja jums ir `app/config/services.php` fails, šie servisi būs pieejami jūsu komandai. ```php public function execute() @@ -271,16 +271,16 @@ public function execute() } ``` -## AI palīglopu apvalki +## AI palīglīdzekļu apvalki -Runway ir daži palīglopu apvalki, kas padara vieglāku AI komandu ģenerēšanu. Jūs varat izmantot `addOption` un `addArgument` veidā, kas šķiet līdzīgs Symfony Console. Tas ir noderīgi, ja izmantojat AI rīkus, lai ģenerētu jūsu komandas. +Lidlaukumam ir daži palīglīdzekļu apvalki, kas atvieglo AI komandu ģenerēšanu. Jūs varat izmantot `addOption` un `addArgument` veidā, kas šķiet līdzīgs Symfony Console. Tas ir noderīgi, ja izmantojat AI rīkus, lai ģenerētu savas komandas. ```php public function __construct(array $config) { parent::__construct('make:example', 'Izveidot piemēru dokumentācijai', $config); - // The mode argument is nullable and defaults to completely optional - $this->addOption('name', 'The name of the example', null); + // Name arguments ir null un pēc noklusējuma pilnībā izvēles + $this->addOption('name', 'Piemēra nosaukums', null); } ``` \ No newline at end of file diff --git a/content/v3/lv/learn/autoloading.md b/content/v3/lv/learn/autoloading.md index 0ba9b7b9..6c92f763 100644 --- a/content/v3/lv/learn/autoloading.md +++ b/content/v3/lv/learn/autoloading.md @@ -2,17 +2,17 @@ ## Pārskats -Autoloading ir PHP koncepts, kurā jūs norādāt direktoriju vai direktorijus, no kuriem ielādēt klases. Tas ir daudz izdevīgāk nekā izmantot `require` vai `include` klašu ielādei. Tas ir arī prasība Composer pakotņu izmantošanai. +Autoloading ir PHP koncepts, kurā jūs norādāt direktoriju vai direktorijas, no kurām ielādēt klases. Tas ir daudz izdevīgāk nekā izmantot `require` vai `include` klases ielādei. Tas ir arī prasība Composer pakotņu izmantošanai. ## Saprašana Pēc noklusējuma jebkura `Flight` klase tiek automātiski autoloadēta jums, pateicoties composer. Tomēr, ja vēlaties autoloadēt savas klases, jūs varat izmantot `Flight::path()` metodi, lai norādītu direktoriju, no kura ielādēt klases. -Autoloadera izmantošana var palīdzēt ievērojami vienkāršot jūsu kodu. Tā vietā, lai faili sāktos ar daudziem `include` vai `require` paziņojumiem augšpusē, lai uztvertu visas tajā failā izmantotās klases, jūs varat dinamiski izsaukt savas klases, un tās tiks iekļautas automātiski. +Autoloadera izmantošana var palīdzēt ievērojami vienkāršot jūsu kodu. Tā vietā, lai faili sāktos ar daudziem `include` vai `require` paziņojumiem augšpusē, lai uztvertu visas klases, kas tiek izmantotas tajā failā, jūs varat dinamiski izsaukt savas klases, un tās tiks iekļautas automātiski. -## Pamatlietojums +## Pamata izmantošana -Pieņemsim, ka mums ir direktoriju koks šāds: +Pieņemsim, ka mums ir direktoriju koka struktūra šāda: ```text # Piemēra ceļš @@ -22,7 +22,7 @@ Pieņemsim, ka mums ir direktoriju koks šāds: │ ├── config │ ├── controllers - satur šī projekta kontrolierus │ ├── translations -│ ├── UTILS - satur klases tikai šai lietojumprogrammai (tas ir visi lielie burti mērķtiecīgi piemēram vēlāk) +│ ├── UTILS - satur klases tikai šai lietojumprogrammai (tas ir visiem lielajiem burtiem mērķtiecīgi piemēram vēlāk) │ └── views └── public └── css @@ -30,9 +30,9 @@ Pieņemsim, ka mums ir direktoriju koks šāds: └── index.php ``` -Jūs varbūt pamanījāt, ka tas ir tāds pats failu struktūra kā šī dokumentācijas vietnei. +Jūs varbūt pamanījāt, ka tā ir tā pati failu struktūra kā šai dokumentācijas vietnei. -Jūs varat norādīt katru direktoriju, no kura ielādēt, šādi: +Jūs varat norādīt katru direktoriju ielādei šādi: ```php @@ -40,7 +40,7 @@ Jūs varat norādīt katru direktoriju, no kura ielādēt, šādi: * public/index.php */ -// Pievienojiet ceļu autoloaderim +// Pievienot ceļu autoloaderam Flight::path(__DIR__.'/../app/controllers/'); Flight::path(__DIR__.'/../app/utils/'); @@ -49,20 +49,20 @@ Flight::path(__DIR__.'/../app/utils/'); * app/controllers/MyController.php */ -// nav nepieciešama vārdu telpa +// nav nepieciešama namespacing -// Visām autoloadētajām klasēm ieteicams būt Pascal Case (katrs vārds ar lielu burtu, bez atstarpēm) +// Visām autoloadētajām klasēm iesaka būt Pascal Case (katrs vārds ar lielajiem burtiem, bez atstarpēm) class MyController { public function index() { - // dariet kaut ko + // izdarīt kaut ko } } ``` -## Vārdu telpas +## Namespaces -Ja jums ir vārdu telpas, tas faktiski kļūst ļoti viegli ieviest. Jums vajadzētu izmantot `Flight::path()` metodi, lai norādītu jūsu lietojumprogrammas saknes direktoriju (nevis dokumenta sakni vai `public/` mapi). +Ja jums ir namespaces, tas patiesībā kļūst ļoti viegli īstenojams. Jums vajadzētu izmantot `Flight::path()` metodi, lai norādītu jūsu lietojumprogrammas saknes direktoriju (nevis dokumenta sakni vai `public/` mapi). ```php @@ -70,34 +70,34 @@ Ja jums ir vārdu telpas, tas faktiski kļūst ļoti viegli ieviest. Jums vajadz * public/index.php */ -// Pievienojiet ceļu autoloaderim +// Pievienot ceļu autoloaderam Flight::path(__DIR__.'/../'); ``` -Tagad tas ir jūsu kontrolieris izskatītos. Skatiet piemēru zemāk, bet pievērsiet uzmanību komentāriem svarīgai informācijai. +Tagad tā izskatās jūsu kontrolieris. Skatiet piemēru zemāk, bet pievērsiet uzmanību komentāriem svarīgai informācijai. ```php /** * app/controllers/MyController.php */ -// vārdu telpas ir nepieciešamas -// vārdu telpas ir tādas pašas kā direktoriju struktūra -// vārdu telpām jāatbilst tāpat kā direktoriju struktūrai -// vārdu telpām un direktorijiem nevar būt apakšsvītras (ja vien nav iestatīts Loader::setV2ClassLoading(false)) +// namespaces ir nepieciešami +// namespaces ir tādi paši kā direktoriju struktūra +// namespaces jāatbilst tā paša reģistra kā direktoriju struktūrai +// namespaces un direktorijām nevar būt apakšsvītras (ja vien nav iestatīts Loader::setV2ClassLoading(false)) namespace app\controllers; -// Visām autoloadētajām klasēm ieteicams būt Pascal Case (katrs vārds ar lielu burtu, bez atstarpēm) -// No 3.7.2 versijas, jūs varat izmantot Pascal_Snake_Case savām klases nosaukumiem, palaižot Loader::setV2ClassLoading(false); +// Visām autoloadētajām klasēm iesaka būt Pascal Case (katrs vārds ar lielajiem burtiem, bez atstarpēm) +// No 3.7.2 versijas jūs varat izmantot Pascal_Snake_Case saviem klases nosaukumiem, izpildot Loader::setV2ClassLoading(false); class MyController { public function index() { - // dariet kaut ko + // izdarīt kaut ko } } ``` -Un ja jūs vēlaties autoloadēt klasi jūsu utils direktorijā, jūs darītu gandrīz to pašu: +Un, ja jūs vēlaties autoloadēt klasi jūsu utils direktorijā, jūs darītu gandrīz to pašu: ```php @@ -105,22 +105,22 @@ Un ja jūs vēlaties autoloadēt klasi jūsu utils direktorijā, jūs darītu ga * app/UTILS/ArrayHelperUtil.php */ -// vārdu telpai jāatbilst direktoriju struktūrai un reģistram (pamaniet, ka UTILS direktorija ir visi lielie burti +// namespace jāatbilst direktoriju struktūrai un reģistram (pamaniet, ka UTILS direktorija ir visi lielie burti // kā failu kokā augstāk) namespace app\UTILS; class ArrayHelperUtil { public function changeArrayCase(array $array) { - // dariet kaut ko + // izdarīt kaut ko } } ``` ## Apakšsvītras klases nosaukumos -No 3.7.2 versijas, jūs varat izmantot Pascal_Snake_Case savām klases nosaukumiem, palaižot `Loader::setV2ClassLoading(false);`. -Tas ļaus izmantot apakšsvītras jūsu klases nosaukumos. +No 3.7.2 versijas jūs varat izmantot Pascal_Snake_Case saviem klases nosaukumiem, izpildot `Loader::setV2ClassLoading(false);`. +Tas ļaus jums izmantot apakšsvītras savos klases nosaukumos. Tas nav ieteicams, bet tas ir pieejams tiem, kam tas ir nepieciešams. ```php @@ -130,7 +130,7 @@ use flight\core\Loader; * public/index.php */ -// Pievienojiet ceļu autoloaderim +// Pievienot ceļu autoloaderam Flight::path(__DIR__.'/../app/controllers/'); Flight::path(__DIR__.'/../app/utils/'); Loader::setV2ClassLoading(false); @@ -139,24 +139,24 @@ Loader::setV2ClassLoading(false); * app/controllers/My_Controller.php */ -// nav nepieciešama vārdu telpa +// nav nepieciešama namespacing class My_Controller { public function index() { - // dariet kaut ko + // izdarīt kaut ko } } ``` ## Skatīt arī - [Routing](/learn/routing) - Kā kartēt maršrutus uz kontrolieriem un renderēt skatus. -- [Why a Framework?](/learn/why-frameworks) - Saprast ieguvumus, izmantojot ietvaru kā Flight. +- [Why a Framework?](/learn/why-frameworks) - Saprastie ietvara kā Flight priekšrocības. ## Traucējummeklēšana -- Ja jūs nevarat saprast, kāpēc jūsu vārdu telpās esošās klases netiek atrastas, atcerieties izmantot `Flight::path()` uz jūsu projekta saknes direktoriju, nevis jūsu `app/` vai `src/` direktoriju vai ekvivalentu. +- Ja jūs nevarat saprast, kāpēc jūsu namespaced klases netiek atrastas, atcerieties izmantot `Flight::path()` uz jūsu projekta saknes direktoriju, nevis jūsu `app/` vai `src/` direktoriju vai ekvivalentu. -### Klase netika atrasta (autoloading nedarbojas) +### Klase nav atrasta (autoloading nedarbojas) Šim var būt pāris iemesli. Zemāk ir daži piemēri, bet pārliecinieties, ka jūs arī apskatāt [autoloading](/learn/autoloading) sadaļu. @@ -166,24 +166,24 @@ Visbiežākais ir tas, ka klases nosaukums neatbilst faila nosaukumam. Ja jums ir klase ar nosaukumu `MyClass`, tad failam jābūt nosauktam `MyClass.php`. Ja jums ir klase ar nosaukumu `MyClass` un fails ir nosaukts `myclass.php` tad autoloader nevarēs to atrast. -#### Nepareiza vārdu telpa -Ja jūs izmantojat vārdu telpas, tad vārdu telpai jāatbilst direktoriju struktūrai. +#### Nepareizs Namespace +Ja jūs izmantojat namespaces, tad namespace jāatbilst direktoriju struktūrai. ```php -// ...kods... +// ...code... -// ja jūsu MyController ir app/controllers direktorijā un tas ir ar vārdu telpu +// ja jūsu MyController ir app/controllers direktorijā un tas ir namespaced // tas nedarbosies. Flight::route('/hello', 'MyController->hello'); // jums jāizvēlas viena no šīm opcijām Flight::route('/hello', 'app\controllers\MyController->hello'); -// vai ja jums ir use paziņojums augšpusē +// vai, ja jums ir use paziņojums augšpusē use app\controllers\MyController; Flight::route('/hello', [ MyController::class, 'hello' ]); -// var arī rakstīt +// arī var būt rakstīts Flight::route('/hello', MyController::class.'->hello'); // arī... Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); @@ -191,14 +191,14 @@ Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); #### `path()` nav definēts -Skeletā lietojumprogrammā tas ir definēts `config.php` failā, bet lai jūsu klases tiktu atrastas, jums jāpārliecinās, ka `path()` +Skeletā lietojumprogrammā tas ir definēts `config.php` failā, bet, lai jūsu klases tiktu atrastas, jums jāpārliecinās, ka `path()` metode ir definēta (droši vien uz jūsu direktorijas sakni) pirms mēģināt to izmantot. ```php -// Pievienojiet ceļu autoloaderim +// Pievienot ceļu autoloaderam Flight::path(__DIR__.'/../'); ``` -## Izmaiņu žurnāls -- v3.7.2 - Jūs varat izmantot Pascal_Snake_Case savām klases nosaukumiem, palaižot `Loader::setV2ClassLoading(false);` +## Changelog +- v3.7.2 - Jūs varat izmantot Pascal_Snake_Case saviem klases nosaukumiem, izpildot `Loader::setV2ClassLoading(false);` - v2.0 - Autoload funkcionalitāte pievienota. \ No newline at end of file diff --git a/content/v3/lv/learn/learn.md b/content/v3/lv/learn/learn.md index 3f224215..c7b4a6ac 100644 --- a/content/v3/lv/learn/learn.md +++ b/content/v3/lv/learn/learn.md @@ -1,4 +1,4 @@ -# Uzzināt Par Flight +# Uzzināt par Flight Flight ir ātrs, vienkāršs, paplašināms ietvars PHP. Tas ir diezgan daudzpusīgs un to var izmantot jebkura veida tīmekļa lietojumprogrammas izveidei. Tas ir izveidots ar vienkāršību prātā un ir uzrakstīts tā, lai būtu viegli saprast un izmantot. @@ -33,7 +33,7 @@ Uzziniet, kā izmantot iebūvēto skata dzinēju, lai renderētu savas HTML veid ### [Drošība](/learn/security) -Uzziniet, kā nodrošināt savu lietojumprogrammu pret izplatītiem drošības draudiem. +Uzziniet, kā aizsargāt savu lietojumprogrammu no izplatītiem drošības draudiem. ### [Konfigurācija](/learn/configuration) @@ -59,17 +59,21 @@ Uzziniet, kā izmantot atkarību injekcijas konteinerus (DIC), lai pārvaldītu ### [Kolekcijas](/learn/collections) -Kolekcijas tiek izmantotas, lai turētu datus un būtu pieejamas kā masīvs vai kā objekts vieglākai izmantošanai. +Kolekcijas tiek izmantotas, lai turētu datus un tās būtu pieejamas kā masīvs vai kā objekts vieglākai izmantošanai. ### [JSON Apvalks](/learn/json) -Tam ir dažas vienkāršas funkcijas, lai kodēšana un dekodēšana jūsu JSON būtu konsekventa. +Šim ir dažas vienkāršas funkcijas, lai jūsu JSON kodēšana un dekodēšana būtu konsekventa. -### [PDO Apvalks](/learn/pdo-wrapper) +### [SimplePdo](/learn/simple-pdo) -PDO dažreiz var radīt vairāk galvassāpju nekā nepieciešams. Šī vienkāršā apvalka klase var ievērojami atvieglot mijiedarbību ar jūsu datubāzi. +PDO dažreiz var radīt vairāk galvassāpju nekā nepieciešams. SimplePdo ir moderna PDO palīgklašu ar ērtām metodēm, piemēram, `insert()`, `update()`, `delete()` un `transaction()`, lai datubāzes operācijas padarītu daudz vieglākas. -### [Augšupielādētā Faila Apstrādātājs](/learn/uploaded-file) +### [PdoWrapper](/learn/pdo-wrapper) (Novecojis) + +Sākotnējais PDO apvalks ir novecojis no v3.18.0. Lūdzu, izmantojiet [SimplePdo](/learn/simple-pdo) tā vietā. + +### [Augšupielādētā Faila Pārvaldnieks](/learn/uploaded-file) Vienkārša klase, lai palīdzētu pārvaldīt augšupielādētos failus un pārvietot tos uz pastāvīgu atrašanās vietu. @@ -77,21 +81,21 @@ Vienkārša klase, lai palīdzētu pārvaldīt augšupielādētos failus un pār ### [Kāpēc Ietvars?](/learn/why-frameworks) -Šeit ir īss raksts par to, kāpēc jums vajadzētu izmantot ietvaru. Ir laba ideja saprast ietvara izmantošanas priekšrocības, pirms jūs sākat to izmantot. +Šeit ir īss raksts par to, kāpēc jums vajadzētu izmantot ietvaru. Ir laba ideja saprast ietvara izmantošanas priekšrocības, pirms sākat to izmantot. -Turklāt ir izveidots lielisks mācību ceļvedis no [@lubiana](https://git.php.fail/lubiana). Lai gan tas neiet dziļi detaļās par Flight specifiski, +Turklāt ir izveidots lielisks mācību ceļvedis no [@lubiana](https://git.php.fail/lubiana). Lai gan tas neiet dziļi Flight specifiski, šis ceļvedis palīdzēs jums saprast dažus no galvenajiem konceptiem, kas saistīti ar ietvaru, un kāpēc tie ir izdevīgi izmantot. Jūs varat atrast mācību ceļvedi [šeit](https://git.php.fail/lubiana/no-framework-tutorial/src/branch/master/README.md). -### [Flight Salīdzinājumā Ar Citiem Ietvariem](/learn/flight-vs-another-framework) +### [Flight Salīdzinājumā ar Citiem Ietvariem](/learn/flight-vs-another-framework) -Ja jūs migrējat no cita ietvara, piemēram, Laravel, Slim, Fat-Free vai Symfony uz Flight, šī lapa palīdzēs jums saprast atšķirības starp tiem. +Ja jūs migrējat no cita ietvara, piemēram, Laravel, Slim, Fat-Free vai Symfony uz Flight, šī lapa palīdzēs jums saprast atšķirības starp abiem. ## Citi Temati ### [Vienības Testēšana](/learn/unit-testing) -Sekojiet šim ceļvedim, lai uzzinātu, kā veikt vienības testēšanu jūsu Flight kodam, lai tas būtu stingrs kā klints. +Sekojiet šim ceļvedim, lai uzzinātu, kā veikt vienības testēšanu savam Flight kodam, lai tas būtu stingrs kā klints. ### [AI & Izstrādātāja Pieredze](/learn/ai) @@ -99,4 +103,4 @@ Uzziniet, kā Flight darbojas ar AI rīkiem un modernām izstrādātāja darba p ### [Migrēšana v2 -> v3](/learn/migrating-to-v3) -Atpakaļsaderība lielākoties ir saglabāta, bet ir dažas izmaiņas, par kurām jums vajadzētu zināt, migrējot no v2 uz v3. \ No newline at end of file +Atpakaļsaderība lielākoties ir saglabāta, bet ir daži izmaiņas, par kurām jums vajadzētu zināt, migrējot no v2 uz v3. \ No newline at end of file diff --git a/content/v3/lv/learn/pdo_wrapper.md b/content/v3/lv/learn/pdo_wrapper.md index ab720de3..47f3bc92 100644 --- a/content/v3/lv/learn/pdo_wrapper.md +++ b/content/v3/lv/learn/pdo_wrapper.md @@ -1,18 +1,22 @@ -# PdoWrapper PDO Palīgdarbības klase +# PdoWrapper PDO Palīdze ģenerators + +> **BRĪDINĀJUMS** +> +> **Novecojis:** `PdoWrapper` ir novecojis kopš Flight v3.18.0. Tas netiks noņemts nākamajā versijā, bet tiks uzturēts atpakaļsaderībai. Lūdzu, izmantojiet [SimplePdo](/learn/simple-pdo) tā vietā, kas piedāvā tādu pašu funkcionalitāti plus papildu palīgmēģus biežām datubāzes operācijām. ## Pārskats -`PdoWrapper` klase Flight ir draudzīgs palīgs darbam ar datubāzēm, izmantojot PDO. Tā vienkāršo izplatītās datubāzes uzdevumus, pievieno dažas ērtas metodes rezultātu iegūšanai un atgriež rezultātus kā [Collections](/learn/collections) vieglai piekļuvei. Tā arī atbalsta vaicājumu reģistrēšanu un lietotnes veiktspējas uzraudzību (APM) sarežģītām lietošanas situācijām. +`PdoWrapper` klase Flight ir draudzīgs palīgs darbam ar datubāzēm, izmantojot PDO. Tā vienkāršo izplatītās datubāzes uzdevumus, pievieno dažas ērtas metodes rezultātu iegūšanai un atgriež rezultātus kā [Collections](/learn/collections) vieglai piekļuvei. Tā arī atbalsta vaicājumu reģistrēšanu un lietojumprogrammas veiktspējas uzraudzību (APM) sarežģītiem gadījumiem. ## Saprašana -Darbs ar datubāzēm PHP var būt nedaudz verbāls, īpaši, izmantojot PDO tieši. `PdoWrapper` paplašina PDO un pievieno metodes, kas padara vaicājumu veikšanu, rezultātu iegūšanu un apstrādi daudz vieglāku. Tā vietā, lai žonglētu ar sagatavotiem paziņojumiem un iegūšanas režīmiem, jūs iegūstat vienkāršas metodes izplatītiem uzdevumiem, un katra rindiņa tiek atgriezta kā Collection, tāpēc jūs varat izmantot masīva vai objekta notāciju. +Darbs ar datubāzēm PHP var būt nedaudz verbāls, īpaši, izmantojot PDO tieši. `PdoWrapper` paplašina PDO un pievieno metodes, kas padara vaicājumu veikšanu, rezultātu iegūšanu un apstrādi daudz vieglāku. Tā vietā, lai žonglētu ar sagatavotiem paziņojumiem un iegūšanas režīmiem, jūs saņemat vienkāršas metodes izplatītiem uzdevumiem, un katra rindiņa tiek atgriezta kā Collection, tāpēc jūs varat izmantot masīva vai objekta notāciju. -Jūs varat reģistrēt `PdoWrapper` kā koplietojamu servisu Flight un pēc tam izmantot to jebkur savā lietotnē caur `Flight::db()`. +Jūs varat reģistrēt `PdoWrapper` kā kopīgu servisu Flight, un tad izmantot to jebkur savā lietojumprogrammā caur `Flight::db()`. -## Pamatlietošana +## Pamata Izmantošana -### PDO palīgdarbības reģistrēšana +### Reģistrēšana PDO Palīgam Vispirms reģistrējiet `PdoWrapper` klasi ar Flight: @@ -29,13 +33,13 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ Tagad jūs varat izmantot `Flight::db()` jebkur, lai iegūtu savienojumu ar datubāzi. -### Vaicājumu izpildīšana +### Vaicājumu Izpilde #### `runQuery()` `function runQuery(string $sql, array $params = []): PDOStatement` -Izmantojiet to INSERT, UPDATE vai kad vēlaties manuāli iegūt rezultātus: +Izmantojiet to INSERT, UPDATE vai kad vēlaties iegūt rezultātus manuāli: ```php $db = Flight::db(); @@ -79,7 +83,7 @@ echo $user->name; `function fetchAll(string $sql, array $params = []): array` -Iegūstiet visas rindiņas kā Collection masīvu: +Iegūstiet visas rindiņas kā Collections masīvu: ```php $users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); @@ -90,7 +94,7 @@ foreach ($users as $user) { } ``` -### Izmantojot `IN()` aizstājējus +### Izmantojot `IN()` Vietu Turētājus Jūs varat izmantot vienu `?` IN() klauzulā un nodot masīvu vai komatiem atdalītu virkni: @@ -101,66 +105,66 @@ $users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); $users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", ['1,2,3']); ``` -## Uzlabota lietošana +## Uzlabota Izmantošana -### Vaicājumu reģistrēšana & APM +### Vaicājumu Reģistrēšana & APM -Ja vēlaties izsekot vaicājumu veiktspēju, iespējiet APM izsekošanu reģistrēšanas laikā: +Ja vēlaties izsekot vaicājuma veiktspēju, iespējiet APM izsekošanu reģistrējot: ```php Flight::register('db', \flight\database\PdoWrapper::class, [ - 'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [/* options */], true // pēdējais parametrs iespējina APM + 'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [/* options */], true // pēdējais params iespējina APM ]); ``` -Pēc vaicājumu izpildes jūs varat manuāli reģistrēt tos, bet APM tos reģistrēs automātiski, ja iespējots: +Pēc vaicājumu izpildes jūs varat reģistrēt tos manuāli, bet APM tos reģistrēs automātiski, ja iespējots: ```php Flight::db()->logQueries(); ``` -Tas izraisīs notikumu (`flight.db.queries`) ar savienojuma un vaicājumu metrikiem, ko jūs varat klausīties, izmantojot Flight notikumu sistēmu. +Tas izraisīs notikumu (`flight.db.queries`) ar savienojuma un vaicājuma metrikiem, ko jūs varat klausīties, izmantojot Flight notikumu sistēmu. -### Pilns piemērs +### Pilns Piemērs ```php Flight::route('/users', function () { - // Iegūstiet visus lietotājus + // Iegūt visus lietotājus $users = Flight::db()->fetchAll('SELECT * FROM users'); - // Plūsma visiem lietotājiem + // Straumēt visus lietotājus $statement = Flight::db()->runQuery('SELECT * FROM users'); while ($user = $statement->fetch()) { echo $user['name']; } - // Iegūstiet vienu lietotāju + // Iegūt vienu lietotāju $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); - // Iegūstiet vienu vērtību + // Iegūt vienu vērtību $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); - // Īpašā IN() sintakse + // Īpaša IN() sintakse $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', ['1,2,3,4,5']); - // Ievietojiet jaunu lietotāju + // Ievietot jaunu lietotāju Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']); $insert_id = Flight::db()->lastInsertId(); - // Atjauniniet lietotāju + // Atjaunināt lietotāju Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]); - // Dzēsiet lietotāju + // Dzēst lietotāju Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]); - // Iegūstiet skarto rindiņu skaitu + // Iegūt skarto rindu skaitu $statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']); $affected_rows = $statement->rowCount(); }); ``` -## Skatīt arī +## Skatīt Arī - [Collections](/learn/collections) - Uzziniet, kā izmantot Collection klasi vieglai datu piekļuvei. @@ -170,6 +174,6 @@ Flight::route('/users', function () { - Visas rindiņas tiek atgrieztas kā Collections—ja vajadzīgs vienkāršs masīvs, izmantojiet `$collection->getData()`. - IN (?) vaicājumiem pārliecinieties, ka nododiet masīvu vai komatiem atdalītu virkni. -## Izmaiņu žurnāls +## Izmaiņu Žurnāls -- v3.2.0 - Sākotnējā PdoWrapper izlaišana ar pamata vaicājumu un iegūšanas metodēm. \ No newline at end of file +- v3.2.0 - Sākotnējā PdoWrapper izlaišana ar pamata vaicājuma un iegūšanas metodēm. \ No newline at end of file diff --git a/content/v3/lv/learn/simple_pdo.md b/content/v3/lv/learn/simple_pdo.md new file mode 100644 index 00000000..a45dc914 --- /dev/null +++ b/content/v3/lv/learn/simple_pdo.md @@ -0,0 +1,320 @@ +# SimplePdo PDO Palīdze Ģimene + +## Pārskats + +`SimplePdo` klase Flight ir moderna, funkcijām bagāta palīdze darbam ar datubāzēm, izmantojot PDO. Tā paplašina `PdoWrapper` un pievieno ērtas palīgmēģenēm izplatītām datubāzes operācijām, piemēram, `insert()`, `update()`, `delete()` un transakcijām. Tā vienkāršo datubāzes uzdevumus, atgriež rezultātus kā [Collections](/learn/collections) vieglai piekļuvei un atbalsta vaicājumu žurnālveidošanu un lietojumprogrammas veiktspējas uzraudzību (APM) sarežģītām lietošanas situācijām. + +## Saprašana + +`SimplePdo` klase ir izstrādāta, lai padarītu darbu ar datubāzēm PHP daudz vieglāku. Tā vietā, lai žonglētu ar sagatavotiem paziņojumiem, iegūšanas režīmiem un verbāliem SQL operācijām, jūs saņemat tīras, vienkāršas metodes izplatītiem uzdevumiem. Katra rindiņa tiek atgriezta kā Collection, tāpēc jūs varat izmantot gan masīva notāciju (`$row['name']`), gan objekta notāciju (`$row->name`). + +Šī klase ir `PdoWrapper` pārklājums, kas nozīmē, ka tā ietver visu `PdoWrapper` funkcionalitāti plus papildu palīgmēģenes, kas padara jūsu kodu tīrāku un vieglāk uzturamu. Ja jūs pašlaik izmantojat `PdoWrapper`, pāreja uz `SimplePdo` ir vienkārša, jo tā paplašina `PdoWrapper`. + +Jūs varat reģistrēt `SimplePdo` kā kopīgu servisu Flight, un tad izmantot to jebkur savā lietojumprogrammā caur `Flight::db()`. + +## Pamata Lietošana + +### Reģistrēšana SimplePdo + +Vispirms reģistrējiet `SimplePdo` klasi Flight: + +```php +Flight::register('db', \flight\database\SimplePdo::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 + ] +]); +``` + +> **PIEZĪME** +> +> Ja jūs ne norādāt `PDO::ATTR_DEFAULT_FETCH_MODE`, `SimplePdo` automātiski iestatīs to uz `PDO::FETCH_ASSOC` jūsu vietā. + +Tagad jūs varat izmantot `Flight::db()` jebkur, lai iegūtu savienojumu ar datubāzi. + +### Vaicājumu Izpilde + +#### `runQuery()` + +`function runQuery(string $sql, array $params = []): PDOStatement` + +Izmantojiet to INSERT, UPDATE vai kad vēlaties pašrocīgi iegūt rezultātus: + +```php +$db = Flight::db(); +$statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']); +while ($row = $statement->fetch()) { + // $row ir masīvs +} +``` + +Jūs varat izmantot to arī rakstīšanai: + +```php +$db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); +$db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]); +``` + +#### `fetchField()` + +`function fetchField(string $sql, array $params = []): mixed` + +Iegūstiet vienu vērtību no datubāzes: + +```php +$count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']); +``` + +#### `fetchRow()` + +`function fetchRow(string $sql, array $params = []): ?Collection` + +Iegūstiet vienu rindiņu kā Collection (masīva/objekta piekļuve): + +```php +$user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); +echo $user['name']; +// vai +echo $user->name; +``` + +> **PADOMS** +> +> `SimplePdo` automātiski pievieno `LIMIT 1` vaicājumiem `fetchRow()`, ja tas vēl nav klāt, padarot jūsu vaicājumus efektīvākus. + +#### `fetchAll()` + +`function fetchAll(string $sql, array $params = []): array` + +Iegūstiet visas rindiņas kā Collection masīvu: + +```php +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); +foreach ($users as $user) { + echo $user['name']; + // vai + echo $user->name; +} +``` + +#### `fetchColumn()` + +`function fetchColumn(string $sql, array $params = []): array` + +Iegūstiet vienu kolonnu kā masīvu: + +```php +$ids = Flight::db()->fetchColumn("SELECT id FROM users WHERE active = ?", [1]); +// Atgriež: [1, 2, 3, 4, 5] +``` + +#### `fetchPairs()` + +`function fetchPairs(string $sql, array $params = []): array` + +Iegūstiet rezultātus kā atslēgu-vērtību pārus (pirmā kolonna kā atslēga, otrā kā vērtība): + +```php +$userNames = Flight::db()->fetchPairs("SELECT id, name FROM users"); +// Atgriež: [1 => 'John', 2 => 'Jane', 3 => 'Bob'] +``` + +### Izmantojot `IN()` Vietas Turētājus + +Jūs varat izmantot vienu `?` IN() klauzulā un nodot masīvu: + +```php +$ids = [1, 2, 3]; +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); +``` + +## Palīgmēģenes + +Viens no galvenajiem `SimplePdo` priekšrocībām salīdzinājumā ar `PdoWrapper` ir ērtu palīgmēģeņu pievienošana izplatītām datubāzes operācijām. + +### `insert()` + +`function insert(string $table, array $data): string` + +Ievietojiet vienu vai vairākas rindiņas un atgrieziet pēdējo ievietošanas ID. + +**Viena ievietošana:** + +```php +$id = Flight::db()->insert('users', [ + 'name' => 'John', + 'email' => 'john@example.com' +]); +``` + +**Masveida ievietošana:** + +```php +$id = Flight::db()->insert('users', [ + ['name' => 'John', 'email' => 'john@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'], +]); +``` + +### `update()` + +`function update(string $table, array $data, string $where, array $whereParams = []): int` + +Atjauniniet rindiņas un atgrieziet skarto rindiņu skaitu: + +```php +$affected = Flight::db()->update( + 'users', + ['name' => 'Jane', 'email' => 'jane@example.com'], + 'id = ?', + [1] +); +``` + +> **PIEZĪME** +> +> SQLite `rowCount()` atgriež skaitu rindiņu, kur dati patiešām mainījās. Ja jūs atjauninat rindiņu ar tām pašām vērtībām, kas tai jau ir, `rowCount()` atgriezīs 0. Tas atšķiras no MySQL uzvedības, izmantojot `PDO::MYSQL_ATTR_FOUND_ROWS`. + +### `delete()` + +`function delete(string $table, string $where, array $whereParams = []): int` + +Dzēsiet rindiņas un atgrieziet dzēsto rindiņu skaitu: + +```php +$deleted = Flight::db()->delete('users', 'id = ?', [1]); +``` + +### `transaction()` + +`function transaction(callable $callback): mixed` + +Izpildiet atsaukumu transakcijas ietvaros. Transakcija automātiski apstiprina veiksmīgos gadījumos vai atgriežas kļūdas gadījumā: + +```php +$result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John']); + $db->insert('logs', ['action' => 'user_created']); + return $db->lastInsertId(); +}); +``` + +Ja jebkura izņēmuma tiek mestas atsaukuma ietvaros, transakcija automātiski atgriežas un izņēmums tiek atkārtoti mestas. + +## Padziļinātā Lietošana + +### Vaicājumu Žurnālveidošana & APM + +Ja vēlaties izsekot vaicājuma veiktspēju, iespējiet APM izsekošanu reģistrēšanas laikā: + +```php +Flight::register('db', \flight\database\SimplePdo::class, [ + 'mysql:host=localhost;dbname=cool_db_name', + 'user', + 'pass', + [/* PDO opcijas */], + [ + 'trackApmQueries' => true, + 'maxQueryMetrics' => 1000 + ] +]); +``` + +Pēc vaicājumu izpildes jūs varat žurnālveidot tos manuāli, bet APM tos žurnālveidos automātiski, ja iespējots: + +```php +Flight::db()->logQueries(); +``` + +Tas izraisīs notikumu (`flight.db.queries`) ar savienojuma un vaicājuma metrikiem, ko jūs varat klausīties, izmantojot Flight notikumu sistēmu. + +### Pilns Piemērs + +```php +Flight::route('/users', function () { + // Iegūt visus lietotājus + $users = Flight::db()->fetchAll('SELECT * FROM users'); + + // Straumēt visus lietotājus + $statement = Flight::db()->runQuery('SELECT * FROM users'); + while ($user = $statement->fetch()) { + echo $user['name']; + } + + // Iegūt vienu lietotāju + $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); + + // Iegūt vienu vērtību + $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); + + // Iegūt vienu kolonnu + $ids = Flight::db()->fetchColumn('SELECT id FROM users'); + + // Iegūt atslēgu-vērtību pārus + $userNames = Flight::db()->fetchPairs('SELECT id, name FROM users'); + + // Īpaša IN() sintakse + $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); + + // Ievietot jaunu lietotāju + $id = Flight::db()->insert('users', [ + 'name' => 'Bob', + 'email' => 'bob@example.com' + ]); + + // Masveida ievietošana lietotājiem + Flight::db()->insert('users', [ + ['name' => 'Bob', 'email' => 'bob@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'] + ]); + + // Atjaunināt lietotāju + $affected = Flight::db()->update('users', ['name' => 'Bob'], 'id = ?', [123]); + + // Dzēst lietotāju + $deleted = Flight::db()->delete('users', 'id = ?', [123]); + + // Izmantot transakciju + $result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John', 'email' => 'john@example.com']); + $db->insert('audit_log', ['action' => 'user_created']); + return $db->lastInsertId(); + }); +}); +``` + +## Migrēšana no PdoWrapper + +Ja jūs pašlaik izmantojat `PdoWrapper`, migrēšana uz `SimplePdo` ir vienkārša: + +1. **Atjauniniet savu reģistrāciju:** + ```php + // Vecais + Flight::register('db', \flight\database\PdoWrapper::class, [ /* ... */ ]); + + // Jaunais + Flight::register('db', \flight\database\SimplePdo::class, [ /* ... */ ]); + ``` + +2. **Visas esošās `PdoWrapper` metodes darbojas `SimplePdo`** - Nav laušanas izmaiņu. Jūsu esošais kods turpinās darboties. + +3. **Pēc izvēles izmantojiet jaunas palīgmēģenes** - Sāciet izmantot `insert()`, `update()`, `delete()` un `transaction()`, lai vienkāršotu savu kodu. + +## Skatīt Arī + +- [Collections](/learn/collections) - Uzziniet, kā izmantot Collection klasi vieglai datu piekļuvei. +- [PdoWrapper](/learn/pdo-wrapper) - Mantotā PDO palīdze klase (novecojusi). + +## Traucējummeklēšana + +- Ja saņemat kļūdu par datubāzes savienojumu, pārbaudiet savu DSN, lietotājvārdu, paroli un opcijas. +- Visas rindiņas tiek atgrieztas kā Collections—ja vajag vienkāršu masīvu, izmantojiet `$collection->getData()`. +- IN (?) vaicājumiem pārliecinieties, ka nodod masīvu. +- Ja rodas atmiņas problēmas ar vaicājumu žurnālveidošanu garos procesos, pielāgojiet `maxQueryMetrics` opciju. + +## Izmaiņu Žurnāls + +- v3.18.0 - Sākotnējā SimplePdo izlaišana ar palīgmēģenēm insert, update, delete un transakcijām. \ No newline at end of file diff --git a/content/v3/pt/awesome-plugins/awesome_plugins.md b/content/v3/pt/awesome-plugins/awesome_plugins.md index f5f1940b..6d3b57b2 100644 --- a/content/v3/pt/awesome-plugins/awesome_plugins.md +++ b/content/v3/pt/awesome-plugins/awesome_plugins.md @@ -12,43 +12,43 @@ A documentação de API é crucial para qualquer API. Ela ajuda os desenvolvedor ## Monitoramento de Desempenho de Aplicação (APM) O Monitoramento de Desempenho de Aplicação (APM) é crucial para qualquer aplicação. Ele ajuda você a entender como sua aplicação está se saindo e onde estão os gargalos. Existem vários ferramentas APM que podem ser usadas com Flight. -- oficial [flightphp/apm](/awesome-plugins/apm) - Flight APM é uma biblioteca APM simples que pode ser usada para monitorar suas aplicações Flight. Ela pode ser usada para monitorar o desempenho da sua aplicação e ajudá-lo a identificar gargalos. +- oficial [flightphp/apm](/awesome-plugins/apm) - Flight APM é uma biblioteca APM simples que pode ser usada para monitorar suas aplicações Flight. Pode ser usada para monitorar o desempenho da sua aplicação e ajudá-lo a identificar gargalos. -## Async +## Assíncrono -Flight já é um framework rápido, mas adicionar um motor turbo a ele torna tudo mais divertido (e desafiador)! +Flight já é um framework rápido, mas adicionar um motor turbo nele torna tudo mais divertido (e desafiador)! -- [flightphp/async](/awesome-plugins/async) - Biblioteca Async oficial do Flight. Esta biblioteca é uma maneira simples de adicionar processamento assíncrono à sua aplicação. Ela usa Swoole/Openswoole sob o capô para fornecer uma maneira simples e eficaz de executar tarefas de forma assíncrona. +- [flightphp/async](/awesome-plugins/async) - Biblioteca Async oficial do Flight. Esta biblioteca é uma forma simples de adicionar processamento assíncrono à sua aplicação. Ela usa Swoole/Openswoole sob o capô para fornecer uma forma simples e eficaz de executar tarefas de forma assíncrona. ## Autorização/Permissões Autorização e Permissões são cruciais para qualquer aplicação que exija controles para quem pode acessar o quê. -- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca de Permissões oficial do Flight. Esta biblioteca é uma maneira simples de adicionar permissões em nível de usuário e aplicação à sua aplicação. +- oficial [flightphp/permissions](/awesome-plugins/permissions) - Biblioteca de Permissões oficial do Flight. Esta biblioteca é uma forma simples de adicionar permissões em nível de usuário e aplicação à sua aplicação. ## Autenticação A autenticação é essencial para aplicações que precisam verificar a identidade do usuário e proteger endpoints de API. -- [firebase/php-jwt](/awesome-plugins/jwt) - Biblioteca JSON Web Token (JWT) para PHP. Uma maneira simples e segura de implementar autenticação baseada em tokens em suas aplicações Flight. Perfeita para autenticação de API stateless, proteção de rotas com middleware e implementação de fluxos de autorização no estilo OAuth. +- [firebase/php-jwt](/awesome-plugins/jwt) - Biblioteca JSON Web Token (JWT) para PHP. Uma forma simples e segura de implementar autenticação baseada em tokens em suas aplicações Flight. Perfeita para autenticação de API stateless, proteção de rotas com middleware e implementação de fluxos de autorização no estilo OAuth. ## Cache -O cache é uma ótima maneira de acelerar sua aplicação. Existem várias bibliotecas de cache que podem ser usadas com Flight. +O cache é uma ótima forma de acelerar sua aplicação. Existem várias bibliotecas de cache que podem ser usadas com Flight. -- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Classe de cache em arquivo PHP leve, simples e independente +- oficial [flightphp/cache](/awesome-plugins/php-file-cache) - Classe de cache em arquivo PHP leve, simples e standalone ## CLI -Aplicações CLI são uma ótima maneira de interagir com sua aplicação. Você pode usá-las para gerar controladores, exibir todas as rotas e mais. +Aplicações CLI são uma ótima forma de interagir com sua aplicação. Você pode usá-las para gerar controladores, exibir todas as rotas e mais. - oficial [flightphp/runway](/awesome-plugins/runway) - Runway é uma aplicação CLI que ajuda você a gerenciar suas aplicações Flight. ## Cookies -Cookies são uma ótima maneira de armazenar pequenos pedaços de dados no lado do cliente. Eles podem ser usados para armazenar preferências do usuário, configurações da aplicação e mais. +Cookies são uma ótima forma de armazenar pequenos pedaços de dados no lado do cliente. Eles podem ser usados para armazenar preferências de usuário, configurações de aplicação e mais. -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie é uma biblioteca PHP que fornece uma maneira simples e eficaz de gerenciar cookies. +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie é uma biblioteca PHP que fornece uma forma simples e eficaz de gerenciar cookies. ## Depuração @@ -59,15 +59,16 @@ A depuração é crucial quando você está desenvolvendo em seu ambiente local. ## Bancos de Dados -Bancos de dados são o núcleo da maioria das aplicações. É assim que você armazena e recupera dados. Algumas bibliotecas de banco de dados são simplesmente wrappers para escrever consultas e outras são ORMs completos. +Bancos de dados são o núcleo da maioria das aplicações. É assim que você armazena e recupera dados. Algumas bibliotecas de banco de dados são simplesmente wrappers para escrever consultas e algumas são ORMs completos. -- oficial [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO oficial do Flight que faz parte do núcleo. Este é um wrapper simples para ajudar a simplificar o processo de escrever consultas e executá-las. Não é um ORM. +- oficial [flightphp/core SimplePdo](/learn/simple-pdo) - Auxiliar PDO oficial do Flight que faz parte do núcleo. Este é um wrapper moderno com métodos auxiliares convenientes como `insert()`, `update()`, `delete()` e `transaction()` para simplificar operações de banco de dados. Todos os resultados são retornados como Collections para acesso flexível a arrays/objetos. Não é um ORM, apenas uma forma melhor de trabalhar com PDO. +- deprecado [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO oficial do Flight que faz parte do núcleo (deprecado a partir da v3.18.0). Use SimplePdo em vez disso. - oficial [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord oficial do Flight. Ótima biblioteca pequena para recuperar e armazenar dados facilmente em seu banco de dados. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin para rastrear todas as alterações de banco de dados para seu projeto. ## Criptografia -A criptografia é crucial para qualquer aplicação que armazena dados sensíveis. Criptografar e descriptografar os dados não é terrivelmente difícil, mas armazenar corretamente a chave de criptografia [pode](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [ser](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difícil](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). O mais importante é nunca armazenar sua chave de criptografia em um diretório público ou commitá-la em seu repositório de código. +A criptografia é crucial para qualquer aplicação que armazena dados sensíveis. Criptografar e descriptografar os dados não é terrivelmente difícil, mas armazenar adequadamente a chave de criptografia [pode](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [ser](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [difícil](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). O mais importante é nunca armazenar sua chave de criptografia em um diretório público ou commitá-la em seu repositório de código. - [defuse/php-encryption](/awesome-plugins/php-encryption) - Esta é uma biblioteca que pode ser usada para criptografar e descriptografar dados. Começar a usar é bastante simples para começar a criptografar e descriptografar dados. @@ -75,7 +76,7 @@ A criptografia é crucial para qualquer aplicação que armazena dados sensívei Filas de tarefas são realmente úteis para processar tarefas de forma assíncrona. Isso pode ser enviar e-mails, processar imagens ou qualquer coisa que não precise ser feita em tempo real. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue é uma biblioteca que pode ser usada para processar tarefas de forma assíncrona. Ela pode ser usada com beanstalkd, MySQL/MariaDB, SQLite e PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue é uma biblioteca que pode ser usada para processar tarefas de forma assíncrona. Pode ser usada com beanstalkd, MySQL/MariaDB, SQLite e PostgreSQL. ## Sessão @@ -84,12 +85,12 @@ Sessões não são realmente úteis para APIs, mas para construir uma aplicaçã - oficial [flightphp/session](/awesome-plugins/session) - Biblioteca de Sessão oficial do Flight. Esta é uma biblioteca de sessão simples que pode ser usada para armazenar e recuperar dados de sessão. Ela usa o manipulador de sessão integrado do PHP. - [Ghostff/Session](/awesome-plugins/ghost-session) - Gerenciador de Sessão PHP (não bloqueante, flash, segmento, criptografia de sessão). Usa PHP open_ssl para criptografia/descriptografia opcional de dados de sessão. -## Templating +## Modelagem -O templating é o núcleo de qualquer aplicação web com uma UI. Existem vários motores de templating que podem ser usados com Flight. +A modelagem é o núcleo de qualquer aplicação web com uma UI. Existem vários motores de modelagem que podem ser usados com Flight. -- deprecado [flightphp/core View](/learn#views) - Este é um motor de templating muito básico que faz parte do núcleo. Não é recomendado usá-lo se você tiver mais de algumas páginas em seu projeto. -- [latte/latte](/awesome-plugins/latte) - Latte é um motor de templating completo que é muito fácil de usar e se sente mais próximo de uma sintaxe PHP do que Twig ou Smarty. Também é muito fácil de estender e adicionar seus próprios filtros e funções. +- deprecado [flightphp/core View](/learn#views) - Este é um motor de modelagem muito básico que faz parte do núcleo. Não é recomendado usá-lo se você tiver mais do que algumas páginas em seu projeto. +- [latte/latte](/awesome-plugins/latte) - Latte é um motor de modelagem completo que é muito fácil de usar e se sente mais próximo da sintaxe PHP do que Twig ou Smarty. Também é muito fácil de estender e adicionar seus próprios filtros e funções. - [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate é um poderoso motor de template PHP com compilação de assets, herança de templates e processamento de variáveis. Recursos incluem minificação automática de CSS/JS, cache, codificação Base64 e integração opcional com o framework Flight PHP. ## Integração com WordPress diff --git a/content/v3/pt/awesome-plugins/jwt.md b/content/v3/pt/awesome-plugins/jwt.md index 750e89b8..f09bbfb9 100644 --- a/content/v3/pt/awesome-plugins/jwt.md +++ b/content/v3/pt/awesome-plugins/jwt.md @@ -1,24 +1,24 @@ -# Firebase JWT - Autenticação com JSON Web Token para Flight +# Firebase JWT - Autenticação com JSON Web Token -JWT (JSON Web Tokens) são uma forma compacta e segura para URLs de representar reivindicações entre sua aplicação e um cliente. Eles são perfeitos para autenticação de API stateless — sem necessidade de armazenamento de sessão no lado do servidor! Este guia mostra como integrar [Firebase JWT](https://github.com/firebase/php-jwt) com Flight para autenticação segura baseada em tokens. +JWT (JSON Web Tokens) são uma forma compacta e segura para URLs de representar reivindicações entre sua aplicação e um cliente. Eles são perfeitos para autenticação de API sem estado — sem necessidade de armazenamento de sessão no lado do servidor! Este guia mostra como integrar [Firebase JWT](https://github.com/firebase/php-jwt) com Flight para autenticação segura baseada em tokens. Visite o [repositório no Github](https://github.com/firebase/php-jwt) para documentação completa e detalhes. ## O que é JWT? Um JSON Web Token é uma string que contém três partes: -1. **Header**: Metadados sobre o token (algoritmo, tipo) -2. **Payload**: Seus dados (ID do usuário, papéis, expiração, etc.) -3. **Signature**: Assinatura criptográfica para verificar a autenticidade +1. **Cabeçalho**: Metadados sobre o token (algoritmo, tipo) +2. **Carga útil**: Seus dados (ID do usuário, papéis, expiração, etc.) +3. **Assinatura**: Assinatura criptográfica para verificar a autenticidade -Exemplo de JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (parece gibberish, mas é dados estruturados!) +Exemplo de JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (parece gibberish, mas é dado estruturado!) ### Por que Usar JWT? -- **Stateless**: Não é necessário armazenamento de sessão no lado do servidor — perfeito para microsserviços e APIs -- **Escalável**: Funciona bem com balanceadores de carga, pois não há requisito de afinidade de sessão +- **Sem estado**: Não é necessário armazenamento de sessão no lado do servidor — perfeito para microsserviços e APIs +- **Escalável**: Funciona muito bem com balanceadores de carga, pois não há requisito de afinidade de sessão - **Cross-Domain**: Pode ser usado em diferentes domínios e serviços -- **Amigável para Mobile**: Ótimo para apps móveis onde cookies podem não funcionar bem +- **Amigável para Mobile**: Ótimo para aplicativos móveis onde cookies podem não funcionar bem - **Padronizado**: Abordagem padrão da indústria (RFC 7519) ## Instalação @@ -57,7 +57,7 @@ try { $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); echo "User ID: " . $decoded->user_id; } catch (Exception $e) { - echo "Invalid token: " . $e->getMessage(); + echo "Token inválido: " . $e->getMessage(); } ``` @@ -89,14 +89,14 @@ class JwtMiddleware { public function before(array $params) { $authHeader = $this->app->request()->getHeader('Authorization'); - // Verifique se o header de autorização existe + // Verifique se o cabeçalho Authorization existe if (empty($authHeader)) { - $this->app->jsonHalt(['error' => 'No authorization token provided'], 401); + $this->app->jsonHalt(['error' => 'Nenhum token de autorização fornecido'], 401); } // Extraia o token do formato "Bearer " if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { - $this->app->jsonHalt(['error' => 'Invalid authorization format. Use: Bearer '], 401); + $this->app->jsonHalt(['error' => 'Formato de autorização inválido. Use: Bearer '], 401); } $jwt = $matches[1]; @@ -109,11 +109,11 @@ class JwtMiddleware { $this->app->request()->data->user = $decoded; } catch (ExpiredException $e) { - $this->app->jsonHalt(['error' => 'Token has expired'], 401); + $this->app->jsonHalt(['error' => 'Token expirou'], 401); } catch (SignatureInvalidException $e) { - $this->app->jsonHalt(['error' => 'Invalid token signature'], 401); + $this->app->jsonHalt(['error' => 'Assinatura de token inválida'], 401); } catch (Exception $e) { - $this->app->jsonHalt(['error' => 'Invalid token: ' . $e->getMessage()], 401); + $this->app->jsonHalt(['error' => 'Token inválido: ' . $e->getMessage()], 401); } } } @@ -127,12 +127,12 @@ return [ 'jwt_secret' => getenv('JWT_SECRET') ?: 'your-fallback-secret-for-development' ]; -// app/config/bootstrap.php or index.php -// certifique-se de adicionar esta linha se quiser expor a configuração para o app +// app/config/bootstrap.php ou index.php +// certifique-se de adicionar esta linha se quiser expor a configuração para a app $app->set('config', $config); ``` -> **Nota de Segurança**: Nunca hardcode sua chave secreta! Use variáveis de ambiente em produção. +> **Nota de Segurança**: Nunca codifique sua chave secreta! Use variáveis de ambiente em produção. ### Passo 3: Proteja Suas Rotas com Middleware @@ -145,7 +145,7 @@ Flight::route('GET /api/user/profile', function() { 'username' => $user->username, 'role' => $user->role ]); -})->addMiddleware( JwtMiddleware::class); +})->addMiddleware(JwtMiddleware::class); // Proteja um grupo inteiro de rotas (mais comum!) Flight::group('/api', function() { @@ -174,7 +174,7 @@ Flight::route('POST /api/login', function() { $user = validateUserCredentials($username, $password); if (!$user) { - Flight::jsonHalt(['error' => 'Invalid credentials'], 401); + Flight::jsonHalt(['error' => 'Credenciais inválidas'], 401); } // Gere JWT @@ -184,7 +184,7 @@ Flight::route('POST /api/login', function() { 'username' => $user->username, 'role' => $user->role, 'iat' => time(), - 'exp' => time() + (60 * 60) // 1 hora de expiração + 'exp' => time() + (60 * 60) // Expiração em 1 hora ]; $jwt = JWT::encode($payload, $secretKey, 'HS256'); @@ -256,7 +256,7 @@ Flight::route('POST /api/refresh', function() { // Verifique se é um token de atualização if ($decoded->type !== 'refresh') { - Flight::jsonHalt(['error' => 'Invalid token type'], 401); + Flight::jsonHalt(['error' => 'Tipo de token inválido'], 401); } // Gere novo token de acesso @@ -274,7 +274,7 @@ Flight::route('POST /api/refresh', function() { ]); } catch (Exception $e) { - Flight::jsonHalt(['error' => 'Invalid refresh token'], 401); + Flight::jsonHalt(['error' => 'Token de atualização inválido'], 401); } }); ``` @@ -299,12 +299,12 @@ class JwtRoleMiddleware { $user = $this->app->request()->data->user ?? null; if (!$user) { - $this->app->jsonHalt(['error' => 'Authentication required'], 401); + $this->app->jsonHalt(['error' => 'Autenticação necessária'], 401); } // Verifique se o usuário tem o papel necessário if (!empty($this->allowedRoles) && !in_array($user->role, $this->allowedRoles)) { - $this->app->jsonHalt(['error' => 'Insufficient permissions'], 403); + $this->app->jsonHalt(['error' => 'Permissões insuficientes'], 403); } } } @@ -334,7 +334,7 @@ class RateLimitMiddleware { $requests = Flight::cache()->get($cacheKey, 0); if ($requests >= 100) { // 100 requisições por hora - Flight::jsonHalt(['error' => 'Rate limit exceeded'], 429); + Flight::jsonHalt(['error' => 'Limite de taxa excedido'], 429); } Flight::cache()->set($cacheKey, $requests + 1, 3600); @@ -356,7 +356,7 @@ echo $secretKey; // Armazene isso no seu arquivo .env! ```php // Nunca commite segredos no controle de versão! -// Use um arquivo .env e biblioteca como vlucas/phpdotenv +// Use um arquivo .env e uma biblioteca como vlucas/phpdotenv // Arquivo .env: // JWT_SECRET=your-base64-encoded-secret-here @@ -387,7 +387,7 @@ $secretKey = getenv('JWT_SECRET'); JWTs devem **sempre** ser transmitidos via HTTPS. Nunca envie tokens via HTTP simples em produção! -### 5. Valide Reivindicações do Token +### 5. Valide Reivindicações de Token Sempre valide as reivindicações que você se importa: @@ -397,11 +397,11 @@ $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); // Verificação de expiração é tratada automaticamente pela biblioteca // Mas você pode adicionar validações personalizadas: if ($decoded->iat > time()) { - throw new Exception('Token used before it was issued'); + throw new Exception('Token usado antes de ser emitido'); } if (isset($decoded->nbf) && $decoded->nbf > time()) { - throw new Exception('Token not yet valid'); + throw new Exception('Token ainda não válido'); } ``` @@ -422,7 +422,7 @@ Flight::route('POST /api/logout', function() { // Armazene no cache/redis até a expiração Flight::cache()->set("blacklist:$jwt", true, $ttl); - Flight::json(['message' => 'Successfully logged out']); + Flight::json(['message' => 'Logout realizado com sucesso']); }); // Adicione ao seu JwtMiddleware: @@ -431,7 +431,7 @@ public function before(array $params) { // Verifique a lista negra if (Flight::cache()->get("blacklist:$jwt")) { - $this->app->jsonHalt(['error' => 'Token has been revoked'], 401); + $this->app->jsonHalt(['error' => 'Token foi revogado'], 401); } // ... verifique o token ... @@ -488,8 +488,8 @@ JWT::$leeway = 60; // Permita 60 segundos de desvio de relógio $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); ``` -### Token Não Enviado nas Requisições -Certifique-se de que seu cliente está enviando o header `Authorization`: +### Token Não Sendo Enviado nas Requisições +Certifique-se de que seu cliente está enviando o cabeçalho `Authorization`: ```javascript // Exemplo em JavaScript @@ -504,10 +504,10 @@ fetch('/api/users', { A biblioteca Firebase JWT fornece estes métodos principais: -- `JWT::encode(array $payload, string $key, string $alg)`: Cria um JWT a partir de um payload +- `JWT::encode(array $payload, string $key, string $alg)`: Cria um JWT a partir de uma carga útil - `JWT::decode(string $jwt, Key $key)`: Decodifica e verifica um JWT -- `JWT::urlsafeB64Encode(string $input)`: Codificação Base64 URL-safe -- `JWT::urlsafeB64Decode(string $input)`: Decodificação Base64 URL-safe +- `JWT::urlsafeB64Encode(string $input)`: Codificação Base64 segura para URL +- `JWT::urlsafeB64Decode(string $input)`: Decodificação Base64 segura para URL - `JWT::$leeway`: Propriedade estática para definir leeway de tempo para validação (em segundos) ## Por que Usar Esta Biblioteca? @@ -522,11 +522,11 @@ A biblioteca Firebase JWT fornece estes métodos principais: ## Veja Também - [Repositório Github do Firebase JWT](https://github.com/firebase/php-jwt) -- [JWT.io](https://jwt.io/) - Debug e decodificação de JWTs -- [RFC 7519](https://tools.ietf.org/html/rfc7519) - Especificação oficial de JWT +- [JWT.io](https://jwt.io/) - Depure e decodifique JWTs +- [RFC 7519](https://tools.ietf.org/html/rfc7519) - Especificação oficial do JWT - [Documentação de Middleware do Flight](/learn/middleware) -- [Plugin de Sessão do Flight](/awesome-plugins/session) - Para autenticação baseada em sessões tradicionais +- [Plugin de Sessão do Flight](/awesome-plugins/session) - Para autenticação baseada em sessão tradicional ## Licença -A biblioteca Firebase JWT é licenciada sob a Licença BSD 3-Clause. Veja o [repositório no Github](https://github.com/firebase/php-jwt) para detalhes. \ No newline at end of file +A biblioteca Firebase JWT está licenciada sob a Licença BSD 3-Clause. Veja o [repositório Github](https://github.com/firebase/php-jwt) para detalhes. \ No newline at end of file diff --git a/content/v3/pt/awesome-plugins/runway.md b/content/v3/pt/awesome-plugins/runway.md index 92da2dd9..6384ad67 100644 --- a/content/v3/pt/awesome-plugins/runway.md +++ b/content/v3/pt/awesome-plugins/runway.md @@ -1,6 +1,6 @@ # Runway -Runway é uma aplicação CLI que ajuda você a gerenciar suas aplicações Flight. Ela pode gerar controladores, exibir todas as rotas e mais. É baseada na excelente biblioteca [adhocore/php-cli](https://github.com/adhocore/php-cli). +Runway é um aplicativo CLI que ajuda você a gerenciar suas aplicações Flight. Ele pode gerar controladores, exibir todas as rotas e mais. É baseado na excelente biblioteca [adhocore/php-cli](https://github.com/adhocore/php-cli). Clique [aqui](https://github.com/flightphp/runway) para visualizar o código. @@ -27,18 +27,18 @@ return [ ]; ``` -> **NOTA** - A partir de **v1.2.0**, `.runway-config.json` está depreciado. Por favor, migre sua configuração para `app/config/config.php`. Você pode fazer isso facilmente com o comando `php runway config:migrate`. +> **NOTA** - A partir da **v1.2.0**, o `.runway-config.json` está depreciado. Por favor, migre sua configuração para `app/config/config.php`. Você pode fazer isso facilmente com o comando `php runway config:migrate`. ### Detecção da Raiz do Projeto -Runway é inteligente o suficiente para detectar a raiz do seu projeto, mesmo se você o executar a partir de um subdiretório. Ele procura indicadores como `composer.json`, `.git` ou `app/config/config.php` para determinar onde está a raiz do projeto. Isso significa que você pode executar comandos do Runway de qualquer lugar no seu projeto! +O Runway é inteligente o suficiente para detectar a raiz do seu projeto, mesmo se você o executar de um subdiretório. Ele procura por indicadores como `composer.json`, `.git` ou `app/config/config.php` para determinar onde está a raiz do projeto. Isso significa que você pode executar comandos do Runway de qualquer lugar no seu projeto! ## Uso -Runway tem uma série de comandos que você pode usar para gerenciar sua aplicação Flight. Existem duas maneiras fáceis de usar o Runway. +O Runway tem vários comandos que você pode usar para gerenciar sua aplicação Flight. Há duas maneiras fáceis de usar o Runway. -1. Se você estiver usando o projeto esqueleto, você pode executar `php runway [command]` a partir da raiz do seu projeto. -1. Se você estiver usando Runway como um pacote instalado via composer, você pode executar `vendor/bin/runway [command]` a partir da raiz do seu projeto. +1. Se você estiver usando o projeto esqueleto, você pode executar `php runway [command]` da raiz do seu projeto. +1. Se você estiver usando o Runway como um pacote instalado via composer, você pode executar `vendor/bin/runway [command]` da raiz do seu projeto. ### Lista de Comandos @@ -68,13 +68,13 @@ php runway make:controller MyController ### Gerar um Modelo Active Record -Primeiro, certifique-se de que você instalou o plugin [Active Record](/awesome-plugins/active-record). Com base na configuração em `runway.app_root`, o local gerará um registro para você no diretório `app/records/`. +Primeiro, certifique-se de ter instalado o plugin [Active Record](/awesome-plugins/active-record). Com base na configuração em `runway.app_root`, o local gerará um registro para você no diretório `app/records/`. ```bash php runway make:record users ``` -Se, por exemplo, você tiver a tabela `users` com o seguinte esquema: `id`, `name`, `email`, `created_at`, `updated_at`, um arquivo semelhante ao seguinte será criado no arquivo `app/records/UserRecord.php`: +Por exemplo, se você tiver a tabela `users` com o seguinte esquema: `id`, `name`, `email`, `created_at`, `updated_at`, um arquivo semelhante ao seguinte será criado no arquivo `app/records/UserRecord.php`: ```php argument('', 'O nome do gif engraçado'); } @@ -178,7 +178,7 @@ class ExampleCommand extends AbstractBaseCommand } ``` -Consulte a [Documentação do adhocore/php-cli](https://github.com/adhocore/php-cli) para mais informações sobre como construir seus próprios comandos personalizados para sua aplicação Flight! +Consulte a [Documentação do adhocore/php-cli](https://github.com/adhocore/php-cli) para mais informações sobre como construir seus próprios comandos personalizados na sua aplicação Flight! ## Gerenciamento de Configuração @@ -216,13 +216,13 @@ Se você precisar personalizar a configuração para o Runway, você pode defini [ // Este é o local onde o diretório da sua aplicação está localizado 'app_root' => 'app/', - // Este é o diretório onde o seu arquivo index raiz está localizado + // Este é o diretório onde o arquivo de índice raiz está localizado 'index_root' => 'public/', // Estes são os caminhos para as raízes de outros projetos @@ -233,16 +233,16 @@ return [ // Caminhos base provavelmente não precisam ser configurados, mas está aqui se você quiser 'base_paths' => [ - '/includes/libs/vendor', // se você tiver um caminho realmente único para o seu diretório vendor ou algo assim + '/includes/libs/vendor', // se você tiver um caminho realmente único para o diretório vendor ou algo assim ], - // Caminhos finais são locais dentro de um projeto para procurar os arquivos de comando + // Caminhos finais são locais dentro de um projeto para procurar arquivos de comandos 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // Se você quiser apenas adicionar o caminho completo, vá em frente (absoluto ou relativo à raiz do projeto) + // Se você quiser adicionar o caminho completo, vá em frente (absoluto ou relativo à raiz do projeto) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -254,7 +254,7 @@ return [ ### Acessando a Configuração -Se você precisar acessar os valores de configuração de forma eficaz, você pode acessá-los através do método `__construct` ou do método `app()`. Também é importante notar que, se você tiver um arquivo `app/config/services.php`, esses serviços também estarão disponíveis para o seu comando. +Se você precisar acessar os valores de configuração de forma eficaz, pode acessá-los através do método `__construct` ou do método `app()`. Também é importante notar que, se você tiver um arquivo `app/config/services.php`, esses serviços também estarão disponíveis para o seu comando. ```php public function execute() @@ -264,7 +264,7 @@ public function execute() // Acessar configuração $app_root = $this->config['runway']['app_root']; - // Acessar serviços como talvez uma conexão com o banco de dados + // Acessar serviços como talvez uma conexão de banco de dados $database = $this->config['database'] // ... @@ -273,14 +273,14 @@ public function execute() ## Wrappers de Auxílio de IA -Runway tem alguns wrappers de auxílio que facilitam para a IA gerar comandos. Você pode usar `addOption` e `addArgument` de uma maneira que se sinta semelhante ao Symfony Console. Isso é útil se você estiver usando ferramentas de IA para gerar seus comandos. +O Runway tem alguns wrappers de auxílio que facilitam para a IA gerar comandos. Você pode usar `addOption` e `addArgument` de uma maneira que se sente semelhante ao Symfony Console. Isso é útil se você estiver usando ferramentas de IA para gerar seus comandos. ```php public function __construct(array $config) { - parent::__construct('make:example', 'Cria um exemplo para a documentação', $config); + parent::__construct('make:example', 'Criar um exemplo para a documentação', $config); - // O argumento mode é anulável e padrão para completamente opcional + // O argumento mode é nulo e padrão para completamente opcional $this->addOption('name', 'O nome do exemplo', null); } ``` \ No newline at end of file diff --git a/content/v3/pt/learn/autoloading.md b/content/v3/pt/learn/autoloading.md index 70718660..ec124a05 100644 --- a/content/v3/pt/learn/autoloading.md +++ b/content/v3/pt/learn/autoloading.md @@ -2,7 +2,7 @@ ## Visão Geral -Autoloading é um conceito no PHP onde você especifica um diretório ou diretórios para carregar classes. Isso é muito mais benéfico do que usar `require` ou `include` para carregar classes. Também é um requisito para usar pacotes do Composer. +Autoloading é um conceito em PHP onde você especifica um diretório ou diretórios para carregar classes. Isso é muito mais benéfico do que usar `require` ou `include` para carregar classes. Também é um requisito para usar pacotes do Composer. ## Entendendo @@ -22,7 +22,7 @@ Vamos assumir que temos uma árvore de diretórios como a seguinte: │ ├── config │ ├── controllers - contém os controllers para este projeto │ ├── translations -│ ├── UTILS - contém classes apenas para esta aplicação (isso está em maiúsculas de propósito para um exemplo posterior) +│ ├── UTILS - contém classes apenas para esta aplicação (isso é tudo maiúsculo de propósito para um exemplo posterior) │ └── views └── public └── css @@ -49,7 +49,7 @@ Flight::path(__DIR__.'/../app/utils/'); * app/controllers/MyController.php */ -// sem namespacing necessário +// nenhum namespacing necessário // Todas as classes autoloaded são recomendadas para serem Pascal Case (cada palavra capitalizada, sem espaços) class MyController { @@ -62,7 +62,7 @@ class MyController { ## Namespaces -Se você tiver namespaces, na verdade fica muito fácil implementar isso. Você deve usar o método `Flight::path()` para especificar o diretório raiz (não o document root ou pasta `public/`) da sua aplicação. +Se você tiver namespaces, na verdade se torna muito fácil implementar isso. Você deve usar o método `Flight::path()` para especificar o diretório raiz (não o document root ou pasta `public/`) da sua aplicação. ```php @@ -105,7 +105,7 @@ E se você quisesse autoload uma classe no seu diretório utils, você faria bas * app/UTILS/ArrayHelperUtil.php */ -// namespace deve corresponder à estrutura de diretórios e case (note que o diretório UTILS está em maiúsculas +// namespace deve corresponder à estrutura de diretórios e case (note que o diretório UTILS é tudo maiúsculo // como na árvore de arquivos acima) namespace app\UTILS; @@ -139,7 +139,7 @@ Loader::setV2ClassLoading(false); * app/controllers/My_Controller.php */ -// sem namespacing necessário +// nenhum namespacing necessário class My_Controller { @@ -158,7 +158,7 @@ class My_Controller { ### Classe Não Encontrada (autoloading não funcionando) -Pode haver alguns motivos para isso não acontecer. Abaixo estão alguns exemplos, mas certifique-se de verificar também a seção [autoloading](/learn/autoloading). +Pode haver alguns motivos para isso não acontecer. Abaixo estão alguns exemplos, mas certifique-se de também verificar a seção [autoloading](/learn/autoloading). #### Nome de Arquivo Incorreto O mais comum é que o nome da classe não corresponda ao nome do arquivo. @@ -170,9 +170,9 @@ então o autoloader não conseguirá encontrá-lo. Se você estiver usando namespaces, o namespace deve corresponder à estrutura de diretórios. ```php -// ...código... +// ...code... -// se o seu MyController estiver no diretório app/controllers e estiver namespaced +// se o seu MyController estiver no diretório app/controllers e for namespaced // isso não funcionará. Flight::route('/hello', 'MyController->hello'); diff --git a/content/v3/pt/learn/learn.md b/content/v3/pt/learn/learn.md index 4252ab0a..9a040f14 100644 --- a/content/v3/pt/learn/learn.md +++ b/content/v3/pt/learn/learn.md @@ -1,15 +1,15 @@ # Aprenda Sobre o Flight Flight é um framework rápido, simples e extensível para PHP. Ele é bastante versátil e pode ser usado para construir qualquer tipo de aplicação web. -Ele é construído com simplicidade em mente e é escrito de uma forma que é fácil de entender e usar. +É construído com simplicidade em mente e é escrito de uma forma fácil de entender e usar. -> **Nota:** Você verá exemplos que usam `Flight::` como uma variável estática e alguns que usam o objeto Engine `$app->`. Ambos funcionam de forma intercambiável com o outro. `$app` e `$this->app` em um controller/middleware é a abordagem recomendada pela equipe do Flight. +> **Nota:** Você verá exemplos que usam `Flight::` como uma variável estática e alguns que usam o objeto Engine `$app->`. Ambos funcionam de forma intercambiável um com o outro. `$app` e `$this->app` em um controller/middleware é a abordagem recomendada pela equipe do Flight. ## Componentes Principais ### [Routing](/learn/routing) -Aprenda como gerenciar rotas para sua aplicação web. Isso também inclui agrupar rotas, parâmetros de rota e middleware. +Aprenda como gerenciar rotas para sua aplicação web. Isso também inclui agrupamento de rotas, parâmetros de rota e middleware. ### [Middleware](/learn/middleware) @@ -17,7 +17,7 @@ Aprenda como usar middleware para filtrar requisições e respostas em sua aplic ### [Autoloading](/learn/autoloading) -Aprenda como autoloadar suas próprias classes em sua aplicação. +Aprenda como carregar automaticamente suas próprias classes em sua aplicação. ### [Requests](/learn/requests) @@ -49,7 +49,7 @@ Aprenda como estender o framework adicionando seus próprios métodos e classes. ### [Method Hooks and Filtering](/learn/filtering) -Aprenda como adicionar hooks de eventos aos seus métodos e métodos internos do framework. +Aprenda como adicionar ganchos de eventos aos seus métodos e métodos internos do framework. ### [Dependency Injection Container (DIC)](/learn/dependency-injection-container) @@ -65,9 +65,13 @@ Collections são usadas para armazenar dados e serem acessíveis como um array o Isso tem algumas funções simples para tornar a codificação e decodificação do seu JSON consistente. -### [PDO Wrapper](/learn/pdo-wrapper) +### [SimplePdo](/learn/simple-pdo) -PDO às vezes pode adicionar mais dor de cabeça do que o necessário. Esta classe wrapper simples pode tornar significativamente mais fácil interagir com seu banco de dados. +PDO às vezes pode adicionar mais dor de cabeça do que o necessário. SimplePdo é uma classe auxiliar moderna para PDO com métodos convenientes como `insert()`, `update()`, `delete()` e `transaction()` para tornar as operações de banco de dados muito mais fáceis. + +### [PdoWrapper](/learn/pdo-wrapper) (Deprecated) + +O wrapper original do PDO está depreciado a partir da v3.18.0. Por favor, use [SimplePdo](/learn/simple-pdo) em vez disso. ### [Uploaded File Handler](/learn/uploaded-file) @@ -75,15 +79,15 @@ Uma classe simples para ajudar a gerenciar arquivos enviados e movê-los para um ## Conceitos Importantes -### [Por Que um Framework?](/learn/why-frameworks) +### [Why a Framework?](/learn/why-frameworks) Aqui está um artigo curto sobre por que você deve usar um framework. É uma boa ideia entender os benefícios de usar um framework antes de começar a usar um. -Adicionalmente, um excelente tutorial foi criado por [@lubiana](https://git.php.fail/lubiana). Embora não entre em grandes detalhes sobre o Flight especificamente, -este guia ajudará você a entender alguns dos principais conceitos ao redor de um framework e por que eles são benéficos de usar. +Além disso, um excelente tutorial foi criado por [@lubiana](https://git.php.fail/lubiana). Embora não entre em grandes detalhes sobre o Flight especificamente, +este guia ajudará você a entender alguns dos conceitos principais ao redor de um framework e por que eles são benéficos de usar. Você pode encontrar o tutorial [aqui](https://git.php.fail/lubiana/no-framework-tutorial/src/branch/master/README.md). -### [Flight Comparado a Outros Frameworks](/learn/flight-vs-another-framework) +### [Flight Compared to Other Frameworks](/learn/flight-vs-another-framework) Se você está migrando de outro framework como Laravel, Slim, Fat-Free ou Symfony para o Flight, esta página ajudará você a entender as diferenças entre os dois. @@ -91,7 +95,7 @@ Se você está migrando de outro framework como Laravel, Slim, Fat-Free ou Symfo ### [Unit Testing](/learn/unit-testing) -Siga este guia para aprender como fazer testes unitários no seu código Flight para que seja sólido como uma rocha. +Siga este guia para aprender como fazer testes unitários no seu código Flight para torná-lo sólido como uma rocha. ### [AI & Developer Experience](/learn/ai) @@ -99,4 +103,4 @@ Aprenda como o Flight funciona com ferramentas de IA e fluxos de trabalho modern ### [Migrating v2 -> v3](/learn/migrating-to-v3) -A compatibilidade com versões anteriores foi mantida na maior parte, mas há algumas mudanças das quais você deve estar ciente ao migrar da v2 para a v3. \ No newline at end of file +A compatibilidade com versões anteriores foi mantida em grande parte, mas há algumas mudanças das quais você deve estar ciente ao migrar da v2 para a v3. \ No newline at end of file diff --git a/content/v3/pt/learn/pdo_wrapper.md b/content/v3/pt/learn/pdo_wrapper.md index 8f54c4f5..9b136785 100644 --- a/content/v3/pt/learn/pdo_wrapper.md +++ b/content/v3/pt/learn/pdo_wrapper.md @@ -1,14 +1,18 @@ # Classe Auxiliar PDO PdoWrapper +> **AVISO** +> +> **Depreciado:** `PdoWrapper` está depreciado a partir do Flight v3.18.0. Não será removido em uma versão futura, mas será mantido para compatibilidade com versões anteriores. Por favor, use [SimplePdo](/learn/simple-pdo) em vez disso, que oferece a mesma funcionalidade mais métodos auxiliares adicionais para operações comuns de banco de dados. + ## Visão Geral -A classe `PdoWrapper` no Flight é um auxiliar amigável para trabalhar com bancos de dados usando PDO. Ela simplifica tarefas comuns de banco de dados, adiciona alguns métodos úteis para buscar resultados e retorna os resultados como [Collections](/learn/collections) para acesso fácil. Ela também suporta log de consultas e monitoramento de desempenho de aplicação (APM) para casos de uso avançados. +A classe `PdoWrapper` no Flight é um auxiliar amigável para trabalhar com bancos de dados usando PDO. Ela simplifica tarefas comuns de banco de dados, adiciona alguns métodos úteis para buscar resultados e retorna resultados como [Collections](/learn/collections) para acesso fácil. Ela também suporta registro de consultas e monitoramento de desempenho de aplicação (APM) para casos de uso avançados. ## Entendendo -Trabalhar com bancos de dados em PHP pode ser um pouco verboso, especialmente ao usar PDO diretamente. `PdoWrapper` estende PDO e adiciona métodos que facilitam muito a consulta, busca e manipulação de resultados. Em vez de lidar com declarações preparadas e modos de busca, você obtém métodos simples para tarefas comuns, e cada linha é retornada como uma Collection, para que você possa usar notação de array ou objeto. +Trabalhar com bancos de dados em PHP pode ser um pouco verboso, especialmente ao usar PDO diretamente. `PdoWrapper` estende PDO e adiciona métodos que tornam a consulta, busca e manipulação de resultados muito mais fáceis. Em vez de lidar com declarações preparadas e modos de busca, você obtém métodos simples para tarefas comuns, e cada linha é retornada como uma Collection, para que você possa usar notação de array ou objeto. -Você pode registrar o `PdoWrapper` como um serviço compartilhado no Flight, e então usá-lo em qualquer lugar da sua aplicação via `Flight::db()`. +Você pode registrar o `PdoWrapper` como um serviço compartilhado no Flight, e então usá-lo em qualquer lugar do seu app via `Flight::db()`. ## Uso Básico @@ -103,17 +107,17 @@ $users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", ['1,2,3'] ## Uso Avançado -### Log de Consultas & APM +### Registro de Consultas & APM -Se você quiser rastrear o desempenho de consultas, habilite o rastreamento APM ao registrar: +Se você quiser rastrear o desempenho de consultas, ative o rastreamento APM ao registrar: ```php Flight::register('db', \flight\database\PdoWrapper::class, [ - 'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [/* options */], true // último parâmetro habilita APM + 'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [/* options */], true // último parâmetro ativa APM ]); ``` -Após executar consultas, você pode registrá-las manualmente, mas o APM as registrará automaticamente se habilitado: +Após executar consultas, você pode registrá-las manualmente, mas o APM as registrará automaticamente se ativado: ```php Flight::db()->logQueries(); @@ -170,6 +174,6 @@ Flight::route('/users', function () { - Todas as linhas são retornadas como Collections—se você precisar de um array simples, use `$collection->getData()`. - Para consultas `IN (?)`, certifique-se de passar um array ou string separada por vírgulas. -## Registro de Alterações +## Changelog - v3.2.0 - Lançamento inicial do PdoWrapper com métodos básicos de consulta e busca. \ No newline at end of file diff --git a/content/v3/pt/learn/simple_pdo.md b/content/v3/pt/learn/simple_pdo.md new file mode 100644 index 00000000..39168434 --- /dev/null +++ b/content/v3/pt/learn/simple_pdo.md @@ -0,0 +1,320 @@ +# Classe Auxiliar SimplePdo PDO + +## Visão Geral + +A classe `SimplePdo` no Flight é um auxiliar moderno e rico em recursos para trabalhar com bancos de dados usando PDO. Ela estende `PdoWrapper` e adiciona métodos auxiliares convenientes para operações comuns de banco de dados, como `insert()`, `update()`, `delete()` e transações. Ela simplifica tarefas de banco de dados, retorna resultados como [Collections](/learn/collections) para acesso fácil e suporta registro de consultas e monitoramento de desempenho de aplicação (APM) para casos de uso avançados. + +## Entendendo + +A classe `SimplePdo` é projetada para tornar o trabalho com bancos de dados em PHP muito mais fácil. Em vez de lidar com declarações preparadas, modos de busca e operações SQL verbosas, você obtém métodos limpos e simples para tarefas comuns. Cada linha é retornada como uma Collection, para que você possa usar tanto notação de array (`$row['name']`) quanto notação de objeto (`$row->name`). + +Esta classe é um superconjunto de `PdoWrapper`, o que significa que ela inclui toda a funcionalidade de `PdoWrapper` mais métodos auxiliares adicionais que tornam seu código mais limpo e mais fácil de manter. Se você está usando `PdoWrapper` atualmente, atualizar para `SimplePdo` é direto, pois ela estende `PdoWrapper`. + +Você pode registrar `SimplePdo` como um serviço compartilhado no Flight e, em seguida, usá-lo em qualquer lugar em seu app via `Flight::db()`. + +## Uso Básico + +### Registrando SimplePdo + +Primeiro, registre a classe `SimplePdo` com o Flight: + +```php +Flight::register('db', \flight\database\SimplePdo::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 + ] +]); +``` + +> **NOTA** +> +> Se você não especificar `PDO::ATTR_DEFAULT_FETCH_MODE`, `SimplePdo` o definirá automaticamente como `PDO::FETCH_ASSOC` para você. + +Agora você pode usar `Flight::db()` em qualquer lugar para obter sua conexão com o banco de dados. + +### Executando Consultas + +#### `runQuery()` + +`function runQuery(string $sql, array $params = []): PDOStatement` + +Use isso para INSERTs, UPDATEs ou quando você quiser buscar resultados manualmente: + +```php +$db = Flight::db(); +$statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']); +while ($row = $statement->fetch()) { + // $row é um array +} +``` + +Você também pode usá-lo para gravações: + +```php +$db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); +$db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]); +``` + +#### `fetchField()` + +`function fetchField(string $sql, array $params = []): mixed` + +Obtenha um único valor do banco de dados: + +```php +$count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']); +``` + +#### `fetchRow()` + +`function fetchRow(string $sql, array $params = []): ?Collection` + +Obtenha uma única linha como uma Collection (acesso array/objeto): + +```php +$user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); +echo $user['name']; +// ou +echo $user->name; +``` + +> **DICA** +> +> `SimplePdo` adiciona automaticamente `LIMIT 1` às consultas `fetchRow()` se não estiver presente, tornando suas consultas mais eficientes. + +#### `fetchAll()` + +`function fetchAll(string $sql, array $params = []): array` + +Obtenha todas as linhas como um array de Collections: + +```php +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); +foreach ($users as $user) { + echo $user['name']; + // ou + echo $user->name; +} +``` + +#### `fetchColumn()` + +`function fetchColumn(string $sql, array $params = []): array` + +Busque uma única coluna como um array: + +```php +$ids = Flight::db()->fetchColumn("SELECT id FROM users WHERE active = ?", [1]); +// Retorna: [1, 2, 3, 4, 5] +``` + +#### `fetchPairs()` + +`function fetchPairs(string $sql, array $params = []): array` + +Busque resultados como pares chave-valor (primeira coluna como chave, segunda como valor): + +```php +$userNames = Flight::db()->fetchPairs("SELECT id, name FROM users"); +// Retorna: [1 => 'John', 2 => 'Jane', 3 => 'Bob'] +``` + +### Usando Placeholders `IN()` + +Você pode usar um único `?` em uma cláusula `IN()` e passar um array: + +```php +$ids = [1, 2, 3]; +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); +``` + +## Métodos Auxiliares + +Uma das principais vantagens do `SimplePdo` sobre `PdoWrapper` é a adição de métodos auxiliares convenientes para operações comuns de banco de dados. + +### `insert()` + +`function insert(string $table, array $data): string` + +Insira uma ou mais linhas e retorne o último ID de inserção. + +**Inserção única:** + +```php +$id = Flight::db()->insert('users', [ + 'name' => 'John', + 'email' => 'john@example.com' +]); +``` + +**Inserção em massa:** + +```php +$id = Flight::db()->insert('users', [ + ['name' => 'John', 'email' => 'john@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'], +]); +``` + +### `update()` + +`function update(string $table, array $data, string $where, array $whereParams = []): int` + +Atualize linhas e retorne o número de linhas afetadas: + +```php +$affected = Flight::db()->update( + 'users', + ['name' => 'Jane', 'email' => 'jane@example.com'], + 'id = ?', + [1] +); +``` + +> **NOTA** +> +> O `rowCount()` do SQLite retorna o número de linhas onde os dados realmente mudaram. Se você atualizar uma linha com os mesmos valores que ela já tem, `rowCount()` retornará 0. Isso difere do comportamento do MySQL ao usar `PDO::MYSQL_ATTR_FOUND_ROWS`. + +### `delete()` + +`function delete(string $table, string $where, array $whereParams = []): int` + +Exclua linhas e retorne o número de linhas excluídas: + +```php +$deleted = Flight::db()->delete('users', 'id = ?', [1]); +``` + +### `transaction()` + +`function transaction(callable $callback): mixed` + +Execute um callback dentro de uma transação. A transação é confirmada automaticamente em caso de sucesso ou revertida em caso de erro: + +```php +$result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John']); + $db->insert('logs', ['action' => 'user_created']); + return $db->lastInsertId(); +}); +``` + +Se qualquer exceção for lançada dentro do callback, a transação é revertida automaticamente e a exceção é relançada. + +## Uso Avançado + +### Registro de Consultas & APM + +Se você quiser rastrear o desempenho de consultas, habilite o rastreamento de APM ao registrar: + +```php +Flight::register('db', \flight\database\SimplePdo::class, [ + 'mysql:host=localhost;dbname=cool_db_name', + 'user', + 'pass', + [/* opções PDO */], + [ + 'trackApmQueries' => true, + 'maxQueryMetrics' => 1000 + ] +]); +``` + +Após executar consultas, você pode registrá-las manualmente, mas o APM as registrará automaticamente se habilitado: + +```php +Flight::db()->logQueries(); +``` + +Isso acionará um evento (`flight.db.queries`) com métricas de conexão e consulta, que você pode escutar usando o sistema de eventos do Flight. + +### Exemplo Completo + +```php +Flight::route('/users', function () { + // Obter todos os usuários + $users = Flight::db()->fetchAll('SELECT * FROM users'); + + // Transmitir todos os usuários + $statement = Flight::db()->runQuery('SELECT * FROM users'); + while ($user = $statement->fetch()) { + echo $user['name']; + } + + // Obter um único usuário + $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); + + // Obter um único valor + $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); + + // Obter uma única coluna + $ids = Flight::db()->fetchColumn('SELECT id FROM users'); + + // Obter pares chave-valor + $userNames = Flight::db()->fetchPairs('SELECT id, name FROM users'); + + // Sintaxe especial IN() + $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); + + // Inserir um novo usuário + $id = Flight::db()->insert('users', [ + 'name' => 'Bob', + 'email' => 'bob@example.com' + ]); + + // Inserção em massa de usuários + Flight::db()->insert('users', [ + ['name' => 'Bob', 'email' => 'bob@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'] + ]); + + // Atualizar um usuário + $affected = Flight::db()->update('users', ['name' => 'Bob'], 'id = ?', [123]); + + // Excluir um usuário + $deleted = Flight::db()->delete('users', 'id = ?', [123]); + + // Usar uma transação + $result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John', 'email' => 'john@example.com']); + $db->insert('audit_log', ['action' => 'user_created']); + return $db->lastInsertId(); + }); +}); +``` + +## Migrando de PdoWrapper + +Se você está usando `PdoWrapper` atualmente, migrar para `SimplePdo` é direto: + +1. **Atualize seu registro:** + ```php + // Antigo + Flight::register('db', \flight\database\PdoWrapper::class, [ /* ... */ ]); + + // Novo + Flight::register('db', \flight\database\SimplePdo::class, [ /* ... */ ]); + ``` + +2. **Todos os métodos existentes de `PdoWrapper` funcionam no `SimplePdo`** - Não há mudanças que quebrem o código. Seu código existente continuará funcionando. + +3. **Opcionalmente, use os novos métodos auxiliares** - Comece a usar `insert()`, `update()`, `delete()` e `transaction()` para simplificar seu código. + +## Veja Também + +- [Collections](/learn/collections) - Aprenda como usar a classe Collection para acesso fácil aos dados. +- [PdoWrapper](/learn/pdo-wrapper) - A classe auxiliar PDO legada (depreciada). + +## Solução de Problemas + +- Se você receber um erro sobre conexão com o banco de dados, verifique seu DSN, nome de usuário, senha e opções. +- Todas as linhas são retornadas como Collections—se você precisar de um array simples, use `$collection->getData()`. +- Para consultas `IN (?)`, certifique-se de passar um array. +- Se você estiver enfrentando problemas de memória com registro de consultas em processos de longa duração, ajuste a opção `maxQueryMetrics`. + +## Registro de Alterações + +- v3.18.0 - Lançamento inicial do SimplePdo com métodos auxiliares para insert, update, delete e transações. \ No newline at end of file diff --git a/content/v3/ru/awesome-plugins/awesome_plugins.md b/content/v3/ru/awesome-plugins/awesome_plugins.md index 7ab11e83..b11921ce 100644 --- a/content/v3/ru/awesome-plugins/awesome_plugins.md +++ b/content/v3/ru/awesome-plugins/awesome_plugins.md @@ -1,102 +1,103 @@ -# Крутой плагины +# Крутые плагины Flight невероятно расширяем. Существует множество плагинов, которые можно использовать для добавления функциональности в ваше приложение Flight. Некоторые из них официально поддерживаются командой Flight, а другие — это микро/лайт-библиотеки, чтобы помочь вам начать. ## Документация API -Документация API крайне важна для любого API. Она помогает разработчикам понять, как взаимодействовать с вашим API и чего ожидать в ответ. Существует несколько инструментов, которые помогут вам генерировать документацию API для ваших проектов Flight. +Документация API крайне важна для любого API. Она помогает разработчикам понять, как взаимодействовать с вашим API и чего ожидать в ответ. Есть несколько инструментов, доступных для генерации документации API для ваших проектов Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Пост в блоге, написанный Даниэлем Шрайбером, о том, как использовать спецификацию OpenAPI с FlightPHP для создания вашего API с использованием подхода API first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI — отличный инструмент, который поможет вам генерировать документацию API для ваших проектов Flight. Его очень легко использовать, и его можно настроить под ваши нужды. Это PHP-библиотека, которая поможет вам генерировать документацию Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) — Пост в блоге, написанный Даниэлем Шрайбером, о том, как использовать спецификацию OpenAPI с FlightPHP для построения вашего API с использованием подхода API first. +- [SwaggerUI](https://github.com/zircote/swagger-php) — Swagger UI — отличный инструмент для генерации документации API для ваших проектов Flight. Его очень легко использовать, и его можно настроить под ваши нужды. Это PHP-библиотека для генерации документации Swagger. ## Мониторинг производительности приложений (APM) -Мониторинг производительности приложений (APM) крайне важен для любого приложения. Он помогает вам понять, как работает ваше приложение и где находятся узкие места. Существует множество инструментов APM, которые можно использовать с Flight. -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM — это простая библиотека APM, которую можно использовать для мониторинга ваших приложений Flight. Её можно использовать для мониторинга производительности вашего приложения и помощи в выявлении узких мест. +Мониторинг производительности приложений (APM) крайне важен для любого приложения. Он помогает понять, как работает ваше приложение и где находятся узкие места. Существует множество инструментов APM, которые можно использовать с Flight. +- official [flightphp/apm](/awesome-plugins/apm) — Flight APM — простая библиотека APM, которую можно использовать для мониторинга приложений Flight. Её можно использовать для мониторинга производительности вашего приложения и помощи в выявлении узких мест. ## Асинхронность -Flight уже является быстрым фреймворком, но добавление к нему турбо-двигателя делает всё ещё веселее (и сложнее)! +Flight уже является быстрым фреймворком, но добавление турбо-двигателя делает всё ещё веселее (и сложнее)! -- [flightphp/async](/awesome-plugins/async) - Официальная библиотека Flight Async. Эта библиотека — простой способ добавить асинхронную обработку в ваше приложение. Она использует Swoole/Openswoole под капотом, чтобы предоставить простой и эффективный способ запуска задач асинхронно. +- [flightphp/async](/awesome-plugins/async) — Официальная библиотека Flight Async. Эта библиотека — простой способ добавить асинхронную обработку в ваше приложение. Она использует Swoole/Openswoole под капотом, чтобы предоставить простой и эффективный способ запуска задач асинхронно. ## Авторизация/Разрешения -Авторизация и разрешения крайне важны для любого приложения, которое требует контроля над тем, кто может получить доступ к чему. +Авторизация и разрешения крайне важны для любого приложения, которое требует контроля доступа к ресурсам. -- official [flightphp/permissions](/awesome-plugins/permissions) - Официальная библиотека Flight Permissions. Эта библиотека — простой способ добавить разрешения на уровне пользователя и приложения в ваше приложение. +- official [flightphp/permissions](/awesome-plugins/permissions) — Официальная библиотека Flight Permissions. Эта библиотека — простой способ добавить разрешения на уровне пользователя и приложения в ваше приложение. ## Аутентификация -Аутентификация необходима для приложений, которым нужно проверять идентичность пользователя и защищать конечные точки API. +Аутентификация необходима для приложений, которым нужно проверять идентичность пользователя и обеспечивать безопасность конечных точек API. -- [firebase/php-jwt](/awesome-plugins/jwt) - Библиотека JSON Web Token (JWT) для PHP. Простой и безопасный способ реализовать аутентификацию на основе токенов в ваших приложениях Flight. Идеально для бесстатусной аутентификации API, защиты маршрутов с помощью middleware и реализации потоков авторизации в стиле OAuth. +- [firebase/php-jwt](/awesome-plugins/jwt) — Библиотека JSON Web Token (JWT) для PHP. Простой и безопасный способ реализовать аутентификацию на основе токенов в ваших приложениях Flight. Идеально подходит для аутентификации stateless API, защиты маршрутов с помощью middleware и реализации потоков авторизации в стиле OAuth. ## Кэширование Кэширование — отличный способ ускорить ваше приложение. Существует множество библиотек кэширования, которые можно использовать с Flight. -- official [flightphp/cache](/awesome-plugins/php-file-cache) - Лёгкий, простой и автономный класс кэширования PHP в файле +- official [flightphp/cache](/awesome-plugins/php-file-cache) — Лёгкий, простой и автономный класс кэширования PHP в файле ## CLI CLI-приложения — отличный способ взаимодействовать с вашим приложением. Их можно использовать для генерации контроллеров, отображения всех маршрутов и многого другого. -- official [flightphp/runway](/awesome-plugins/runway) - Runway — это CLI-приложение, которое помогает вам управлять вашими приложениями Flight. +- official [flightphp/runway](/awesome-plugins/runway) — Runway — CLI-приложение, которое помогает управлять приложениями Flight. ## Куки -Куки — отличный способ хранить небольшие объёмы данных на стороне клиента. Их можно использовать для хранения предпочтений пользователя, настроек приложения и многого другого. +Куки — отличный способ хранить небольшие объёмы данных на стороне клиента. Их можно использовать для хранения предпочтений пользователя, настроек приложения и т.д. -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie — это PHP-библиотека, которая предоставляет простой и эффективный способ управления куки. +- [overclokk/cookie](/awesome-plugins/php-cookie) — PHP Cookie — PHP-библиотека, которая предоставляет простой и эффективный способ управления куки. ## Отладка -Отладка крайне важна, когда вы разрабатываете в локальной среде. Существует несколько плагинов, которые могут улучшить ваш опыт отладки. +Отладка крайне важна при разработке в локальной среде. Есть несколько плагинов, которые могут улучшить ваш опыт отладки. -- [tracy/tracy](/awesome-plugins/tracy) - Это полнофункциональный обработчик ошибок, который можно использовать с Flight. У него есть несколько панелей, которые могут помочь вам отлаживать ваше приложение. Его также очень легко расширять и добавлять свои собственные панели. -- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Используется с обработчиком ошибок [Tracy](/awesome-plugins/tracy), этот плагин добавляет несколько дополнительных панелей для помощи в отладке специально для проектов Flight. +- [tracy/tracy](/awesome-plugins/tracy) — Это полнофункциональный обработчик ошибок, который можно использовать с Flight. У него есть несколько панелей, которые могут помочь вам отлаживать ваше приложение. Его также очень легко расширять и добавлять свои собственные панели. +- official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) — Используется с обработчиком ошибок [Tracy](/awesome-plugins/tracy), этот плагин добавляет несколько дополнительных панелей для помощи в отладке специально для проектов Flight. ## Базы данных Базы данных — основа большинства приложений. Это способ хранения и извлечения данных. Некоторые библиотеки баз данных — просто обёртки для написания запросов, а некоторые — полноценные ORM. -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Официальная обёртка Flight PDO, которая является частью ядра. Это простая обёртка, которая помогает упростить процесс написания запросов и их выполнения. Это не ORM. -- official [flightphp/active-record](/awesome-plugins/active-record) - Официальный ORM/Mapper Flight ActiveRecord. Отличная маленькая библиотека для лёгкого извлечения и хранения данных в вашей базе данных. -- [byjg/php-migration](/awesome-plugins/migrations) - Плагин для отслеживания всех изменений базы данных для вашего проекта. +- official [flightphp/core SimplePdo](/learn/simple-pdo) — Официальный помощник Flight PDO, который является частью ядра. Это современная обёртка с удобными методами, такими как `insert()`, `update()`, `delete()` и `transaction()`, для упрощения операций с базой данных. Все результаты возвращаются как Collections для гибкого доступа к массивам/объектам. Не ORM, просто лучший способ работать с PDO. +- deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) — Официальная обёртка Flight PDO, которая является частью ядра (устарела с версии 3.18.0). Используйте SimplePdo вместо неё. +- official [flightphp/active-record](/awesome-plugins/active-record) — Официальный ORM/Mapper Flight ActiveRecord. Отличная маленькая библиотека для лёгкого извлечения и хранения данных в вашей базе данных. +- [byjg/php-migration](/awesome-plugins/migrations) — Плагин для отслеживания всех изменений базы данных в вашем проекте. ## Шифрование Шифрование крайне важно для любого приложения, которое хранит конфиденциальные данные. Шифрование и дешифрование данных не так уж сложно, но правильное хранение ключа шифрования [может](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [быть](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [сложным](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Самое важное — никогда не хранить ключ шифрования в публичной директории или коммитить его в репозиторий кода. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Это библиотека, которую можно использовать для шифрования и дешифрования данных. Запуск и настройка довольно просты, чтобы начать шифровать и дешифровать данные. +- [defuse/php-encryption](/awesome-plugins/php-encryption) — Это библиотека, которую можно использовать для шифрования и дешифрования данных. Запуск и использование довольно просты для начала шифрования и дешифрования данных. ## Очередь заданий Очереди заданий очень полезны для асинхронной обработки задач. Это может быть отправка email, обработка изображений или что угодно, что не требует выполнения в реальном времени. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue — это библиотека, которую можно использовать для асинхронной обработки заданий. Её можно использовать с beanstalkd, MySQL/MariaDB, SQLite и PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) — Simple Job Queue — библиотека, которую можно использовать для асинхронной обработки заданий. Её можно использовать с beanstalkd, MySQL/MariaDB, SQLite и PostgreSQL. ## Сессии -Сессии не очень полезны для API, но для создания веб-приложения сессии могут быть крайне важны для поддержания состояния и информации о входе. +Сессии не очень полезны для API, но для построения веб-приложения сессии могут быть крайне важны для поддержания состояния и информации о входе. -- official [flightphp/session](/awesome-plugins/session) - Официальная библиотека Flight Session. Это простая библиотека сессий, которую можно использовать для хранения и извлечения данных сессии. Она использует встроенную обработку сессий PHP. -- [Ghostff/Session](/awesome-plugins/ghost-session) - Менеджер сессий PHP (неблокирующий, flash, сегмент, шифрование сессий). Использует PHP open_ssl для опционального шифрования/дешифрования данных сессии. +- official [flightphp/session](/awesome-plugins/session) — Официальная библиотека Flight Session. Это простая библиотека сессий, которую можно использовать для хранения и извлечения данных сессии. Она использует встроенную обработку сессий PHP. +- [Ghostff/Session](/awesome-plugins/ghost-session) — Менеджер сессий PHP (неблокирующий, flash, сегмент, шифрование сессии). Использует PHP open_ssl для опционального шифрования/дешифрования данных сессии. ## Шаблонизация Шаблонизация — основа любого веб-приложения с UI. Существует множество шаблонизаторов, которые можно использовать с Flight. -- deprecated [flightphp/core View](/learn#views) - Это очень базовый шаблонизатор, который является частью ядра. Не рекомендуется использовать, если у вас больше нескольких страниц в проекте. -- [latte/latte](/awesome-plugins/latte) - Latte — полнофункциональный шаблонизатор, который очень легко использовать и ближе к синтаксису PHP, чем Twig или Smarty. Его также очень легко расширять и добавлять свои собственные фильтры и функции. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate — мощный шаблонизатор PHP с компиляцией ассетов, наследованием шаблонов и обработкой переменных. Поддерживает автоматическую минификацию CSS/JS, кэширование, кодирование Base64 и опциональную интеграцию с фреймворком Flight PHP. +- deprecated [flightphp/core View](/learn#views) — Это очень базовый шаблонизатор, который является частью ядра. Не рекомендуется использовать, если у вас больше нескольких страниц в проекте. +- [latte/latte](/awesome-plugins/latte) — Latte — полнофункциональный шаблонизатор, который очень легко использовать и ближе к синтаксису PHP, чем Twig или Smarty. Его также очень легко расширять и добавлять свои фильтры и функции. +- [knifelemon/comment-template](/awesome-plugins/comment-template) — CommentTemplate — мощный шаблонизатор PHP с компиляцией ассетов, наследованием шаблонов и обработкой переменных. Поддерживает автоматическую минификацию CSS/JS, кэширование, кодирование Base64 и опциональную интеграцию с фреймворком Flight PHP. ## Интеграция с WordPress -Хотите использовать Flight в вашем проекте WordPress? Для этого есть удобный плагин! +Хотите использовать Flight в вашем проекте WordPress? Есть удобный плагин для этого! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Этот плагин WordPress позволяет запускать Flight прямо рядом с WordPress. Он идеален для добавления пользовательских API, микросервисов или даже полноценных приложений на ваш сайт WordPress с использованием фреймворка Flight. Супер полезно, если вы хотите лучшее из двух миров! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) — Этот плагин WordPress позволяет запускать Flight прямо рядом с WordPress. Идеально подходит для добавления пользовательских API, микросервисов или даже полноценных приложений на ваш сайт WordPress с использованием фреймворка Flight. Супер полезно, если вы хотите лучшее из двух миров! ## Вклад diff --git a/content/v3/ru/awesome-plugins/jwt.md b/content/v3/ru/awesome-plugins/jwt.md index 09dc339c..688c1304 100644 --- a/content/v3/ru/awesome-plugins/jwt.md +++ b/content/v3/ru/awesome-plugins/jwt.md @@ -1,6 +1,6 @@ -# Firebase JWT - Аутентификация с использованием JSON Web Token для Flight +# Firebase JWT - Аутентификация с использованием JSON Web Token -JWT (JSON Web Tokens) — это компактный, безопасный для URL способ представления утверждений между вашим приложением и клиентом. Они идеальны для аутентификации stateless API — без необходимости хранения сессий на сервере! Это руководство показывает, как интегрировать [Firebase JWT](https://github.com/firebase/php-jwt) с Flight для безопасной аутентификации на основе токенов. +JWT (JSON Web Tokens) — это компактный и безопасный для URL способ представления утверждений между вашим приложением и клиентом. Они идеально подходят для аутентификации stateless API — без необходимости хранения сессий на сервере! Это руководство показывает, как интегрировать [Firebase JWT](https://github.com/firebase/php-jwt) с Flight для безопасной аутентификации на основе токенов. Посетите [репозиторий на Github](https://github.com/firebase/php-jwt) для полной документации и деталей. @@ -8,17 +8,17 @@ JWT (JSON Web Tokens) — это компактный, безопасный дл JSON Web Token — это строка, содержащая три части: 1. **Заголовок**: Метаданные о токене (алгоритм, тип) -2. **Полезная нагрузка**: Ваши данные (ID пользователя, роли, срок действия и т.д.) +2. **Полезная нагрузка**: Ваши данные (ID пользователя, роли, срок истечения и т.д.) 3. **Подпись**: Криптографическая подпись для проверки подлинности -Пример JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (выглядит как бессмысленный набор символов, но это структурированные данные!) +Пример JWT: `eyJ0eXAiOiJKV1QiLCJhbGc...` (выглядит как бессмыслица, но это структурированные данные!) ### Почему использовать JWT? - **Stateless**: Не требуется хранение сессий на сервере — идеально для микросервисов и API -- **Масштабируемость**: Хорошо работает с балансировщиками нагрузки, поскольку нет требования к affinity сессий -- **Кросс-доменная совместимость**: Может использоваться в разных доменах и сервисах -- **Дружественно к мобильным устройствам**: Отлично подходит для мобильных приложений, где куки могут работать не так хорошо +- **Масштабируемость**: Отлично работает с балансировщиками нагрузки, поскольку нет требования к affinity сессий +- **Кросс-доменная**: Может использоваться через разные домены и сервисы +- **Дружественно к мобильным**: Отлично для мобильных приложений, где куки могут не работать хорошо - **Стандартизировано**: Стандарт отрасли (RFC 7519) ## Установка @@ -29,7 +29,7 @@ JSON Web Token — это строка, содержащая три части: composer require firebase/php-jwt ``` -## Основное использование +## Базовое использование Вот быстрый пример создания и проверки JWT: @@ -37,7 +37,7 @@ composer require firebase/php-jwt use Firebase\JWT\JWT; use Firebase\JWT\Key; -// Ваш секретный ключ (ХРАНИТЕ ЕГО В БЕЗОПАСНОСТИ!) +// Ваш секретный ключ (ХРАНИТЕ ЕГО В БЕЗОПАСНОМ МЕСТЕ!) $secretKey = 'your-256-bit-secret-key-here-keep-it-safe'; // Создание токена @@ -63,7 +63,7 @@ try { ## Middleware JWT для Flight (Рекомендуемый подход) -Наиболее распространенный и полезный способ использования JWT с Flight — это как **middleware** для защиты маршрутов API. Вот полный, готовый для производства пример: +Наиболее распространенный и полезный способ использования JWT с Flight — это как **middleware** для защиты маршрутов API. Вот полный, готовый к производству пример: ### Шаг 1: Создание класса JWT Middleware @@ -82,7 +82,7 @@ class JwtMiddleware { public function __construct(Engine $app) { $this->app = $app; - // Храните ваш секретный ключ в app/config/config.php, НЕ жёстко закодированным! + // Храните ваш секретный ключ в app/config/config.php, НЕ хардкодьте! $this->secretKey = $app->get('config')['jwt_secret']; } @@ -119,7 +119,7 @@ class JwtMiddleware { } ``` -### Шаг 2: Регистрация JWT Secret в вашем конфиге +### Шаг 2: Регистрация JWT секрета в вашей конфигурации ```php // app/config/config.php @@ -128,11 +128,11 @@ return [ ]; // app/config/bootstrap.php или index.php -// убедитесь, что добавили эту строку, если хотите сделать конфиг доступным для приложения +// убедитесь, что добавили эту строку, если хотите предоставить конфигурацию приложению $app->set('config', $config); ``` -> **Примечание по безопасности**: Никогда не жёстко кодируйте ваш секретный ключ! Используйте переменные окружения в производстве. +> **Примечание по безопасности**: Никогда не хардкодьте ваш секретный ключ! Используйте переменные окружения в производстве. ### Шаг 3: Защита ваших маршрутов с помощью Middleware @@ -145,7 +145,7 @@ Flight::route('GET /api/user/profile', function() { 'username' => $user->username, 'role' => $user->role ]); -})->addMiddleware( JwtMiddleware::class); +})->addMiddleware(JwtMiddleware::class); // Защита всей группы маршрутов (более распространено!) Flight::group('/api', function() { @@ -156,7 +156,7 @@ Flight::group('/api', function() { }, [ JwtMiddleware::class ]); // Все маршруты в этой группе защищены! ``` -Для получения дополнительной информации о middleware см. [документацию по middleware](/learn/middleware). +Для более подробной информации о middleware см. [документацию по middleware](/learn/middleware). ## Распространенные сценарии использования @@ -170,7 +170,7 @@ Flight::route('POST /api/login', function() { $username = $data->username ?? ''; $password = $data->password ?? ''; - // Проверка учетных данных (пример — используйте свою логику!) + // Валидация учетных данных (пример — используйте свою логику!) $user = validateUserCredentials($username, $password); if (!$user) { @@ -184,7 +184,7 @@ Flight::route('POST /api/login', function() { 'username' => $user->username, 'role' => $user->role, 'iat' => time(), - 'exp' => time() + (60 * 60) // Истекает через 1 час + 'exp' => time() + (60 * 60) // Истечение через 1 час ]; $jwt = JWT::encode($payload, $secretKey, 'HS256'); @@ -197,7 +197,7 @@ Flight::route('POST /api/login', function() { }); function validateUserCredentials($username, $password) { - // Здесь ваш поиск в базе данных и проверка пароля + // Ваш поиск в базе данных и проверка пароля здесь // Пример: $db = Flight::db(); $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); @@ -215,16 +215,16 @@ function validateUserCredentials($username, $password) { ### 2. Поток обновления токена -Реализуйте систему обновления токена для долгоживущих сессий: +Реализуйте систему обновления токенов для долгоживущих сессий: ```php Flight::route('POST /api/login', function() { - // ... проверка учетных данных ... + // ... валидация учетных данных ... $secretKey = Flight::get('config')['jwt_secret']; $refreshSecret = Flight::get('config')['jwt_refresh_secret']; - // Короткоживущий access token (15 минут) + // Короткоживущий токен доступа (15 минут) $accessToken = JWT::encode([ 'user_id' => $user->id, 'type' => 'access', @@ -232,7 +232,7 @@ Flight::route('POST /api/login', function() { 'exp' => time() + (15 * 60) ], $secretKey, 'HS256'); - // Долгоживущий refresh token (7 дней) + // Долгоживущий токен обновления (7 дней) $refreshToken = JWT::encode([ 'user_id' => $user->id, 'type' => 'refresh', @@ -254,12 +254,12 @@ Flight::route('POST /api/refresh', function() { try { $decoded = JWT::decode($refreshToken, new Key($refreshSecret, 'HS256')); - // Проверка, что это refresh token + // Проверка, что это токен обновления if ($decoded->type !== 'refresh') { Flight::jsonHalt(['error' => 'Invalid token type'], 401); } - // Генерация нового access token + // Генерация нового токена доступа $secretKey = Flight::get('config')['jwt_secret']; $accessToken = JWT::encode([ 'user_id' => $decoded->user_id, @@ -281,7 +281,7 @@ Flight::route('POST /api/refresh', function() { ### 3. Контроль доступа на основе ролей -Расширьте ваш middleware для проверки ролей пользователя: +Расширьте ваше middleware для проверки ролей пользователя: ```php class JwtRoleMiddleware { @@ -309,7 +309,7 @@ class JwtRoleMiddleware { } } -// Использование: маршрут только для админов +// Использование: Маршрут только для админов Flight::route('DELETE /api/users/@id', function($id) { // Логика удаления пользователя })->addMiddleware([ @@ -318,7 +318,7 @@ Flight::route('DELETE /api/users/@id', function($id) { ]); ``` -### 4. Публичное API с ограничением скорости по пользователям +### 4. Публичный API с ограничением скорости по пользователю Используйте JWT для отслеживания и ограничения скорости пользователей без сессий: @@ -347,23 +347,23 @@ class RateLimitMiddleware { ### 1. Используйте сильные секретные ключи ```php -// Генерация безопасного секретного ключа (запустите один раз, сохраните в файл .env) +// Генерация безопасного секретного ключа (запустите один раз, сохраните в .env файл) $secretKey = base64_encode(random_bytes(32)); -echo $secretKey; // Сохраните это в вашем файле .env! +echo $secretKey; // Сохраните это в вашем .env файле! ``` ### 2. Храните секреты в переменных окружения ```php -// Никогда не коммитьте секреты в систему контроля версий! -// Используйте файл .env и библиотеку вроде vlucas/phpdotenv +// Никогда не коммитьте секреты в контроль версий! +// Используйте .env файл и библиотеку вроде vlucas/phpdotenv -// Файл .env: +// .env файл: // JWT_SECRET=your-base64-encoded-secret-here // JWT_REFRESH_SECRET=another-base64-encoded-secret-here // Вы также можете использовать файл app/config/config.php для хранения секретов -// просто убедитесь, что файл конфигурации не коммитится в систему контроля версий +// просто убедитесь, что файл конфигурации не коммитится в контроль версий // return [ // 'jwt_secret' => 'your-base64-encoded-secret-here', // 'jwt_refresh_secret' => 'another-base64-encoded-secret-here', @@ -373,29 +373,29 @@ echo $secretKey; // Сохраните это в вашем файле .env! $secretKey = getenv('JWT_SECRET'); ``` -### 3. Устанавливайте подходящие сроки действия +### 3. Устанавливайте подходящие сроки истечения ```php -// Хорошая практика: короткоживущие access tokens +// Хорошая практика: короткоживущие токены доступа 'exp' => time() + (15 * 60) // 15 минут -// Для refresh tokens: более длинный срок действия +// Для токенов обновления: более длинное истечение 'exp' => time() + (7 * 24 * 60 * 60) // 7 дней ``` ### 4. Используйте HTTPS в производстве -JWT должны **всегда** передаваться по HTTPS. Никогда не отправляйте токены по обычному HTTP в производстве! +JWT **всегда** должны передаваться по HTTPS. Никогда не отправляйте токены по обычному HTTP в производстве! -### 5. Проверяйте утверждения токена +### 5. Валидируйте утверждения токена -Всегда проверяйте утверждения, которые вас интересуют: +Всегда валидируйте утверждения, которые вас интересуют: ```php $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); -// Проверка истечения срока действия обрабатывается библиотекой автоматически -// Но вы можете добавить пользовательские проверки: +// Проверка истечения обрабатывается библиотекой автоматически +// Но вы можете добавить кастомные валидации: if ($decoded->iat > time()) { throw new Exception('Token used before it was issued'); } @@ -415,17 +415,17 @@ Flight::route('POST /api/logout', function() { preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches); $jwt = $matches[1]; - // Извлечение срока действия токена + // Извлечение срока истечения токена $decoded = Flight::request()->data->user; $ttl = $decoded->exp - time(); - // Сохранение в кэше/redis до истечения срока действия + // Сохранение в кэше/redis до истечения Flight::cache()->set("blacklist:$jwt", true, $ttl); Flight::json(['message' => 'Successfully logged out']); }); -// Добавьте в ваш JwtMiddleware: +// Добавьте в ваше JwtMiddleware: public function before(array $params) { // ... извлечение JWT ... @@ -453,7 +453,7 @@ $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); ### Асимметричные алгоритмы (RSA/ECDSA) - **RS256**, **RS384**, **RS512**: Использует пары публичный/приватный ключ -- **ES256**, **ES384**, **ES512**: Варианты на основе эллиптических кривых +- **ES256**, **ES384**, **ES512**: Варианты на эллиптических кривых ```php // Генерация ключей: openssl genrsa -out private.key 2048 @@ -479,12 +479,12 @@ $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); ### "Signature verification failed" - Вы используете другой секретный ключ для декодирования, чем для кодирования - Токен был изменен -- Расхождение во времени между серверами (добавьте буфер leeway) +- Разница во времени между серверами (добавьте буфер leeway) ```php use Firebase\JWT\JWT; -JWT::$leeway = 60; // Разрешить 60 секунд расхождения во времени +JWT::$leeway = 60; // Разрешить 60 секунд разницы во времени $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); ``` @@ -506,8 +506,8 @@ fetch('/api/users', { - `JWT::encode(array $payload, string $key, string $alg)`: Создает JWT из полезной нагрузки - `JWT::decode(string $jwt, Key $key)`: Декодирует и проверяет JWT -- `JWT::urlsafeB64Encode(string $input)`: Base64-кодирование, безопасное для URL -- `JWT::urlsafeB64Decode(string $input)`: Base64-декодирование, безопасное для URL +- `JWT::urlsafeB64Encode(string $input)`: Base64 кодирование безопасное для URL +- `JWT::urlsafeB64Decode(string $input)`: Base64 декодирование безопасное для URL - `JWT::$leeway`: Статическое свойство для установки временного leeway для валидации (в секундах) ## Почему использовать эту библиотеку? @@ -516,8 +516,8 @@ fetch('/api/users', { - **Активное обслуживание**: Поддерживается командой Google/Firebase - **Фокус на безопасности**: Регулярные обновления и патчи безопасности - **Простой API**: Легко понять и реализовать -- **Хорошо задокументировано**: Обширная документация и поддержка сообщества -- **Гибкость**: Поддерживает несколько алгоритмов и настраиваемые опции +- **Хорошо документировано**: Обширная документация и поддержка сообщества +- **Гибко**: Поддерживает несколько алгоритмов и настраиваемые опции ## См. также @@ -529,4 +529,4 @@ fetch('/api/users', { ## Лицензия -Библиотека Firebase JWT лицензирована по лицензии BSD 3-Clause. См. [репозиторий на Github](https://github.com/firebase/php-jwt) для деталей. \ No newline at end of file +Библиотека Firebase JWT лицензирована по BSD 3-Clause License. См. [репозиторий на Github](https://github.com/firebase/php-jwt) для деталей. \ No newline at end of file diff --git a/content/v3/ru/awesome-plugins/runway.md b/content/v3/ru/awesome-plugins/runway.md index 8b468b1c..6d3501a5 100644 --- a/content/v3/ru/awesome-plugins/runway.md +++ b/content/v3/ru/awesome-plugins/runway.md @@ -14,7 +14,7 @@ composer require flightphp/runway ## Базовая конфигурация -В первый раз при запуске Runway попытается найти конфигурацию `runway` в `app/config/config.php` через ключ `'runway'`. +Впервые запустив Runway, оно попытается найти конфигурацию `runway` в `app/config/config.php` через ключ `'runway'`. ```php hello'); @@ -192,7 +192,7 @@ Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); #### `path()` не определен В скелетном приложении это определено внутри файла `config.php`, но чтобы ваши классы были найдены, вам нужно убедиться, что метод `path()` -определен (вероятно, к корню вашего каталога) до того, как вы попытаетесь его использовать. +определен (вероятно, к корню вашей директории) до того, как вы попытаетесь его использовать. ```php // Добавьте путь к автозагрузчику diff --git a/content/v3/ru/learn/learn.md b/content/v3/ru/learn/learn.md index c82319ef..7e83b69e 100644 --- a/content/v3/ru/learn/learn.md +++ b/content/v3/ru/learn/learn.md @@ -1,6 +1,6 @@ -# Изучите Flight +# Узнайте о Flight -Flight — это быстрый, простой и расширяемый фреймворк для PHP. Он довольно универсален и может использоваться для создания любого вида веб-приложения. +Flight — это быстрый, простой и расширяемый фреймворк для PHP. Он довольно универсален и может использоваться для создания любого типа веб-приложения. Он создан с учетом простоты и написан таким образом, чтобы его было легко понять и использовать. > **Примечание:** Вы увидите примеры, которые используют `Flight::` как статическую переменную, и некоторые, которые используют объект движка `$app->`. Оба работают взаимозаменяемо друг с другом. `$app` и `$this->app` в контроллере/промежуточном ПО — это рекомендуемый подход от команды Flight. @@ -17,7 +17,7 @@ Flight — это быстрый, простой и расширяемый фр ### [Автозагрузка](/learn/autoloading) -Узнайте, как автозагружать свои собственные классы в вашем приложении. +Узнайте, как автозагружать свои собственные классы в приложении. ### [Запросы](/learn/requests) @@ -45,7 +45,7 @@ Flight — это быстрый, простой и расширяемый фр ### [Расширение Flight](/learn/extending) -Узнайте, как расширять фреймворк, добавляя свои собственные методы и классы. +Узнайте, как расширить фреймворк, добавив свои собственные методы и классы. ### [Хуки методов и фильтрация](/learn/filtering) @@ -65,9 +65,13 @@ Flight — это быстрый, простой и расширяемый фр Это несколько простых функций, чтобы сделать кодирование и декодирование вашего JSON последовательным. -### [Обертка PDO](/learn/pdo-wrapper) +### [SimplePdo](/learn/simple-pdo) -PDO иногда может добавлять больше головной боли, чем необходимо. Этот простой класс-обертка может значительно упростить взаимодействие с вашей базой данных. +PDO иногда может вызывать больше головной боли, чем необходимо. SimplePdo — это современный вспомогательный класс PDO с удобными методами, такими как `insert()`, `update()`, `delete()` и `transaction()`, чтобы сделать операции с базой данных гораздо проще. + +### [PdoWrapper](/learn/pdo-wrapper) (Устаревший) + +Оригинальная обертка PDO устарела начиная с версии v3.18.0. Пожалуйста, используйте [SimplePdo](/learn/simple-pdo) вместо этого. ### [Обработчик загруженных файлов](/learn/uploaded-file) @@ -75,9 +79,9 @@ PDO иногда может добавлять больше головной б ## Важные концепции -### [Почему фреймворк?](/learn/why-frameworks) +### [Зачем фреймворк?](/learn/why-frameworks) -Вот короткая статья о том, почему вы должны использовать фреймворк. Это хорошая идея понять преимущества использования фреймворка, прежде чем начать его использовать. +Вот краткая статья о том, почему вы должны использовать фреймворк. Хорошо понять преимущества использования фреймворка перед тем, как начать его использовать. Кроме того, отличный учебник создан [@lubiana](https://git.php.fail/lubiana). Хотя он не углубляется в детали конкретно о Flight, это руководство поможет вам понять некоторые из основных концепций, окружающих фреймворк, и почему они полезны. diff --git a/content/v3/ru/learn/pdo_wrapper.md b/content/v3/ru/learn/pdo_wrapper.md index e4e82e8f..8559c0f8 100644 --- a/content/v3/ru/learn/pdo_wrapper.md +++ b/content/v3/ru/learn/pdo_wrapper.md @@ -1,18 +1,22 @@ -# PdoWrapper Вспомогательный класс PDO +# PdoWrapper Класс-помощник PDO + +> **ПРЕДУПРЕЖДЕНИЕ** +> +> **Устарело:** `PdoWrapper` устарел начиная с Flight v3.18.0. Он не будет удален в будущих версиях, но будет поддерживаться для обратной совместимости. Пожалуйста, используйте [SimplePdo](/learn/simple-pdo) вместо него, который предлагает те же функции плюс дополнительные вспомогательные методы для распространенных операций с базой данных. ## Обзор -Класс `PdoWrapper` в Flight — это удобный помощник для работы с базами данных с использованием PDO. Он упрощает распространенные задачи работы с базами данных, добавляет полезные методы для получения результатов и возвращает результаты в виде [Collections](/learn/collections) для легкого доступа. Он также поддерживает логирование запросов и мониторинг производительности приложений (APM) для продвинутых сценариев использования. +Класс `PdoWrapper` в Flight — это удобный помощник для работы с базами данных с использованием PDO. Он упрощает распространенные задачи с базами данных, добавляет полезные методы для получения результатов и возвращает результаты в виде [Collections](/learn/collections) для легкого доступа. Он также поддерживает логирование запросов и мониторинг производительности приложений (APM) для продвинутых случаев использования. ## Понимание -Работа с базами данных в PHP может быть немного многословной, особенно при прямом использовании PDO. `PdoWrapper` расширяет PDO и добавляет методы, которые делают запросы, получение и обработку результатов гораздо проще. Вместо жонглирования подготовленными выражениями и режимами получения, вы получаете простые методы для распространенных задач, и каждая строка возвращается как Collection, чтобы вы могли использовать нотацию массива или объекта. +Работа с базами данных в PHP может быть немного многословной, особенно при прямом использовании PDO. `PdoWrapper` расширяет PDO и добавляет методы, которые делают запросы, получение и обработку результатов гораздо проще. Вместо жонглирования подготовленными выражениями и режимами получения вы получаете простые методы для распространенных задач, и каждая строка возвращается как Collection, так что вы можете использовать нотацию массива или объекта. Вы можете зарегистрировать `PdoWrapper` как общую службу в Flight, а затем использовать его в любом месте вашего приложения через `Flight::db()`. -## Базовое использование +## Основное использование -### Регистрация вспомогательного PDO +### Регистрация помощника PDO Сначала зарегистрируйте класс `PdoWrapper` в Flight: @@ -27,7 +31,7 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ ]); ``` -Теперь вы можете использовать `Flight::db()` в любом месте для получения подключения к базе данных. +Теперь вы можете использовать `Flight::db()` в любом месте для получения соединения с базой данных. ### Выполнение запросов @@ -45,7 +49,7 @@ while ($row = $statement->fetch()) { } ``` -Вы также можете использовать его для записи: +Вы также можете использовать это для записей: ```php $db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); @@ -66,7 +70,7 @@ $count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", `function fetchRow(string $sql, array $params = []): Collection` -Получите одну строку как Collection (доступ как к массиву/объекту): +Получите одну строку как Collection (доступ по массиву/объекту): ```php $user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); @@ -92,7 +96,7 @@ foreach ($users as $user) { ### Использование заполнителей `IN()` -Вы можете использовать один `?` в предложении `IN()` и передать массив или строку с разделителями-запятыми: +Вы можете использовать один `?` в предложении `IN()` и передать массив или строку, разделенную запятыми: ```php $ids = [1, 2, 3]; @@ -109,7 +113,7 @@ $users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", ['1,2,3'] ```php Flight::register('db', \flight\database\PdoWrapper::class, [ - 'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [/* options */], true // last param enables APM + 'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [/* options */], true // последний параметр включает APM ]); ``` @@ -119,7 +123,7 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ Flight::db()->logQueries(); ``` -Это запустит событие (`flight.db.queries`) с метриками подключения и запросов, на которое вы можете подписаться с помощью системы событий Flight. +Это вызовет событие (`flight.db.queries`) с метриками соединения и запросов, которые вы можете прослушивать с помощью системы событий Flight. ### Полный пример @@ -166,10 +170,10 @@ Flight::route('/users', function () { ## Устранение неисправностей -- Если вы получаете ошибку о подключении к базе данных, проверьте DSN, имя пользователя, пароль и опции. -- Все строки возвращаются как Collections — если вам нужен обычный массив, используйте `$collection->getData()`. -- Для запросов `IN (?)` убедитесь, что вы передаете массив или строку с разделителями-запятыми. +- Если вы получаете ошибку о соединении с базой данных, проверьте ваш DSN, имя пользователя, пароль и опции. +- Все строки возвращаются как Collections — если вам нужен простой массив, используйте `$collection->getData()`. +- Для запросов `IN (?)` убедитесь, что вы передаете массив или строку, разделенную запятыми. ## Журнал изменений -- v3.2.0 - Первое выпущение PdoWrapper с базовыми методами запросов и получения. \ No newline at end of file +- v3.2.0 - Первоначальный выпуск PdoWrapper с базовыми методами запросов и получения. \ No newline at end of file diff --git a/content/v3/ru/learn/simple_pdo.md b/content/v3/ru/learn/simple_pdo.md new file mode 100644 index 00000000..477ef265 --- /dev/null +++ b/content/v3/ru/learn/simple_pdo.md @@ -0,0 +1,320 @@ +# Класс помощника SimplePdo PDO + +## Обзор + +Класс `SimplePdo` в Flight — это современный, функциональный помощник для работы с базами данных с использованием PDO. Он расширяет `PdoWrapper` и добавляет удобные методы-помощники для распространённых операций с базой данных, таких как `insert()`, `update()`, `delete()` и транзакции. Он упрощает задачи работы с базой данных, возвращает результаты в виде [Collections](/learn/collections) для лёгкого доступа и поддерживает логирование запросов и мониторинг производительности приложений (APM) для продвинутых сценариев использования. + +## Понимание + +Класс `SimplePdo` предназначен для упрощения работы с базами данных в PHP. Вместо манипуляций с подготовленными выражениями, режимами выборки и многословными SQL-операциями вы получаете чистые, простые методы для распространённых задач. Каждая строка возвращается как Collection, так что вы можете использовать нотацию массива (`$row['name']`) и нотацию объекта (`$row->name`). + +Этот класс является суперкомплектом `PdoWrapper`, то есть включает всю функциональность `PdoWrapper` плюс дополнительные методы-помощники, которые делают ваш код чище и удобнее в поддержке. Если вы сейчас используете `PdoWrapper`, переход на `SimplePdo` будет простым, поскольку он расширяет `PdoWrapper`. + +Вы можете зарегистрировать `SimplePdo` как общую службу в Flight, а затем использовать её в любом месте вашего приложения через `Flight::db()`. + +## Основное использование + +### Регистрация SimplePdo + +Сначала зарегистрируйте класс `SimplePdo` в Flight: + +```php +Flight::register('db', \flight\database\SimplePdo::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 + ] +]); +``` + +> **ПРИМЕЧАНИЕ** +> +> Если вы не укажете `PDO::ATTR_DEFAULT_FETCH_MODE`, `SimplePdo` автоматически установит его в `PDO::FETCH_ASSOC` за вас. + +Теперь вы можете использовать `Flight::db()` в любом месте для получения соединения с базой данных. + +### Выполнение запросов + +#### `runQuery()` + +`function runQuery(string $sql, array $params = []): PDOStatement` + +Используйте это для INSERT, UPDATE или когда вы хотите вручную получить результаты: + +```php +$db = Flight::db(); +$statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']); +while ($row = $statement->fetch()) { + // $row is an array +} +``` + +Вы также можете использовать его для операций записи: + +```php +$db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); +$db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]); +``` + +#### `fetchField()` + +`function fetchField(string $sql, array $params = []): mixed` + +Получите одно значение из базы данных: + +```php +$count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']); +``` + +#### `fetchRow()` + +`function fetchRow(string $sql, array $params = []): ?Collection` + +Получите одну строку как Collection (доступ как к массиву/объекту): + +```php +$user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); +echo $user['name']; +// or +echo $user->name; +``` + +> **СОВЕТ** +> +> `SimplePdo` автоматически добавляет `LIMIT 1` к запросам `fetchRow()`, если он ещё не присутствует, что делает ваши запросы более эффективными. + +#### `fetchAll()` + +`function fetchAll(string $sql, array $params = []): array` + +Получите все строки как массив Collections: + +```php +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); +foreach ($users as $user) { + echo $user['name']; + // or + echo $user->name; +} +``` + +#### `fetchColumn()` + +`function fetchColumn(string $sql, array $params = []): array` + +Выберите одну колонку как массив: + +```php +$ids = Flight::db()->fetchColumn("SELECT id FROM users WHERE active = ?", [1]); +// Returns: [1, 2, 3, 4, 5] +``` + +#### `fetchPairs()` + +`function fetchPairs(string $sql, array $params = []): array` + +Выберите результаты как пары ключ-значение (первая колонка как ключ, вторая как значение): + +```php +$userNames = Flight::db()->fetchPairs("SELECT id, name FROM users"); +// Returns: [1 => 'John', 2 => 'Jane', 3 => 'Bob'] +``` + +### Использование заполнителей `IN()` + +Вы можете использовать один `?` в предложении `IN()` и передать массив: + +```php +$ids = [1, 2, 3]; +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); +``` + +## Методы-помощники + +Одно из главных преимуществ `SimplePdo` по сравнению с `PdoWrapper` — добавление удобных методов-помощников для распространённых операций с базой данных. + +### `insert()` + +`function insert(string $table, array $data): string` + +Вставьте одну или несколько строк и верните ID последней вставки. + +**Одиночная вставка:** + +```php +$id = Flight::db()->insert('users', [ + 'name' => 'John', + 'email' => 'john@example.com' +]); +``` + +**Пакетная вставка:** + +```php +$id = Flight::db()->insert('users', [ + ['name' => 'John', 'email' => 'john@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'], +]); +``` + +### `update()` + +`function update(string $table, array $data, string $where, array $whereParams = []): int` + +Обновите строки и верните количество затронутых строк: + +```php +$affected = Flight::db()->update( + 'users', + ['name' => 'Jane', 'email' => 'jane@example.com'], + 'id = ?', + [1] +); +``` + +> **ПРИМЕЧАНИЕ** +> +> В SQLite `rowCount()` возвращает количество строк, где данные действительно изменились. Если вы обновляете строку с теми же значениями, которые у неё уже есть, `rowCount()` вернёт 0. Это отличается от поведения MySQL при использовании `PDO::MYSQL_ATTR_FOUND_ROWS`. + +### `delete()` + +`function delete(string $table, string $where, array $whereParams = []): int` + +Удалите строки и верните количество удалённых строк: + +```php +$deleted = Flight::db()->delete('users', 'id = ?', [1]); +``` + +### `transaction()` + +`function transaction(callable $callback): mixed` + +Выполните обратный вызов в рамках транзакции. Транзакция автоматически фиксируется при успехе или откатывается при ошибке: + +```php +$result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John']); + $db->insert('logs', ['action' => 'user_created']); + return $db->lastInsertId(); +}); +``` + +Если в обратном вызове возникает любое исключение, транзакция автоматически откатывается, и исключение повторно выбрасывается. + +## Продвинутое использование + +### Логирование запросов и APM + +Если вы хотите отслеживать производительность запросов, включите отслеживание APM при регистрации: + +```php +Flight::register('db', \flight\database\SimplePdo::class, [ + 'mysql:host=localhost;dbname=cool_db_name', + 'user', + 'pass', + [/* PDO options */], + [ + 'trackApmQueries' => true, + 'maxQueryMetrics' => 1000 + ] +]); +``` + +После выполнения запросов вы можете логировать их вручную, но APM будет логировать их автоматически, если включено: + +```php +Flight::db()->logQueries(); +``` + +Это вызовет событие (`flight.db.queries`) с метриками соединения и запросов, на которое вы можете подписаться с помощью системы событий Flight. + +### Полный пример + +```php +Flight::route('/users', function () { + // Get all users + $users = Flight::db()->fetchAll('SELECT * FROM users'); + + // Stream all users + $statement = Flight::db()->runQuery('SELECT * FROM users'); + while ($user = $statement->fetch()) { + echo $user['name']; + } + + // Get a single user + $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); + + // Get a single value + $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); + + // Get a single column + $ids = Flight::db()->fetchColumn('SELECT id FROM users'); + + // Get key-value pairs + $userNames = Flight::db()->fetchPairs('SELECT id, name FROM users'); + + // Special IN() syntax + $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); + + // Insert a new user + $id = Flight::db()->insert('users', [ + 'name' => 'Bob', + 'email' => 'bob@example.com' + ]); + + // Bulk insert users + Flight::db()->insert('users', [ + ['name' => 'Bob', 'email' => 'bob@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'] + ]); + + // Update a user + $affected = Flight::db()->update('users', ['name' => 'Bob'], 'id = ?', [123]); + + // Delete a user + $deleted = Flight::db()->delete('users', 'id = ?', [123]); + + // Use a transaction + $result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John', 'email' => 'john@example.com']); + $db->insert('audit_log', ['action' => 'user_created']); + return $db->lastInsertId(); + }); +}); +``` + +## Миграция с PdoWrapper + +Если вы сейчас используете `PdoWrapper`, миграция на `SimplePdo` будет простой: + +1. **Обновите вашу регистрацию:** + ```php + // Old + Flight::register('db', \flight\database\PdoWrapper::class, [ /* ... */ ]); + + // New + Flight::register('db', \flight\database\SimplePdo::class, [ /* ... */ ]); + ``` + +2. **Все существующие методы `PdoWrapper` работают в `SimplePdo`** — Нет разрушительных изменений. Ваш существующий код продолжит работать. + +3. **Опционально используйте новые методы-помощники** — Начните использовать `insert()`, `update()`, `delete()` и `transaction()` для упрощения вашего кода. + +## См. также + +- [Collections](/learn/collections) — Узнайте, как использовать класс Collection для лёгкого доступа к данным. +- [PdoWrapper](/learn/pdo-wrapper) — Устаревший класс помощника PDO (устарел). + +## Устранение неисправностей + +- Если вы получаете ошибку о соединении с базой данных, проверьте ваш DSN, имя пользователя, пароль и опции. +- Все строки возвращаются как Collections — если вам нужен простой массив, используйте `$collection->getData()`. +- Для запросов `IN (?)` убедитесь, что вы передаёте массив. +- Если вы испытываете проблемы с памятью при логировании запросов в долгоживущих процессах, настройте опцию `maxQueryMetrics`. + +## Журнал изменений + +- v3.18.0 — Первое выпуски SimplePdo с методами-помощниками для insert, update, delete и транзакций. \ No newline at end of file diff --git a/content/v3/uk/awesome-plugins/awesome_plugins.md b/content/v3/uk/awesome-plugins/awesome_plugins.md index 4897ce0c..19975f65 100644 --- a/content/v3/uk/awesome-plugins/awesome_plugins.md +++ b/content/v3/uk/awesome-plugins/awesome_plugins.md @@ -1,102 +1,103 @@ -# Класні Плагіни +# Круті Плагіни -Flight є надзвичайно розширюваним. Існує низка плагінів, які можна використовувати для додавання функціональності до вашої програми Flight. Деякі з них офіційно підтримуються командою Flight, а інші є мікро/лайт бібліотеками, щоб допомогти вам розпочати. +Flight є надзвичайно розширюваним. Існує низка плагінів, які можна використовувати для додавання функціональності до вашого додатка Flight. Деякі з них офіційно підтримуються командою Flight, а інші є мікро/лайт бібліотеками, щоб допомогти вам розпочати роботу. ## Документація API -Документація API є критичною для будь-якого API. Вона допомагає розробникам зрозуміти, як взаємодіяти з вашим API та що очікувати натомість. Існує кілька інструментів, доступних для допомоги у генерації документації API для ваших проєктів Flight. +Документація API є критичною для будь-якого API. Вона допомагає розробникам зрозуміти, як взаємодіяти з вашим API та що очікувати у відповідь. Існує кілька інструментів, доступних для допомоги у генерації документації API для ваших проєктів Flight. -- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Блог-пост, написаний Даніелем Шрайбером, про те, як використовувати специфікацію OpenAPI з FlightPHP для побудови вашого API з використанням підходу API first. -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI є чудовим інструментом для допомоги у генерації документації API для ваших проєктів Flight. Його дуже легко використовувати, і його можна налаштувати відповідно до ваших потреб. Це PHP-бібліотека для допомоги у генерації документації Swagger. +- [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - Блог-пост, написаний Даніелем Шрайбером, про те, як використовувати специфікацію OpenAPI з FlightPHP для побудови вашого API з використанням підходу API першим. +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI є чудовим інструментом для допомоги у генерації документації API для ваших проєктів Flight. Його дуже легко використовувати, і його можна налаштувати під ваші потреби. Це PHP-бібліотека для допомоги у генерації документації Swagger. -## Моніторинг Продуктивності Застосунків (APM) +## Моніторинг Продуктивності Додатків (APM) -Моніторинг продуктивності застосунків (APM) є критичним для будь-якої програми. Він допомагає вам зрозуміти, як працює ваша програма та де є вузькі місця. Існує низка інструментів APM, які можна використовувати з Flight. -- official [flightphp/apm](/awesome-plugins/apm) - Flight APM є простою бібліотекою APM, яка може бути використана для моніторингу ваших програм Flight. Її можна використовувати для моніторингу продуктивності вашої програми та допомоги у виявленні вузьких місць. +Моніторинг продуктивності додатків (APM) є критичним для будь-якого додатка. Він допомагає вам зрозуміти, як працює ваш додаток і де знаходяться вузькі місця. Існує низка інструментів APM, які можна використовувати з Flight. +- official [flightphp/apm](/awesome-plugins/apm) - Flight APM є простою бібліотекою APM, яка може використовуватися для моніторингу ваших додатків Flight. Її можна використовувати для моніторингу продуктивності вашого додатка та допомоги у виявленні вузьких місць. ## Асинхронність Flight вже є швидким фреймворком, але додавання до нього турбо-двигуна робить все більш веселим (і складним)! -- [flightphp/async](/awesome-plugins/async) - Офіційна бібліотека Flight Async. Ця бібліотека є простим способом додати асинхронну обробку до вашої програми. Вона використовує Swoole/Openswoole під капотом, щоб надати простий та ефективний спосіб запуску завдань асинхронно. +- [flightphp/async](/awesome-plugins/async) - Офіційна бібліотека Flight Async. Ця бібліотека є простим способом додати асинхронну обробку до вашого додатка. Вона використовує Swoole/Openswoole під капотом, щоб надати простий та ефективний спосіб запуску завдань асинхронно. ## Авторизація/Дозволи -Авторизація та дозволи є критичними для будь-якої програми, яка вимагає контролю за тим, хто може отримати доступ до чого. +Авторизація та дозволи є критичними для будь-якого додатка, який вимагає контролю над тим, хто може отримати доступ до чого. -- official [flightphp/permissions](/awesome-plugins/permissions) - Офіційна бібліотека Flight Permissions. Ця бібліотека є простим способом додати дозволи на рівні користувача та програми до вашої програми. +- official [flightphp/permissions](/awesome-plugins/permissions) - Офіційна бібліотека Flight Permissions. Ця бібліотека є простим способом додати дозволи на рівні користувача та додатка до вашого додатка. ## Аутентифікація -Аутентифікація є суттєвою для програм, які потребують перевірки ідентичності користувача та захисту кінцевих точок API. +Аутентифікація є суттєвою для додатків, які потребують перевірки ідентичності користувача та захисту кінцевих точок API. -- [firebase/php-jwt](/awesome-plugins/jwt) - Бібліотека JSON Web Token (JWT) для PHP. Простий та безпечний спосіб реалізувати аутентифікацію на основі токенів у ваших програмах Flight. Ідеально для безстанної аутентифікації API, захисту маршрутів з middleware та реалізації потоків авторизації в стилі OAuth. +- [firebase/php-jwt](/awesome-plugins/jwt) - Бібліотека JSON Web Token (JWT) для PHP. Простий та безпечний спосіб реалізувати аутентифікацію на основі токенів у ваших додатках Flight. Ідеально для безстанної аутентифікації API, захисту маршрутів з middleware та реалізації потоків авторизації у стилі OAuth. ## Кешування -Кешування є чудовим способом прискорити вашу програму. Існує низка бібліотек кешування, які можна використовувати з Flight. +Кешування є чудовим способом прискорити ваш додаток. Існує низка бібліотек кешування, які можна використовувати з Flight. -- official [flightphp/cache](/awesome-plugins/php-file-cache) - Легка, проста та автономна PHP-клас кешування в файлі +- official [flightphp/cache](/awesome-plugins/php-file-cache) - Легка, проста та автономна PHP-клас для кешування у файлі ## CLI -CLI-програми є чудовим способом взаємодіяти з вашою програмою. Ви можете використовувати їх для генерації контролерів, відображення всіх маршрутів та багато іншого. +CLI-додатки є чудовим способом взаємодіяти з вашим додатком. Ви можете використовувати їх для генерації контролерів, відображення всіх маршрутів та інше. -- official [flightphp/runway](/awesome-plugins/runway) - Runway є CLI-програмою, яка допомагає вам керувати вашими програмами Flight. +- official [flightphp/runway](/awesome-plugins/runway) - Runway є CLI-додатком, який допомагає вам керувати вашими додатками Flight. -## Кукі +## Куки -Кукі є чудовим способом зберігати малі фрагменти даних на стороні клієнта. Їх можна використовувати для зберігання уподобань користувача, налаштувань програми та багато іншого. +Кукі є чудовим способом зберігати малі частини даних на стороні клієнта. Їх можна використовувати для зберігання уподобань користувача, налаштувань додатка та інше. -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie є PHP-бібліотекою, яка надає простий та ефективний спосіб керування кукі. +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie є PHP-бібліотекою, яка надає простий та ефективний спосіб керувати куками. ## Налагодження Налагодження є критичним, коли ви розробляєте у локальному середовищі. Існує кілька плагінів, які можуть покращити ваш досвід налагодження. -- [tracy/tracy](/awesome-plugins/tracy) - Це повнофункціональний обробник помилок, який можна використовувати з Flight. Він має низку панелей, які можуть допомогти вам налагоджувати вашу програму. Його також дуже легко розширювати та додавати власні панелі. +- [tracy/tracy](/awesome-plugins/tracy) - Це повнофункціональний обробник помилок, який можна використовувати з Flight. Він має низку панелей, які можуть допомогти вам налагоджувати ваш додаток. Його також дуже легко розширювати та додавати власні панелі. - official [flightphp/tracy-extensions](/awesome-plugins/tracy-extensions) - Використовується з обробником помилок [Tracy](/awesome-plugins/tracy), цей плагін додає кілька додаткових панелей для допомоги з налагодженням спеціально для проєктів Flight. ## Бази Даних -Бази даних є основою для більшості програм. Це спосіб зберігати та отримувати дані. Деякі бібліотеки баз даних є просто обгортками для написання запитів, а деякі є повноцінними ORM. +Бази даних є основою для більшості додатків. Це спосіб зберігати та отримувати дані. Деякі бібліотеки баз даних є просто обгортками для написання запитів, а деякі є повноцінними ORM. -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Офіційна обгортка Flight PDO, яка є частиною ядра. Це проста обгортка для спрощення процесу написання запитів та їх виконання. Це не ORM. -- official [flightphp/active-record](/awesome-plugins/active-record) - Офіційна ORM/Mapper Flight ActiveRecord. Чудова маленька бібліотека для легкого отримання та зберігання даних у вашій базі даних. +- official [flightphp/core SimplePdo](/learn/simple-pdo) - Офіційний помічник Flight PDO, який є частиною ядра. Це сучасна обгортка з зручними методами-помічниками, такими як `insert()`, `update()`, `delete()` та `transaction()`, щоб спростити операції з базою даних. Усі результати повертаються як Collections для гнучкого доступу до масивів/об'єктів. Не ORM, просто кращий спосіб працювати з PDO. +- deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Офіційна обгортка Flight PDO, яка є частиною ядра (застаріла з v3.18.0). Використовуйте SimplePdo замість. +- official [flightphp/active-record](/awesome-plugins/active-record) - Офіційний ORM/Mapper Flight ActiveRecord. Чудова маленька бібліотека для легкого отримання та зберігання даних у вашій базі даних. - [byjg/php-migration](/awesome-plugins/migrations) - Плагін для відстеження всіх змін бази даних для вашого проєкту. ## Шифрування -Шифрування є критичним для будь-якої програми, яка зберігає чутливі дані. Шифрування та дешифрування даних не є надто складним, але правильне зберігання ключа шифрування [може](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [бути](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [складним](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Найважливіше — ніколи не зберігати ключ шифрування в публічній директорії або комітити його до вашого репозиторію коду. +Шифрування є критичним для будь-якого додатка, який зберігає чутливі дані. Шифрування та дешифрування даних не є надто складним, але правильне зберігання ключа шифрування [може](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [бути](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [складним](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Найважливіше — ніколи не зберігати ключ шифрування у публічній директорії або комітити його до репозиторію коду. -- [defuse/php-encryption](/awesome-plugins/php-encryption) - Це бібліотека, яка може бути використана для шифрування та дешифрування даних. Запуск та налаштування є досить простим для початку шифрування та дешифрування даних. +- [defuse/php-encryption](/awesome-plugins/php-encryption) - Це бібліотека, яку можна використовувати для шифрування та дешифрування даних. Запуск є досить простим, щоб почати шифрувати та дешифрувати дані. ## Черга Завдань -Черги завдань є дуже корисними для асинхронної обробки завдань. Це може бути надсилання email, обробка зображень або будь-що, що не потребує реального часу. +Черги завдань дійсно корисні для асинхронної обробки завдань. Це може бути відправка email, обробка зображень або будь-що, що не потребує реального часу. -- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue є бібліотекою, яка може бути використана для асинхронної обробки завдань. Її можна використовувати з beanstalkd, MySQL/MariaDB, SQLite та PostgreSQL. +- [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue є бібліотекою, яку можна використовувати для асинхронної обробки завдань. Її можна використовувати з beanstalkd, MySQL/MariaDB, SQLite та PostgreSQL. ## Сесії -Сесії не є особливо корисними для API, але для побудови веб-програми сесії можуть бути критичними для підтримки стану та інформації про вхід. +Сесії не дуже корисні для API, але для побудови веб-додатка сесії можуть бути критичними для підтримки стану та інформації про вхід. -- official [flightphp/session](/awesome-plugins/session) - Офіційна бібліотека Flight Session. Це проста бібліотека сесій, яка може бути використана для зберігання та отримання даних сесії. Вона використовує вбудоване керування сесіями PHP. +- official [flightphp/session](/awesome-plugins/session) - Офіційна бібліотека Flight Session. Це проста бібліотека сесій, яку можна використовувати для зберігання та отримання даних сесії. Вона використовує вбудоване керування сесіями PHP. - [Ghostff/Session](/awesome-plugins/ghost-session) - PHP Session Manager (неблокуючий, flash, сегмент, шифрування сесії). Використовує PHP open_ssl для опціонального шифрування/дешифрування даних сесії. ## Шаблонізація -Шаблонізація є основою для будь-якої веб-програми з UI. Існує низка рушіїв шаблонізації, які можна використовувати з Flight. +Шаблонізація є основою для будь-якого веб-додатка з UI. Існує низка рушіїв шаблонізації, які можна використовувати з Flight. - deprecated [flightphp/core View](/learn#views) - Це дуже базовий рушій шаблонізації, який є частиною ядра. Не рекомендується використовувати, якщо у вашому проєкті більше кількох сторінок. -- [latte/latte](/awesome-plugins/latte) - Latte є повнофункціональним рушієм шаблонізації, який дуже легко використовувати та відчувається ближчим до синтаксису PHP, ніж Twig чи Smarty. Його також дуже легко розширювати та додавати власні фільтри та функції. -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate є потужним PHP-рушієм шаблонів з компіляцією активів, успадкуванням шаблонів та обробкою змінних. Має автоматичне мініфікацію CSS/JS, кешування, кодування Base64 та опціональну інтеграцію з фреймворком Flight PHP. +- [latte/latte](/awesome-plugins/latte) - Latte є повнофункціональним рушієм шаблонізації, який дуже легко використовувати та ближчий до синтаксису PHP, ніж Twig чи Smarty. Його також дуже легко розширювати та додавати власні фільтри та функції. +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate є потужним PHP-рушієм шаблонів з компіляцією активів, успадкуванням шаблонів та обробкою змінних. Має автоматичну мініфікацію CSS/JS, кешування, кодування Base64 та опціональну інтеграцію з фреймворком Flight PHP. ## Інтеграція з WordPress Хочете використовувати Flight у вашому проєкті WordPress? Є зручний плагін для цього! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Цей плагін WordPress дозволяє запускати Flight поруч з WordPress. Він ідеальний для додавання кастомних API, мікросервісів або навіть повноцінних програм до вашого сайту WordPress з використанням фреймворку Flight. Надзвичайно корисний, якщо ви хочете найкраще з обох світів! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - Цей плагін WordPress дозволяє запускати Flight поруч з WordPress. Він ідеальний для додавання кастомних API, мікросервісів або навіть повних додатків до вашого сайту WordPress з використанням фреймворку Flight. Надзвичайно корисний, якщо ви хочете найкраще з обох світів! ## Внесок diff --git a/content/v3/uk/awesome-plugins/jwt.md b/content/v3/uk/awesome-plugins/jwt.md index fdcd4dc1..a3fad9b1 100644 --- a/content/v3/uk/awesome-plugins/jwt.md +++ b/content/v3/uk/awesome-plugins/jwt.md @@ -1,12 +1,12 @@ -# Firebase JWT - Аутентифікація JSON Web Token для Flight +# Firebase JWT - Аутентифікація JSON Web Token -JWT (JSON Web Tokens) — це компактний, безпечний для URL спосіб представлення тверджень між вашим додатком і клієнтом. Вони ідеальні для безстанційної аутентифікації API — немає потреби в зберіганні сесій на сервері! Цей посібник показує, як інтегрувати [Firebase JWT](https://github.com/firebase/php-jwt) з Flight для безпечної аутентифікації на основі токенів. +JWT (JSON Web Tokens) — це компактний, безпечний для URL спосіб представлення тверджень між вашим додатком та клієнтом. Вони ідеальні для безстанної аутентифікації API — немає потреби в зберіганні сесій на сервері! Цей посібник показує, як інтегрувати [Firebase JWT](https://github.com/firebase/php-jwt) з Flight для безпечної аутентифікації на основі токенів. -Відвідайте [репозиторій на Github](https://github.com/firebase/php-jwt) для повної документації та деталей. +Відвідайте [репозиторій Github](https://github.com/firebase/php-jwt) для повної документації та деталей. ## Що таке JWT? -JSON Web Token — це рядок, що містить три частини: +JSON Web Token — це рядок, який містить три частини: 1. **Заголовок**: Метадані про токен (алгоритм, тип) 2. **Навантаження**: Ваші дані (ID користувача, ролі, термін дії тощо) 3. **Підпис**: Криптографічний підпис для перевірки автентичності @@ -15,15 +15,15 @@ JSON Web Token — це рядок, що містить три частини: ### Чому використовувати JWT? -- **Безстанційний**: Не потрібно зберігати сесії на сервері — ідеально для мікросервісів і API -- **Масштабованість**: Добре працює з балансувальниками навантаження, оскільки немає вимоги до афінності сесій -- **Крос-доменний**: Можна використовувати між різними доменами та сервісами -- **Дружній до мобільних**: Чудово для мобільних додатків, де куки можуть не працювати добре -- **Стандартизований**: Стандарт галузі (RFC 7519) +- **Безстанний**: Не потрібно зберігати сесії на сервері — ідеально для мікросервісів та API +- **Масштабований**: Добре працює з балансувальниками навантаження, оскільки немає вимоги до афінності сесій +- **Крос-доменний**: Може використовуватися між різними доменами та сервісами +- **Дружній до мобільних**: Чудово підходить для мобільних додатків, де куки можуть не працювати добре +- **Стандартизований**: Підхід промислового стандарту (RFC 7519) ## Встановлення -Встановіть через Composer: +Встановіть за допомогою Composer: ```bash composer require firebase/php-jwt @@ -61,9 +61,9 @@ try { } ``` -## Middleware JWT для Flight (Рекомендований підхід) +## JWT Middleware для Flight (Рекомендований підхід) -Найпоширеніший і корисний спосіб використання JWT з Flight — як **middleware** для захисту маршрутів API. Ось повний, готовий до виробництва приклад: +Найпоширеніший та корисний спосіб використання JWT з Flight — як **middleware** для захисту маршрутів API. Ось повний, готовий до виробництва приклад: ### Крок 1: Створення класу JWT Middleware @@ -82,7 +82,7 @@ class JwtMiddleware { public function __construct(Engine $app) { $this->app = $app; - // Зберігайте свій секретний ключ у app/config/config.php, НЕ жорстко закодований! + // Зберігайте ваш секретний ключ у app/config/config.php, НЕ хардкодьте! $this->secretKey = $app->get('config')['jwt_secret']; } @@ -128,11 +128,11 @@ return [ ]; // app/config/bootstrap.php або index.php -// переконайтеся, що додали цей рядок, якщо хочете надати доступ до конфігурації додатку +// переконайтеся, що додали цей рядок, якщо хочете надати доступ до конфігурації в додатку $app->set('config', $config); ``` -> **Примітка щодо безпеки**: Ніколи не жорстко кодуйте свій секретний ключ! Використовуйте змінні середовища в продакшені. +> **Примітка щодо безпеки**: Ніколи не хардкодьте ваш секретний ключ! Використовуйте змінні середовища в продакшені. ### Крок 3: Захист ваших маршрутів за допомогою Middleware @@ -145,22 +145,22 @@ Flight::route('GET /api/user/profile', function() { 'username' => $user->username, 'role' => $user->role ]); -})->addMiddleware( JwtMiddleware::class); +})->addMiddleware(JwtMiddleware::class); -// Захист цілої групи маршрутів (поширеніше!) +// Захист цілої групи маршрутів (більш поширено!) Flight::group('/api', function() { Flight::route('GET /users', function() { /* ... */ }); Flight::route('GET /posts', function() { /* ... */ }); Flight::route('POST /posts', function() { /* ... */ }); Flight::route('DELETE /posts/@id', function($id) { /* ... */ }); -}, [ JwtMiddleware::class ]); // Усі маршрути в цій групі захищені! +}, [ JwtMiddleware::class ]); // Всі маршрути в цій групі захищені! ``` -Для отримання детальнішої інформації про middleware дивіться [документацію middleware](/learn/middleware). +Для отримання додаткових деталей щодо middleware дивіться [документацію middleware](/learn/middleware). ## Поширені випадки використання -### 1. Endpoint входу (Генерація токена) +### 1. Ендпоінт входу (Генерація токена) Створіть маршрут, який генерує JWT після успішної аутентифікації: @@ -281,7 +281,7 @@ Flight::route('POST /api/refresh', function() { ### 3. Контроль доступу на основі ролей -Розширте свій middleware для перевірки ролей користувача: +Розширте ваш middleware для перевірки ролей користувача: ```php class JwtRoleMiddleware { @@ -295,7 +295,7 @@ class JwtRoleMiddleware { } public function before(array $params) { - // Припустимо, що JwtMiddleware вже запустився та встановив дані користувача + // Припустимо, що JwtMiddleware вже виконався та встановив дані користувача $user = $this->app->request()->data->user ?? null; if (!$user) { @@ -309,7 +309,7 @@ class JwtRoleMiddleware { } } -// Використання: Маршрут тільки для адміністраторів +// Використання: маршрут тільки для адміністраторів Flight::route('DELETE /api/users/@id', function($id) { // Логіка видалення користувача })->addMiddleware([ @@ -347,16 +347,16 @@ class RateLimitMiddleware { ### 1. Використовуйте сильні секретні ключі ```php -// Генерація безпечного секретного ключа (запустіть один раз, збережіть у .env файл) +// Генерація безпечного секретного ключа (виконайте один раз, збережіть у .env файл) $secretKey = base64_encode(random_bytes(32)); echo $secretKey; // Збережіть це у вашому .env файлі! ``` -### 2. Зберігайте секрети в змінних середовища +### 2. Зберігайте секрети у змінних середовища ```php // Ніколи не комітьте секрети до контролю версій! -// Використовуйте .env файл та бібліотеку, як vlucas/phpdotenv +// Використовуйте .env файл та бібліотеку як vlucas/phpdotenv // .env файл: // JWT_SECRET=your-base64-encoded-secret-here @@ -407,7 +407,7 @@ if (isset($decoded->nbf) && $decoded->nbf > time()) { ### 6. Розгляньте чорний список токенів для виходу -Для додаткової безпеки підтримуйте чорний список анульованих токенів: +Для додаткової безпеки підтримуйте чорний список недійсних токенів: ```php Flight::route('POST /api/logout', function() { @@ -452,7 +452,7 @@ $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); ``` ### Асиметричні алгоритми (RSA/ECDSA) -- **RS256**, **RS384**, **RS512**: Використовує пари публічний/приватний ключ +- **RS256**, **RS384**, **RS512**: Використовує пари публічних/приватних ключів - **ES256**, **ES384**, **ES512**: Варіанти на еліптичних кривих ```php @@ -469,7 +469,7 @@ $jwt = JWT::encode($payload, $privateKey, 'RS256'); $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); ``` -> **Коли використовувати RSA**: Використовуйте RSA, коли потрібно розповсюджувати публічний ключ для перевірки (наприклад, мікросервіси, інтеграції з третіми сторонами). Для одного додатка HS256 простіший і достатній. +> **Коли використовувати RSA**: Використовуйте RSA, коли потрібно розповсюджувати публічний ключ для перевірки (наприклад, мікросервіси, інтеграції з третіми сторонами). Для одного додатка HS256 простіший та достатній. ## Вирішення проблем @@ -479,12 +479,12 @@ $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); ### "Signature verification failed" - Ви використовуєте інший секретний ключ для декодування, ніж для кодування - Токен був змінений -- Розбіжність годинників між серверами (додайте буфер leeway) +- Розбіжність годин між серверами (додайте буфер leeway) ```php use Firebase\JWT\JWT; -JWT::$leeway = 60; // Дозволити 60 секунд розбіжності годинників +JWT::$leeway = 60; // Дозволити 60 секунд розбіжності годин $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); ``` @@ -506,13 +506,13 @@ fetch('/api/users', { - `JWT::encode(array $payload, string $key, string $alg)`: Створює JWT з навантаження - `JWT::decode(string $jwt, Key $key)`: Декодує та перевіряє JWT -- `JWT::urlsafeB64Encode(string $input)`: Кодування Base64 безпечне для URL -- `JWT::urlsafeB64Decode(string $input)`: Декодування Base64 безпечне для URL +- `JWT::urlsafeB64Encode(string $input)`: Безпечне для URL кодування Base64 +- `JWT::urlsafeB64Decode(string $input)`: Безпечне для URL декодування Base64 - `JWT::$leeway`: Статична властивість для встановлення leeway часу для перевірки (у секундах) ## Чому використовувати цю бібліотеку? -- **Стандарт галузі**: Firebase JWT — найпопулярніша та широко довірена JWT бібліотека для PHP +- **Промисловий стандарт**: Firebase JWT — найпопулярніша та широко довірена JWT бібліотека для PHP - **Активне обслуговування**: Підтримується командою Google/Firebase - **Фокус на безпеці**: Регулярні оновлення та патчі безпеки - **Простий API**: Легко зрозуміти та реалізувати @@ -521,7 +521,7 @@ fetch('/api/users', { ## Дивіться також -- [Репозиторій Firebase JWT на Github](https://github.com/firebase/php-jwt) +- [Репозиторій Firebase JWT Github](https://github.com/firebase/php-jwt) - [JWT.io](https://jwt.io/) - Налагодження та декодування JWT - [RFC 7519](https://tools.ietf.org/html/rfc7519) - Офіційна специфікація JWT - [Документація Middleware Flight](/learn/middleware) @@ -529,4 +529,4 @@ fetch('/api/users', { ## Ліцензія -Бібліотека Firebase JWT ліцензована за BSD 3-Clause License. Дивіться [репозиторій на Github](https://github.com/firebase/php-jwt) для деталей. \ No newline at end of file +Бібліотека Firebase JWT ліцензована за BSD 3-Clause License. Дивіться [репозиторій Github](https://github.com/firebase/php-jwt) для деталей. \ No newline at end of file diff --git a/content/v3/uk/awesome-plugins/runway.md b/content/v3/uk/awesome-plugins/runway.md index 7a2e847b..08879af2 100644 --- a/content/v3/uk/awesome-plugins/runway.md +++ b/content/v3/uk/awesome-plugins/runway.md @@ -1,6 +1,6 @@ -# Runway +# Паска -Runway — це CLI-застосунок, який допомагає керувати вашими Flight-застосунками. Він може генерувати контролери, відображати всі маршрути та багато іншого. Він базується на чудовій бібліотеці [adhocore/php-cli](https://github.com/adhocore/php-cli). +Паска — це CLI-додаток, який допомагає керувати вашими додатками Flight. Він може генерувати контролери, відображати всі маршрути та багато іншого. Він базується на чудовій бібліотеці [adhocore/php-cli](https://github.com/adhocore/php-cli). Натисніть [тут](https://github.com/flightphp/runway), щоб переглянути код. @@ -12,9 +12,9 @@ Runway — це CLI-застосунок, який допомагає керув composer require flightphp/runway ``` -## Базова Конфігурація +## Базова конфігурація -Вперше запустивши Runway, він спробує знайти конфігурацію `runway` у `app/config/config.php` через ключ `'runway'`. +Вперше, коли ви запустите Паска, він спробує знайти конфігурацію `runway` у `app/config/config.php` через ключ `'runway'`. ```php **ПРИМІТКА** - Починаючи з **v1.2.0**, `.runway-config.json` є застарілим. Будь ласка, мігруйте вашу конфігурацію до `app/config/config.php`. Ви можете зробити це легко за допомогою команди `php runway config:migrate`. -### Виявлення Кореня Проекту +### Виявлення кореня проекту -Runway достатньо розумний, щоб виявити корінь вашого проекту, навіть якщо ви запускаєте його з підкаталогу. Він шукає індикатори, такі як `composer.json`, `.git` або `app/config/config.php`, щоб визначити, де знаходиться корінь проекту. Це означає, що ви можете запускати команди Runway з будь-якого місця у вашому проекті! +Паска достатньо розумний, щоб виявити корінь вашого проекту, навіть якщо ви запускаєте його з підкаталогу. Він шукає індикатори, такі як `composer.json`, `.git` або `app/config/config.php`, щоб визначити, де знаходиться корінь проекту. Це означає, що ви можете запускати команди Паска з будь-якого місця у вашому проекті! ## Використання -Runway має низку команд, які ви можете використовувати для керування вашим Flight-застосунком. Є два простих способи використовувати Runway. +Паска має низку команд, які ви можете використовувати для керування вашим додатком Flight. Є два простих способи використовувати Паска. 1. Якщо ви використовуєте скелетний проект, ви можете запустити `php runway [command]` з кореня вашого проекту. -1. Якщо ви використовуєте Runway як пакет, встановлений через composer, ви можете запустити `vendor/bin/runway [command]` з кореня вашого проекту. +1. Якщо ви використовуєте Паска як пакет, встановлений через composer, ви можете запустити `vendor/bin/runway [command]` з кореня вашого проекту. -### Список Команд +### Список команд Ви можете переглянути список усіх доступних команд, запустивши команду `php runway`. @@ -48,7 +48,7 @@ Runway має низку команд, які ви можете використ php runway ``` -### Довідка по Командах +### Довідка по команді Для будь-якої команди ви можете передати прапорець `--help`, щоб отримати більше інформації про те, як використовувати команду. @@ -58,7 +58,7 @@ php runway routes --help Ось кілька прикладів: -### Генерація Контролера +### Генерація контролера На основі конфігурації в `runway.app_root`, локація згенерує для вас контролер у директорії `app/controllers/`. @@ -66,7 +66,7 @@ php runway routes --help php runway make:controller MyController ``` -### Генерація Моделі Active Record +### Генерація моделі Active Record Спочатку переконайтеся, що ви встановили плагін [Active Record](/awesome-plugins/active-record). На основі конфігурації в `runway.app_root`, локація згенерує для вас запис у директорії `app/records/`. @@ -74,7 +74,7 @@ php runway make:controller MyController php runway make:record users ``` -Наприклад, якщо у вас є таблиця `users` з такою схемою: `id`, `name`, `email`, `created_at`, `updated_at`, файл, подібний до наступного, буде створено у файлі `app/records/UserRecord.php`: +Наприклад, якщо у вас є таблиця `users` зі схемою: `id`, `name`, `email`, `created_at`, `updated_at`, буде створено файл, подібний до наступного, у файлі `app/records/UserRecord.php`: ```php hello'); // вам потрібно обрати один з цих варіантів Flight::route('/hello', 'app\controllers\MyController->hello'); -// або якщо у вас є оператор use нагорі +// або якщо у вас є оператор use на вершині use app\controllers\MyController; Flight::route('/hello', [ MyController::class, 'hello' ]); -// також можна написати +// також може бути написано Flight::route('/hello', MyController::class.'->hello'); // також... Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); @@ -191,7 +191,7 @@ Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); #### `path()` не визначено -У скелетному додатку це визначено всередині файлу `config.php`, але щоб ваші класи були знайдені, вам потрібно переконатися, що метод `path()` +У скелетному додатку це визначено всередині файлу `config.php`, але для того, щоб ваші класи були знайдені, вам потрібно переконатися, що метод `path()` визначено (ймовірно, до кореня вашого каталогу) перед тим, як ви спробуєте його використовувати. ```php diff --git a/content/v3/uk/learn/learn.md b/content/v3/uk/learn/learn.md index 892c62dc..2d33e69a 100644 --- a/content/v3/uk/learn/learn.md +++ b/content/v3/uk/learn/learn.md @@ -1,9 +1,9 @@ # Дізнайтесь про Flight -Flight — це швидкий, простий, розширюваний фреймворк для PHP. Він досить універсальний і може використовуватися для створення будь-якого виду веб-додатків. -Він створений з урахуванням простоти та написаний у спосіб, який легко зрозуміти та використовувати. +Flight — це швидкий, простий, розширюваний фреймворк для PHP. Він досить універсальний і може використовуватися для створення будь-якого типу веб-додатка. +Він побудований з урахуванням простоти та написаний таким чином, щоб бути легким для розуміння та використання. -> **Примітка:** Ви побачите приклади, які використовують `Flight::` як статичну змінну, і деякі, що використовують об'єкт двигуна `$app->`. Обидва працюють взаємозамінно з одним іншим. `$app` та `$this->app` у контролері/проміжному ПЗ — це рекомендований підхід від команди Flight. +> **Примітка:** Ви побачите приклади, які використовують `Flight::` як статичну змінну, і деякі, які використовують об'єкт двигуна `$app->`. Обидва працюють взаємозамінно з іншим. `$app` та `$this->app` у контролері/проміжному ПЗ є рекомендованим підходом від команди Flight. ## Основні компоненти @@ -45,17 +45,17 @@ Flight — це швидкий, простий, розширюваний фре ### [Розширення Flight](/learn/extending) -Дізнайтесь, як розширювати фреймворк, додаючи власні методи та класи. +Дізнайтесь, як розширювати фреймворк шляхом додавання власних методів та класів. ### [Хуки методів та фільтрація](/learn/filtering) -Дізнайтесь, як додавати хуки подій до ваших методів та внутрішніх методів фреймворка. +Дізнайтесь, як додавати хуки подій до ваших методів та внутрішніх методів фреймворку. ### [Контейнер ін'єкції залежностей (DIC)](/learn/dependency-injection-container) Дізнайтесь, як використовувати контейнери ін'єкції залежностей (DIC) для керування залежностями вашого додатка. -## Утиліти класів +## Утилітарні класи ### [Колекції](/learn/collections) @@ -65,33 +65,37 @@ Flight — це швидкий, простий, розширюваний фре Це має кілька простих функцій для забезпечення послідовного кодування та декодування вашого JSON. -### [Обгортка PDO](/learn/pdo-wrapper) +### [SimplePdo](/learn/simple-pdo) -PDO іноді може додавати більше головного болю, ніж потрібно. Цей простий клас-обгортка може значно спростити взаємодію з вашою базою даних. +PDO іноді може додавати більше головного болю, ніж необхідно. SimplePdo — це сучасний допоміжний клас PDO з зручними методами, такими як `insert()`, `update()`, `delete()` та `transaction()`, щоб зробити операції з базою даних набагато простішими. + +### [PdoWrapper](/learn/pdo-wrapper) (Застарілий) + +Оригінальна обгортка PDO є застарілою з версії v3.18.0. Будь ласка, використовуйте [SimplePdo](/learn/simple-pdo) замість цього. ### [Обробник завантажених файлів](/learn/uploaded-file) -Простий клас для допомоги в керуванні завантаженими файлами та переміщенні їх у постійне місце. +Простий клас для допомоги в керуванні завантаженими файлами та переміщенні їх у постійне місце розташування. ## Важливі концепції ### [Чому фреймворк?](/learn/why-frameworks) -Ось коротка стаття про те, чому ви повинні використовувати фреймворк. Це гарна ідея зрозуміти переваги використання фреймворка, перш ніж почати його використовувати. +Ось коротка стаття про те, чому ви повинні використовувати фреймворк. Це гарна ідея зрозуміти переваги використання фреймворку, перш ніж почати його використовувати. Додатково, чудовий посібник створено [@lubiana](https://git.php.fail/lubiana). Хоча він не заглиблюється в деталі саме про Flight, -цей посібник допоможе вам зрозуміти деякі з основних концепцій, що оточують фреймворк, та чому вони корисні. +цей посібник допоможе вам зрозуміти деякі з основних концепцій, що оточують фреймворк, та чому вони корисні для використання. Ви можете знайти посібник [тут](https://git.php.fail/lubiana/no-framework-tutorial/src/branch/master/README.md). -### [Flight порівняно з іншими фреймворками](/learn/flight-vs-another-framework) +### [Flight у порівнянні з іншими фреймворками](/learn/flight-vs-another-framework) -Якщо ви мігруєте з іншого фреймворка, такого як Laravel, Slim, Fat-Free чи Symfony, до Flight, ця сторінка допоможе вам зрозуміти відмінності між ними. +Якщо ви мігруєте з іншого фреймворку, такого як Laravel, Slim, Fat-Free чи Symfony, до Flight, ця сторінка допоможе вам зрозуміти відмінності між ними. ## Інші теми ### [Юніт-тестування](/learn/unit-testing) -Слідуйте цьому посібнику, щоб дізнатися, як проводити юніт-тестування вашого коду Flight, щоб він був надійним. +Дотримуйтесь цього посібника, щоб дізнатись, як проводити юніт-тестування вашого коду Flight, щоб він був надійним. ### [ШІ та досвід розробника](/learn/ai) @@ -99,4 +103,4 @@ PDO іноді може додавати більше головного бол ### [Міграція v2 -> v3](/learn/migrating-to-v3) -Зворотна сумісність у більшості випадків збережена, але є деякі зміни, про які ви повинні знати під час міграції з v2 до v3. \ No newline at end of file +Зворотна сумісність у більшості випадків збережена, але є деякі зміни, про які ви повинні знати при міграції з v2 до v3. \ No newline at end of file diff --git a/content/v3/uk/learn/pdo_wrapper.md b/content/v3/uk/learn/pdo_wrapper.md index 12f1d95e..973ec542 100644 --- a/content/v3/uk/learn/pdo_wrapper.md +++ b/content/v3/uk/learn/pdo_wrapper.md @@ -1,20 +1,24 @@ -# PdoWrapper Клас-допоміжник PDO +# PdoWrapper Клас-помічник PDO + +> **ПОПЕРЕДЖЕННЯ** +> +> **Застарілий:** `PdoWrapper` є застарілим з версії Flight v3.18.0. Він не буде видалений у майбутніх версіях, але буде підтримуватися для зворотної сумісності. Будь ласка, використовуйте [SimplePdo](/learn/simple-pdo) замість нього, який пропонує ту ж функціональність плюс додаткові допоміжні методи для поширених операцій з базою даних. ## Огляд -Клас `PdoWrapper` у Flight є зручним помічником для роботи з базами даних за допомогою PDO. Він спрощує поширені завдання баз даних, додає корисні методи для отримання результатів і повертає результати як [Collections](/learn/collections) для легкого доступу. Він також підтримує журналювання запитів і моніторинг продуктивності додатку (APM) для розширених випадків використання. +Клас `PdoWrapper` у Flight є дружнім помічником для роботи з базами даних за допомогою PDO. Він спрощує поширені завдання з базами даних, додає деякі зручні методи для отримання результатів і повертає результати як [Collections](/learn/collections) для легкого доступу. Він також підтримує логування запитів і моніторинг продуктивності додатків (APM) для просунутих випадків використання. ## Розуміння -Робота з базами даних у PHP може бути дещо багатослівною, особливо при прямому використанні PDO. `PdoWrapper` розширює PDO і додає методи, які роблять запитування, отримання та обробку результатів набагато простішими. Замість жонглювання підготовленими виразами та режимами отримання ви отримуєте прості методи для поширених завдань, і кожен рядок повертається як Collection, тому ви можете використовувати нотацію масиву або об'єкта. +Робота з базами даних у PHP може бути дещо багатослівною, особливо при прямому використанні PDO. `PdoWrapper` розширює PDO і додає методи, які роблять запитування, отримання та обробку результатів набагато простішими. Замість жонглювання підготовленими виразами та режимами отримання, ви отримуєте прості методи для поширених завдань, і кожен рядок повертається як Collection, тому ви можете використовувати нотацію масиву або об'єкта. -Ви можете зареєструвати `PdoWrapper` як спільну послугу в Flight, а потім використовувати його будь-де у вашому додатку через `Flight::db()`. +Ви можете зареєструвати `PdoWrapper` як спільну послугу в Flight, а потім використовувати його будь-де у вашому додатку за допомогою `Flight::db()`. ## Основне використання ### Реєстрація помічника PDO -Спочатку зареєструйте клас `PdoWrapper` з Flight: +Спочатку зареєструйте клас `PdoWrapper` у Flight: ```php Flight::register('db', \flight\database\PdoWrapper::class, [ @@ -41,7 +45,7 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ $db = Flight::db(); $statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']); while ($row = $statement->fetch()) { - // $row is an array + // $row є масивом } ``` @@ -66,12 +70,12 @@ $count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", `function fetchRow(string $sql, array $params = []): Collection` -Отримайте один рядок як Collection (доступ через масив/об'єкт): +Отримайте один рядок як Collection (доступ як до масиву/об'єкта): ```php $user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); echo $user['name']; -// or +// або echo $user->name; ``` @@ -85,35 +89,35 @@ echo $user->name; $users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); foreach ($users as $user) { echo $user['name']; - // or + // або echo $user->name; } ``` ### Використання заповнювачів `IN()` -Ви можете використовувати один `?` у клаузі `IN()` і передати масив або рядок, розділений комами: +Ви можете використовувати єдиний `?` у клаузі `IN()` і передати масив або рядок, розділений комами: ```php $ids = [1, 2, 3]; $users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); -// or +// або $users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", ['1,2,3']); ``` -## Розширене використання +## Просунуте використання -### Журналювання запитів та APM +### Логування запитів та APM Якщо ви хочете відстежувати продуктивність запитів, увімкніть відстеження APM під час реєстрації: ```php Flight::register('db', \flight\database\PdoWrapper::class, [ - 'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [/* options */], true // last param enables APM + 'mysql:host=localhost;dbname=cool_db_name', 'user', 'pass', [/* options */], true // останній параметр увімкнює APM ]); ``` -Після виконання запитів ви можете журналізувати їх вручну, але APM журналізуватиме їх автоматично, якщо увімкнено: +Після виконання запитів ви можете логувати їх вручну, але APM логуватиме їх автоматично, якщо увімкнено: ```php Flight::db()->logQueries(); @@ -125,42 +129,42 @@ Flight::db()->logQueries(); ```php Flight::route('/users', function () { - // Get all users + // Отримайте всіх користувачів $users = Flight::db()->fetchAll('SELECT * FROM users'); - // Stream all users + // Потоково отримайте всіх користувачів $statement = Flight::db()->runQuery('SELECT * FROM users'); while ($user = $statement->fetch()) { echo $user['name']; } - // Get a single user + // Отримайте одного користувача $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); - // Get a single value + // Отримайте одне значення $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); - // Special IN() syntax + // Спеціальний синтаксис IN() $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', ['1,2,3,4,5']); - // Insert a new user + // Вставте нового користувача Flight::db()->runQuery("INSERT INTO users (name, email) VALUES (?, ?)", ['Bob', 'bob@example.com']); $insert_id = Flight::db()->lastInsertId(); - // Update a user + // Оновіть користувача Flight::db()->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 123]); - // Delete a user + // Видаліть користувача Flight::db()->runQuery("DELETE FROM users WHERE id = ?", [123]); - // Get the number of affected rows + // Отримайте кількість уражених рядків $statement = Flight::db()->runQuery("UPDATE users SET name = ? WHERE name = ?", ['Bob', 'Sally']); $affected_rows = $statement->rowCount(); }); ``` -## Див. також +## Дивіться також - [Collections](/learn/collections) - Дізнайтеся, як використовувати клас Collection для легкого доступу до даних. @@ -168,7 +172,7 @@ Flight::route('/users', function () { - Якщо ви отримуєте помилку про з'єднання з базою даних, перевірте ваш DSN, ім'я користувача, пароль та опції. - Усі рядки повертаються як Collections — якщо вам потрібен звичайний масив, використовуйте `$collection->getData()`. -- Для запитів `IN (?)` переконайтеся, що передаєте масив або рядок, розділений комами. +- Для запитів `IN (?)` переконайтеся, що ви передаєте масив або рядок, розділений комами. ## Журнал змін diff --git a/content/v3/uk/learn/simple_pdo.md b/content/v3/uk/learn/simple_pdo.md new file mode 100644 index 00000000..f6e1ad26 --- /dev/null +++ b/content/v3/uk/learn/simple_pdo.md @@ -0,0 +1,320 @@ +# Клас помічника SimplePdo PDO + +## Огляд + +Клас `SimplePdo` у Flight є сучасним, багатим на функції помічником для роботи з базами даних за допомогою PDO. Він розширює `PdoWrapper` та додає зручні методи-помічники для поширених операцій з базами даних, таких як `insert()`, `update()`, `delete()` та транзакції. Він спрощує завдання з базами даних, повертає результати як [Collections](/learn/collections) для легкого доступу та підтримує логування запитів і моніторинг продуктивності додатка (APM) для просунутих випадків використання. + +## Розуміння + +Клас `SimplePdo` розроблений для того, щоб зробити роботу з базами даних у PHP набагато простішою. Замість жонглювання підготовленими запитами, режимами отримання даних та громіздкими SQL-операціями ви отримуєте чисті, прості методи для поширених завдань. Кожен рядок повертається як Collection, тому ви можете використовувати як нотацію масиву (`$row['name']`), так і нотацію об'єкта (`$row->name`). + +Цей клас є надмножиною `PdoWrapper`, тобто він включає всю функціональність `PdoWrapper` плюс додаткові методи-помічники, які роблять ваш код чистішим і легшим у підтримці. Якщо ви зараз використовуєте `PdoWrapper`, оновлення до `SimplePdo` є простим, оскільки він розширює `PdoWrapper`. + +Ви можете зареєструвати `SimplePdo` як спільну послугу у Flight, а потім використовувати його будь-де у вашому додатку за допомогою `Flight::db()`. + +## Основне використання + +### Реєстрація SimplePdo + +Спочатку зареєструйте клас `SimplePdo` у Flight: + +```php +Flight::register('db', \flight\database\SimplePdo::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 + ] +]); +``` + +> **ПРИМІТКА** +> +> Якщо ви не вкажете `PDO::ATTR_DEFAULT_FETCH_MODE`, `SimplePdo` автоматично встановить його на `PDO::FETCH_ASSOC` для вас. + +Тепер ви можете використовувати `Flight::db()` будь-де, щоб отримати з'єднання з базою даних. + +### Виконання запитів + +#### `runQuery()` + +`function runQuery(string $sql, array $params = []): PDOStatement` + +Використовуйте це для INSERT, UPDATE або коли ви хочете отримати результати вручну: + +```php +$db = Flight::db(); +$statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']); +while ($row = $statement->fetch()) { + // $row є масивом +} +``` + +Ви також можете використовувати його для записів: + +```php +$db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); +$db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]); +``` + +#### `fetchField()` + +`function fetchField(string $sql, array $params = []): mixed` + +Отримайте єдине значення з бази даних: + +```php +$count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']); +``` + +#### `fetchRow()` + +`function fetchRow(string $sql, array $params = []): ?Collection` + +Отримайте єдиний рядок як Collection (доступ як до масиву/об'єкта): + +```php +$user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); +echo $user['name']; +// або +echo $user->name; +``` + +> **ПОРАДА** +> +> `SimplePdo` автоматично додає `LIMIT 1` до запитів `fetchRow()`, якщо його ще немає, роблячи ваші запити ефективнішими. + +#### `fetchAll()` + +`function fetchAll(string $sql, array $params = []): array` + +Отримайте всі рядки як масив Collections: + +```php +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); +foreach ($users as $user) { + echo $user['name']; + // або + echo $user->name; +} +``` + +#### `fetchColumn()` + +`function fetchColumn(string $sql, array $params = []): array` + +Отримайте єдиний стовпець як масив: + +```php +$ids = Flight::db()->fetchColumn("SELECT id FROM users WHERE active = ?", [1]); +// Повертає: [1, 2, 3, 4, 5] +``` + +#### `fetchPairs()` + +`function fetchPairs(string $sql, array $params = []): array` + +Отримайте результати як пари ключ-значення (перший стовпець як ключ, другий як значення): + +```php +$userNames = Flight::db()->fetchPairs("SELECT id, name FROM users"); +// Повертає: [1 => 'John', 2 => 'Jane', 3 => 'Bob'] +``` + +### Використання заповнювачів `IN()` + +Ви можете використовувати єдиний `?` у клаузі `IN()` та передати масив: + +```php +$ids = [1, 2, 3]; +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); +``` + +## Методи-помічники + +Однією з основних переваг `SimplePdo` над `PdoWrapper` є додавання зручних методів-помічників для поширених операцій з базами даних. + +### `insert()` + +`function insert(string $table, array $data): string` + +Вставте один або більше рядків і поверніть останній ID вставки. + +**Єдина вставка:** + +```php +$id = Flight::db()->insert('users', [ + 'name' => 'John', + 'email' => 'john@example.com' +]); +``` + +**Пакетна вставка:** + +```php +$id = Flight::db()->insert('users', [ + ['name' => 'John', 'email' => 'john@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'], +]); +``` + +### `update()` + +`function update(string $table, array $data, string $where, array $whereParams = []): int` + +Оновіть рядки та поверніть кількість уражених рядків: + +```php +$affected = Flight::db()->update( + 'users', + ['name' => 'Jane', 'email' => 'jane@example.com'], + 'id = ?', + [1] +); +``` + +> **ПРИМІТКА** +> +> `rowCount()` у SQLite повертає кількість рядків, де дані дійсно змінилися. Якщо ви оновлюєте рядок тими самими значеннями, які він уже має, `rowCount()` поверне 0. Це відрізняється від поведінки MySQL при використанні `PDO::MYSQL_ATTR_FOUND_ROWS`. + +### `delete()` + +`function delete(string $table, string $where, array $whereParams = []): int` + +Видаліть рядки та поверніть кількість видалених рядків: + +```php +$deleted = Flight::db()->delete('users', 'id = ?', [1]); +``` + +### `transaction()` + +`function transaction(callable $callback): mixed` + +Виконайте зворотний виклик у межах транзакції. Транзакція автоматично фіксується при успіху або скасовується при помилці: + +```php +$result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John']); + $db->insert('logs', ['action' => 'user_created']); + return $db->lastInsertId(); +}); +``` + +Якщо будь-яке виняток виникає в межах зворотного виклику, транзакція автоматично скасовується, а виняток повторно викидається. + +## Просунуте використання + +### Логування запитів та APM + +Якщо ви хочете відстежувати продуктивність запитів, увімкніть відстеження APM під час реєстрації: + +```php +Flight::register('db', \flight\database\SimplePdo::class, [ + 'mysql:host=localhost;dbname=cool_db_name', + 'user', + 'pass', + [/* PDO options */], + [ + 'trackApmQueries' => true, + 'maxQueryMetrics' => 1000 + ] +]); +``` + +Після виконання запитів ви можете логувати їх вручну, але APM логуватиме їх автоматично, якщо увімкнено: + +```php +Flight::db()->logQueries(); +``` + +Це викличе подію (`flight.db.queries`) з метриками з'єднання та запитів, яку ви можете слухати за допомогою системи подій Flight. + +### Повний приклад + +```php +Flight::route('/users', function () { + // Отримайте всіх користувачів + $users = Flight::db()->fetchAll('SELECT * FROM users'); + + // Потоково отримайте всіх користувачів + $statement = Flight::db()->runQuery('SELECT * FROM users'); + while ($user = $statement->fetch()) { + echo $user['name']; + } + + // Отримайте єдиного користувача + $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); + + // Отримайте єдине значення + $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); + + // Отримайте єдиний стовпець + $ids = Flight::db()->fetchColumn('SELECT id FROM users'); + + // Отримайте пари ключ-значення + $userNames = Flight::db()->fetchPairs('SELECT id, name FROM users'); + + // Спеціальний синтаксис IN() + $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); + + // Вставте нового користувача + $id = Flight::db()->insert('users', [ + 'name' => 'Bob', + 'email' => 'bob@example.com' + ]); + + // Пакетна вставка користувачів + Flight::db()->insert('users', [ + ['name' => 'Bob', 'email' => 'bob@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'] + ]); + + // Оновіть користувача + $affected = Flight::db()->update('users', ['name' => 'Bob'], 'id = ?', [123]); + + // Видаліть користувача + $deleted = Flight::db()->delete('users', 'id = ?', [123]); + + // Використовуйте транзакцію + $result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John', 'email' => 'john@example.com']); + $db->insert('audit_log', ['action' => 'user_created']); + return $db->lastInsertId(); + }); +}); +``` + +## Міграція з PdoWrapper + +Якщо ви зараз використовуєте `PdoWrapper`, міграція до `SimplePdo` є простою: + +1. **Оновіть вашу реєстрацію:** + ```php + // Старий + Flight::register('db', \flight\database\PdoWrapper::class, [ /* ... */ ]); + + // Новий + Flight::register('db', \flight\database\SimplePdo::class, [ /* ... */ ]); + ``` + +2. **Усі існуючі методи `PdoWrapper` працюють у `SimplePdo`** - Немає руйнівних змін. Ваш існуючий код продовжить працювати. + +3. **Опціонально використовуйте нові методи-помічники** - Почніть використовувати `insert()`, `update()`, `delete()` та `transaction()`, щоб спростити ваш код. + +## Дивіться також + +- [Collections](/learn/collections) - Дізнайтеся, як використовувати клас Collection для легкого доступу до даних. +- [PdoWrapper](/learn/pdo-wrapper) - Спадковий клас-помічник PDO (застарілий). + +## Вирішення проблем + +- Якщо ви отримуєте помилку щодо з'єднання з базою даних, перевірте ваш DSN, ім'я користувача, пароль та опції. +- Усі рядки повертаються як Collections — якщо вам потрібен звичайний масив, використовуйте `$collection->getData()`. +- Для запитів `IN (?)` переконайтеся, що ви передаєте масив. +- Якщо ви стикаєтеся з проблемами пам'яті при логуванні запитів у довготривалих процесах, налаштуйте опцію `maxQueryMetrics`. + +## Журнал змін + +- v3.18.0 - Початковий реліз SimplePdo з методами-помічниками для insert, update, delete та транзакцій. \ No newline at end of file diff --git a/content/v3/zh/awesome-plugins/awesome_plugins.md b/content/v3/zh/awesome-plugins/awesome_plugins.md index 2e69bbde..c7349f0d 100644 --- a/content/v3/zh/awesome-plugins/awesome_plugins.md +++ b/content/v3/zh/awesome-plugins/awesome_plugins.md @@ -1,13 +1,13 @@ -# 优秀的插件 +# 精选插件 -Flight 具有极强的可扩展性。有许多插件可以用来为您的 Flight 应用程序添加功能。其中一些由 Flight 团队官方支持,其他是一些微型/轻量级库,帮助您快速上手。 +Flight 极具可扩展性。有许多插件可用于为您的 Flight 应用程序添加功能。其中一些由 Flight 团队官方支持,其他则是一些微型/轻量级库,帮助您快速上手。 ## API 文档 -API 文档对于任何 API 都至关重要。它帮助开发者理解如何与您的 API 交互以及期望返回什么。有几个工具可用于帮助您为 Flight 项目生成 API 文档。 +API 文档对于任何 API 都至关重要。它帮助开发者理解如何与您的 API 交互以及预期返回什么。有几个工具可用于帮助您为 Flight 项目生成 API 文档。 - [FlightPHP OpenAPI Generator](https://dev.to/danielsc/define-generate-and-implement-an-api-first-approach-with-openapi-generator-and-flightphp-1fb3) - 由 Daniel Schreiber 撰写的博客文章,介绍如何使用 OpenAPI 规范与 FlightPHP 结合,采用 API 优先方法构建您的 API。 -- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI 是一个优秀的工具,可帮助您为 Flight 项目生成 API 文档。它非常易用,并且可以自定义以满足您的需求。这是用于生成 Swagger 文档的 PHP 库。 +- [SwaggerUI](https://github.com/zircote/swagger-php) - Swagger UI 是一个优秀的工具,可帮助您为 Flight 项目生成 API 文档。它非常易用,并可自定义以满足您的需求。这是用于生成 Swagger 文档的 PHP 库。 ## 应用程序性能监控 (APM) @@ -16,39 +16,39 @@ API 文档对于任何 API 都至关重要。它帮助开发者理解如何与 ## 异步 -Flight 已经是一个快速的框架,但为其添加涡轮引擎会让一切变得更有趣(也更具挑战性)! +Flight 已经是一个快速的框架,但为其添加涡轮引擎会让一切变得更有趣(且更具挑战性)! -- [flightphp/async](/awesome-plugins/async) - 官方 Flight Async 库。该库是一种简单的方式,为您的应用程序添加异步处理。它在底层使用 Swoole/Openswoole,提供简单有效的方式异步运行任务。 +- [flightphp/async](/awesome-plugins/async) - 官方 Flight Async 库。此库是一种简单的方式,为您的应用程序添加异步处理。它在底层使用 Swoole/Openswoole,提供简单有效的任务异步运行方式。 ## 授权/权限 -授权和权限对于任何需要控制访问权限的应用程序都至关重要。 +授权和权限对于需要控制谁可以访问什么的任何应用程序都至关重要。 -- official [flightphp/permissions](/awesome-plugins/permissions) - 官方 Flight Permissions 库。该库是一种简单的方式,为您的应用程序添加用户和应用程序级别的权限。 +- official [flightphp/permissions](/awesome-plugins/permissions) - 官方 Flight Permissions 库。此库是一种简单的方式,为您的应用程序添加用户和应用程序级别的权限。 ## 认证 认证对于需要验证用户身份并保护 API 端点的应用程序至关重要。 -- [firebase/php-jwt](/awesome-plugins/jwt) - PHP 的 JSON Web Token (JWT) 库。这是一种简单且安全的实现基于令牌认证的方式,适用于您的 Flight 应用程序。非常适合无状态 API 认证、使用中间件保护路由以及实现 OAuth 风格的授权流程。 +- [firebase/php-jwt](/awesome-plugins/jwt) - PHP 的 JSON Web Token (JWT) 库。一种简单安全的实现基于令牌认证的方式,适用于您的 Flight 应用程序。非常适合无状态 API 认证、使用中间件保护路由以及实现 OAuth 风格的授权流程。 ## 缓存 -缓存是一种加速应用程序的绝佳方式。有许多缓存库可与 Flight 一起使用。 +缓存是加速应用程序的绝佳方式。有许多缓存库可与 Flight 一起使用。 - official [flightphp/cache](/awesome-plugins/php-file-cache) - 轻量、简单且独立的 PHP 文件内缓存类 ## CLI -CLI 应用程序是一种与您的应用程序交互的绝佳方式。您可以使用它们生成控制器、显示所有路由等。 +CLI 应用程序是与您的应用程序交互的绝佳方式。您可以使用它们生成控制器、显示所有路由等。 - official [flightphp/runway](/awesome-plugins/runway) - Runway 是一个 CLI 应用程序,帮助您管理 Flight 应用程序。 ## Cookie -Cookie 是一种在客户端存储少量数据的绝佳方式。它们可用于存储用户偏好、应用程序设置等。 +Cookie 是存储客户端小量数据的绝佳方式。它们可用于存储用户偏好、应用程序设置等。 -- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie 是一个 PHP 库,提供简单有效的方式管理 Cookie。 +- [overclokk/cookie](/awesome-plugins/php-cookie) - PHP Cookie 是一个 PHP 库,提供简单有效的 cookie 管理方式。 ## 调试 @@ -61,19 +61,20 @@ Cookie 是一种在客户端存储少量数据的绝佳方式。它们可用于 数据库是大多数应用程序的核心。这是存储和检索数据的方式。有些数据库库只是用于编写查询的包装器,有些则是功能齐全的 ORM。 -- official [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 官方 Flight PDO 包装器,是核心的一部分。这是一个简单的包装器,帮助简化编写和执行查询的过程。它不是 ORM。 +- official [flightphp/core SimplePdo](/learn/simple-pdo) - 官方 Flight PDO 助手,是核心的一部分。这是一个现代包装器,带有便捷的辅助方法,如 `insert()`、`update()`、`delete()` 和 `transaction()`,以简化数据库操作。所有结果均返回为集合,支持灵活的数组/对象访问。不是 ORM,而是一种更好地使用 PDO 的方式。 +- deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 官方 Flight PDO 包装器,是核心的一部分(自 v3.18.0 起已弃用)。请改用 SimplePdo。 - official [flightphp/active-record](/awesome-plugins/active-record) - 官方 Flight ActiveRecord ORM/映射器。一个优秀的库,便于轻松检索和存储数据库中的数据。 -- [byjg/php-migration](/awesome-plugins/migrations) - 用于跟踪项目中所有数据库更改的插件。 +- [byjg/php-migration](/awesome-plugins/migrations) - 用于跟踪项目所有数据库变更的插件。 ## 加密 -加密对于任何存储敏感数据的应用程序都至关重要。加密和解密数据并不难,但正确存储加密密钥 [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [会](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [很困难](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)。最重要的是,切勿将加密密钥存储在公共目录中或提交到您的代码仓库。 +加密对于存储敏感数据的任何应用程序都至关重要。加密和解密数据并不难,但正确存储加密密钥 [可能](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [会](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [困难](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key)。最重要的是,切勿将加密密钥存储在公共目录中或提交到您的代码仓库。 - [defuse/php-encryption](/awesome-plugins/php-encryption) - 这是一个可用于加密和解密数据的库。启动并运行非常简单,即可开始加密和解密数据。 ## 作业队列 -作业队列对于异步处理任务非常有用。这可以是发送电子邮件、处理图像,或任何不需要实时完成的任务。 +作业队列对于异步处理任务非常有用。这可以是发送电子邮件、处理图像或任何不需要实时完成的任务。 - [n0nag0n/simple-job-queue](/awesome-plugins/simple-job-queue) - Simple Job Queue 是一个可用于异步处理作业的库。它可与 beanstalkd、MySQL/MariaDB、SQLite 和 PostgreSQL 一起使用。 @@ -82,21 +83,21 @@ Cookie 是一种在客户端存储少量数据的绝佳方式。它们可用于 会话对于 API 并不太有用,但对于构建 Web 应用程序,会话对于维护状态和登录信息至关重要。 - official [flightphp/session](/awesome-plugins/session) - 官方 Flight Session 库。这是一个简单的会话库,可用于存储和检索会话数据。它使用 PHP 内置的会话处理。 -- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 会话管理器(非阻塞、闪存、分段、会话加密)。使用 PHP open_ssl 可选加密/解密会话数据。 +- [Ghostff/Session](/awesome-plugins/ghost-session) - PHP 会话管理器(非阻塞、闪现、段、会话加密)。使用 PHP open_ssl 进行可选的会话数据加密/解密。 ## 模板 -模板是任何具有 UI 的 Web 应用程序的核心。有许多模板引擎可与 Flight 一起使用。 +模板是任何带 UI 的 Web 应用程序的核心。有许多模板引擎可与 Flight 一起使用。 -- deprecated [flightphp/core View](/learn#views) - 这是一个非常基本的模板引擎,是核心的一部分。如果您的项目有多个页面,不推荐使用。 -- [latte/latte](/awesome-plugins/latte) - Latte 是一个功能齐全的模板引擎,非常易用,其语法比 Twig 或 Smarty 更接近 PHP。它也非常易于扩展并添加您自己的过滤器和函数。 -- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate 是一个强大的 PHP 模板引擎,支持资产生成、模板继承和变量处理。具有自动 CSS/JS 压缩、缓存、Base64 编码以及可选的 Flight PHP 框架集成。 +- deprecated [flightphp/core View](/learn#views) - 这是一个非常基本的模板引擎,是核心的一部分。如果您的项目超过几个页面,不推荐使用。 +- [latte/latte](/awesome-plugins/latte) - Latte 是一个功能齐全的模板引擎,非常易用,其语法更接近 PHP 而非 Twig 或 Smarty。它也非常易于扩展并添加您自己的过滤器和函数。 +- [knifelemon/comment-template](/awesome-plugins/comment-template) - CommentTemplate 是一个强大的 PHP 模板引擎,支持资产生成、模板继承和变量处理。特性包括自动 CSS/JS 压缩、缓存、Base64 编码,以及可选的 Flight PHP 框架集成。 ## WordPress 集成 想在您的 WordPress 项目中使用 Flight?有一个方便的插件! -- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 这个 WordPress 插件允许您在 WordPress 旁边运行 Flight。它非常适合使用 Flight 框架为您的 WordPress 站点添加自定义 API、微服务,甚至完整的应用程序。如果您想兼得两者的优点,这超级有用! +- [n0nag0n/wordpress-integration-for-flight-framework](/awesome-plugins/n0nag0n_wordpress) - 此 WordPress 插件让您可以与 WordPress 并行运行 Flight。它非常适合使用 Flight 框架为您的 WordPress 站点添加自定义 API、微服务,甚至完整应用程序。如果您想兼得两者的优点,这超级有用! ## 贡献 diff --git a/content/v3/zh/awesome-plugins/jwt.md b/content/v3/zh/awesome-plugins/jwt.md index 154b82ad..e7f4d155 100644 --- a/content/v3/zh/awesome-plugins/jwt.md +++ b/content/v3/zh/awesome-plugins/jwt.md @@ -1,13 +1,13 @@ -# Firebase JWT - JSON Web Token Authentication for Flight +# Firebase JWT - JSON Web Token 认证 -JWT(JSON Web Tokens)是一种紧凑的、URL 安全的表示应用程序与客户端之间声明的方式。它们非常适合无状态 API 认证——无需服务器端会话存储!本指南将向您展示如何将 [Firebase JWT](https://github.com/firebase/php-jwt) 与 Flight 集成,以实现安全的基于令牌的认证。 +JWT(JSON Web Tokens)是一种紧凑的、URL 安全的表示应用程序与客户端之间声明的方式。它们非常适合无状态 API 认证——无需服务器端会话存储!本指南将向您展示如何将 [Firebase JWT](https://github.com/firebase/php-jwt) 与 Flight 集成,实现安全的基于令牌的认证。 访问 [Github 仓库](https://github.com/firebase/php-jwt) 以获取完整文档和详细信息。 ## 什么是 JWT? JSON Web Token 是一个包含三个部分的字符串: -1. **Header**:关于令牌的元数据(算法、类型) +1. **Header**:令牌的元数据(算法、类型) 2. **Payload**:您的数据(用户 ID、角色、过期时间等) 3. **Signature**:用于验证真实性的加密签名 @@ -17,8 +17,8 @@ JSON Web Token 是一个包含三个部分的字符串: - **无状态**:无需服务器端会话存储——非常适合微服务和 API - **可扩展**:与负载均衡器配合良好,因为没有会话亲和性要求 -- **跨域**:可用于不同域和服务之间 -- **移动友好**:非常适合移动应用,在 cookie 可能无法正常工作的情况下 +- **跨域**:可在不同域和服务之间使用 +- **移动友好**:适合移动应用,Cookie 可能无法正常工作 - **标准化**:行业标准方法(RFC 7519) ## 安装 @@ -45,7 +45,7 @@ $payload = [ 'user_id' => 123, 'username' => 'johndoe', 'role' => 'admin', - 'iat' => time(), // 发行时间 + 'iat' => time(), // 签发时间 'exp' => time() + 3600 // 1 小时后过期 ]; @@ -63,7 +63,7 @@ try { ## Flight 的 JWT 中间件(推荐方法) -使用 JWT 与 Flight 的最常见且最有用的方式是作为 **middleware** 来保护您的 API 路由。以下是一个完整的、生产就绪的示例: +在 Flight 中使用 JWT 最常见且最有用的方式是作为 **middleware** 来保护您的 API 路由。这是一个完整的、生产就绪的示例: ### 步骤 1:创建 JWT 中间件类 @@ -82,14 +82,14 @@ class JwtMiddleware { public function __construct(Engine $app) { $this->app = $app; - // 将您的密钥存储在 app/config/config.php 中,不要硬编码! + // 在 app/config/config.php 中存储您的密钥,不要硬编码! $this->secretKey = $app->get('config')['jwt_secret']; } public function before(array $params) { $authHeader = $this->app->request()->getHeader('Authorization'); - // 检查 Authorization 标头是否存在 + // 检查 Authorization 头是否存在 if (empty($authHeader)) { $this->app->jsonHalt(['error' => 'No authorization token provided'], 401); } @@ -105,7 +105,7 @@ class JwtMiddleware { // 解码并验证令牌 $decoded = JWT::decode($jwt, new Key($this->secretKey, 'HS256')); - // 在请求中存储用户数据,以供路由处理程序使用 + // 将用户数据存储在请求中,以便路由处理器使用 $this->app->request()->data->user = $decoded; } catch (ExpiredException $e) { @@ -145,7 +145,7 @@ Flight::route('GET /api/user/profile', function() { 'username' => $user->username, 'role' => $user->role ]); -})->addMiddleware( JwtMiddleware::class); +})->addMiddleware(JwtMiddleware::class); // 保护一组路由(更常见!) Flight::group('/api', function() { @@ -153,16 +153,16 @@ Flight::group('/api', function() { Flight::route('GET /posts', function() { /* ... */ }); Flight::route('POST /posts', function() { /* ... */ }); Flight::route('DELETE /posts/@id', function($id) { /* ... */ }); -}, [ JwtMiddleware::class ]); // 该组中的所有路由都受保护! +}, [ JwtMiddleware::class ]); // 该组中的所有路由均受保护! ``` -有关中间件的更多详细信息,请参阅 [middleware 文档](/learn/middleware)。 +有关中间件的更多详细信息,请参阅 [middleware documentation](/learn/middleware)。 ## 常见用例 ### 1. 登录端点(令牌生成) -创建一个在成功认证后生成 JWT 的路由: +创建一个在认证成功后生成 JWT 的路由: ```php Flight::route('POST /api/login', function() { @@ -197,7 +197,7 @@ Flight::route('POST /api/login', function() { }); function validateUserCredentials($username, $password) { - // 在这里进行数据库查找和密码验证 + // 在这里执行数据库查找和密码验证 // 示例: $db = Flight::db(); $user = $db->fetchRow("SELECT * FROM users WHERE username = ?", [$username]); @@ -215,7 +215,7 @@ function validateUserCredentials($username, $password) { ### 2. 令牌刷新流程 -为长寿命会话实现刷新令牌系统: +实现一个刷新令牌系统,用于长生命周期会话: ```php Flight::route('POST /api/login', function() { @@ -224,7 +224,7 @@ Flight::route('POST /api/login', function() { $secretKey = Flight::get('config')['jwt_secret']; $refreshSecret = Flight::get('config')['jwt_refresh_secret']; - // 短寿命访问令牌(15 分钟) + // 短期访问令牌(15 分钟) $accessToken = JWT::encode([ 'user_id' => $user->id, 'type' => 'access', @@ -232,7 +232,7 @@ Flight::route('POST /api/login', function() { 'exp' => time() + (15 * 60) ], $secretKey, 'HS256'); - // 长寿命刷新令牌(7 天) + // 长期刷新令牌(7 天) $refreshToken = JWT::encode([ 'user_id' => $user->id, 'type' => 'refresh', @@ -295,7 +295,7 @@ class JwtRoleMiddleware { } public function before(array $params) { - // 假设 JwtMiddleware 已经运行并设置了用户数据 + // 假设 JwtMiddleware 已运行并设置了用户数据 $user = $this->app->request()->data->user ?? null; if (!$user) { @@ -309,7 +309,7 @@ class JwtRoleMiddleware { } } -// 用法:仅管理员路由 +// 用法:仅限管理员路由 Flight::route('DELETE /api/users/@id', function($id) { // 删除用户逻辑 })->addMiddleware([ @@ -318,9 +318,9 @@ Flight::route('DELETE /api/users/@id', function($id) { ]); ``` -### 4. 公共 API 按用户限流 +### 4. 公共 API 按用户速率限制 -使用 JWT 在没有会话的情况下跟踪和限流用户: +使用 JWT 在无需会话的情况下跟踪和限制用户速率: ```php class RateLimitMiddleware { @@ -349,7 +349,7 @@ class RateLimitMiddleware { ```php // 生成安全的密钥(运行一次,保存到 .env 文件) $secretKey = base64_encode(random_bytes(32)); -echo $secretKey; // 将其存储在您的 .env 文件中! +echo $secretKey; // 将此存储到您的 .env 文件中! ``` ### 2. 将密钥存储在环境变量中 @@ -362,7 +362,7 @@ echo $secretKey; // 将其存储在您的 .env 文件中! // JWT_SECRET=your-base64-encoded-secret-here // JWT_REFRESH_SECRET=another-base64-encoded-secret-here -// 您也可以使用 app/config/config.php 文件来存储密钥 +// 您也可以使用 app/config/config.php 文件存储密钥 // 只是确保配置文件未提交到版本控制 // return [ // 'jwt_secret' => 'your-base64-encoded-secret-here', @@ -376,7 +376,7 @@ $secretKey = getenv('JWT_SECRET'); ### 3. 设置适当的过期时间 ```php -// 良好实践:短寿命访问令牌 +// 良好实践:短期访问令牌 'exp' => time() + (15 * 60) // 15 分钟 // 对于刷新令牌:更长的过期时间 @@ -405,9 +405,9 @@ if (isset($decoded->nbf) && $decoded->nbf > time()) { } ``` -### 6. 为注销考虑令牌黑名单 +### 6. 考虑注销时的令牌黑名单 -为额外安全,维护无效令牌的黑名单: +为增强安全性,维护无效令牌的黑名单: ```php Flight::route('POST /api/logout', function() { @@ -419,7 +419,7 @@ Flight::route('POST /api/logout', function() { $decoded = Flight::request()->data->user; $ttl = $decoded->exp - time(); - // 在缓存/Redis 中存储直到过期 + // 存储到缓存/Redis 中直到过期 Flight::cache()->set("blacklist:$jwt", true, $ttl); Flight::json(['message' => 'Successfully logged out']); @@ -473,23 +473,23 @@ $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); ## 故障排除 -### “过期令牌”错误 -您的令牌的 `exp` 声明已过去。颁发新令牌或实现令牌刷新。 +### “Expired token” 错误 +您的令牌的 `exp` 声明已过期。颁发新令牌或实现令牌刷新。 -### “签名验证失败” -- 您使用不同的密钥解码,而非用于编码的密钥 +### “Signature verification failed” +- 您使用不同的密钥解码,而编码时使用了不同的密钥 - 令牌已被篡改 - 服务器之间时钟偏差(添加宽限缓冲) ```php use Firebase\JWT\JWT; -JWT::$leeway = 60; // 允许 60 秒时钟偏差 +JWT::$leeway = 60; // 允许 60 秒的时钟偏差 $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); ``` ### 请求中未发送令牌 -确保您的客户端发送 `Authorization` 标头: +确保您的客户端发送 `Authorization` 头: ```javascript // JavaScript 示例 @@ -514,7 +514,7 @@ Firebase JWT 库提供这些核心方法: - **行业标准**:Firebase JWT 是 PHP 中最流行和最受信任的 JWT 库 - **积极维护**:由 Google/Firebase 团队维护 -- **安全焦点**:定期更新和安全补丁 +- **安全导向**:定期更新和安全补丁 - **简单 API**:易于理解和实现 - **文档完善**:广泛的文档和社区支持 - **灵活**:支持多种算法和可配置选项 diff --git a/content/v3/zh/awesome-plugins/runway.md b/content/v3/zh/awesome-plugins/runway.md index f9ab9233..663741da 100644 --- a/content/v3/zh/awesome-plugins/runway.md +++ b/content/v3/zh/awesome-plugins/runway.md @@ -14,7 +14,7 @@ composer require flightphp/runway ## 基本配置 -第一次运行 Runway 时,它会尝试在 `app/config/config.php` 中通过 `'runway'` 键查找 `runway` 配置。 +首次运行 Runway 时,它会尝试在 `app/config/config.php` 中通过 `'runway'` 键查找 `runway` 配置。 ```php hello'); // 您需要选择以下选项之一 Flight::route('/hello', 'app\controllers\MyController->hello'); -// 或者如果您在上部有 use 语句 +// 或者如果您在顶部有 use 语句 use app\controllers\MyController; @@ -191,11 +191,11 @@ Flight::route('/hello', [ 'app\controllers\MyController', 'hello' ]); #### `path()` 未定义 -在骨架应用程序中,这是在 `config.php` 文件中定义的,但为了让您的类被找到,您需要确保 `path()` -方法在使用之前被定义(可能到您的目录根目录)。 +在骨架应用程序中,这是在 `config.php` 文件中定义的,但是为了让您的类被找到,您需要确保 `path()` +方法在使用它之前被定义(可能到您的目录根目录)。 ```php -// 将路径添加到自动加载器 +// 添加路径到自动加载器 Flight::path(__DIR__.'/../'); ``` diff --git a/content/v3/zh/learn/learn.md b/content/v3/zh/learn/learn.md index 6bc18424..9c5415ff 100644 --- a/content/v3/zh/learn/learn.md +++ b/content/v3/zh/learn/learn.md @@ -1,19 +1,19 @@ # 了解 Flight -Flight 是一个快速、简单、可扩展的 PHP 框架。它非常通用,可用于构建任何类型的 Web 应用程序。 +Flight 是一个快速、简单、可扩展的 PHP 框架。它非常多功能,可用于构建任何类型的 Web 应用程序。 它以简单性为设计理念,并以易于理解和使用的方式编写。 -> **注意:** 您将看到一些示例使用 `Flight::` 作为静态变量,而另一些使用 `$app->` 引擎对象。两者可以互换使用。在控制器/中间件中,`$app` 和 `$this->app` 是 Flight 团队推荐的方法。 +> **注意:** 您将看到一些示例使用 `Flight::` 作为静态变量,而有些使用 `$app->` 引擎对象。两者可以互换使用。`$app` 和 `$this->app` 在控制器/中间件中是 Flight 团队推荐的方法。 ## 核心组件 ### [路由](/learn/routing) -了解如何管理 Web 应用程序的路由。这还包括路由分组、路由参数和中间件。 +了解如何为您的 Web 应用程序管理路由。这还包括路由分组、路由参数和中间件。 ### [中间件](/learn/middleware) -了解如何使用中间件来过滤应用程序中的请求和响应。 +了解如何使用中间件过滤应用程序中的请求和响应。 ### [自动加载](/learn/autoloading) @@ -25,15 +25,15 @@ Flight 是一个快速、简单、可扩展的 PHP 框架。它非常通用, ### [响应](/learn/responses) -了解如何向用户发送响应。 +了解如何向您的用户发送响应。 ### [HTML 模板](/learn/templates) -了解如何使用内置视图引擎渲染 HTML 模板。 +了解如何使用内置视图引擎渲染您的 HTML 模板。 ### [安全](/learn/security) -了解如何保护应用程序免受常见安全威胁。 +了解如何保护您的应用程序免受常见安全威胁。 ### [配置](/learn/configuration) @@ -41,7 +41,7 @@ Flight 是一个快速、简单、可扩展的 PHP 框架。它非常通用, ### [事件管理器](/learn/events) -了解如何使用事件系统向应用程序添加自定义事件。 +了解如何使用事件系统向您的应用程序添加自定义事件。 ### [扩展 Flight](/learn/extending) @@ -49,11 +49,11 @@ Flight 是一个快速、简单、可扩展的 PHP 框架。它非常通用, ### [方法钩子和过滤](/learn/filtering) -了解如何向方法和内部框架方法添加事件钩子。 +了解如何向您的方法和框架内部方法添加事件钩子。 ### [依赖注入容器 (DIC)](/learn/dependency-injection-container) -了解如何使用依赖注入容器 (DIC) 来管理应用程序的依赖项。 +了解如何使用依赖注入容器 (DIC) 来管理您应用程序的依赖项。 ## 实用类 @@ -63,15 +63,19 @@ Flight 是一个快速、简单、可扩展的 PHP 框架。它非常通用, ### [JSON 包装器](/learn/json) -这提供了几个简单函数,使 JSON 的编码和解码保持一致。 +这是一个具有几个简单函数的工具,用于使您的 JSON 编码和解码保持一致。 -### [PDO 包装器](/learn/pdo-wrapper) +### [SimplePdo](/learn/simple-pdo) -PDO 有时会带来不必要的麻烦。这个简单的包装类可以显著简化与数据库的交互。 +PDO 有时会带来不必要的麻烦。SimplePdo 是一个现代的 PDO 辅助类,提供了方便的方法,如 `insert()`、`update()`、`delete()` 和 `transaction()`,使数据库操作更加容易。 + +### [PdoWrapper](/learn/pdo-wrapper)(已弃用) + +从 v3.18.0 开始,原始 PDO 包装器已被弃用。请改用 [SimplePdo](/learn/simple-pdo)。 ### [上传文件处理程序](/learn/uploaded-file) -一个简单的类,帮助管理上传的文件并将其移动到永久位置。 +一个简单的类,用于帮助管理上传的文件并将其移动到永久位置。 ## 重要概念 @@ -79,21 +83,21 @@ PDO 有时会带来不必要的麻烦。这个简单的包装类可以显著简 这是一篇简短的文章,解释为什么您应该使用框架。在开始使用框架之前,了解其好处是个好主意。 -此外,[@lubiana](https://git.php.fail/lubiana) 创建了一个优秀的教程。虽然它没有详细介绍 Flight 的具体内容, -但这个指南将帮助您理解围绕框架的一些主要概念,以及为什么使用它们有益。 +此外,由 [@lubiana](https://git.php.fail/lubiana) 创建了一个优秀的教程。虽然它没有详细介绍 Flight 的具体内容, +但这个指南将帮助您理解围绕框架的一些主要概念,以及为什么使用它们是有益的。 您可以在 [这里](https://git.php.fail/lubiana/no-framework-tutorial/src/branch/master/README.md) 找到该教程。 ### [Flight 与其他框架的比较](/learn/flight-vs-another-framework) -如果您从其他框架(如 Laravel、Slim、Fat-Free 或 Symfony)迁移到 Flight,此页面将帮助您了解两者之间的差异。 +如果您从其他框架(如 Laravel、Slim、Fat-Free 或 Symfony)迁移到 Flight,此页面将帮助您理解两者之间的差异。 ## 其他主题 ### [单元测试](/learn/unit-testing) -按照此指南学习如何对 Flight 代码进行单元测试,使其坚如磐石。 +按照此指南学习如何对您的 Flight 代码进行单元测试,使其坚如磐石。 -### [AI 与开发者体验](/learn/ai) +### [AI 和开发者体验](/learn/ai) 了解 Flight 如何与 AI 工具和现代开发者工作流程配合,帮助您更快、更智能地编码。 diff --git a/content/v3/zh/learn/pdo_wrapper.md b/content/v3/zh/learn/pdo_wrapper.md index 650e3610..4a200436 100644 --- a/content/v3/zh/learn/pdo_wrapper.md +++ b/content/v3/zh/learn/pdo_wrapper.md @@ -1,20 +1,24 @@ # PdoWrapper PDO 辅助类 +> **警告** +> +> **已弃用:** 从 Flight v3.18.0 开始,`PdoWrapper` 已被弃用。它不会在未来的版本中移除,但会为了向后兼容而维护。请改用 [SimplePdo](/learn/simple-pdo),它提供相同的功能加上针对常见数据库操作的额外辅助方法。 + ## 概述 -Flight 中的 `PdoWrapper` 类是一个友好的辅助工具,用于使用 PDO 处理数据库。它简化了常见的数据库任务,添加了一些方便的方法来获取结果,并将结果返回为 [Collections](/learn/collections),便于访问。它还支持查询日志记录和应用程序性能监控 (APM),适用于高级用例。 +Flight 中的 `PdoWrapper` 类是使用 PDO 处理数据库的友好辅助工具。它简化了常见的数据库任务,添加了一些用于获取结果的便捷方法,并以 [Collections](/learn/collections) 的形式返回结果,便于访问。它还支持查询日志记录和应用程序性能监控 (APM),适用于高级用例。 ## 理解 -在 PHP 中处理数据库可能有点冗长,尤其是直接使用 PDO 时。`PdoWrapper` 扩展了 PDO,并添加了使查询、获取和处理结果更容易的方法。不再需要处理预准备语句和获取模式,您可以获得简单的方法来处理常见任务,并且每行都返回为 Collection,因此您可以使用数组或对象表示法。 +在 PHP 中处理数据库可能有些冗长,尤其是直接使用 PDO 时。`PdoWrapper` 扩展了 PDO,并添加了使查询、获取和处理结果更容易的方法。不再需要处理预处理语句和获取模式,你可以获得针对常见任务的简单方法,并且每一行都作为 Collection 返回,因此可以使用数组或对象表示法。 -您可以将 `PdoWrapper` 注册为 Flight 中的共享服务,然后在您的应用程序的任何地方通过 `Flight::db()` 使用它。 +您可以将 `PdoWrapper` 注册为 Flight 中的共享服务,然后在您的应用中的任何地方通过 `Flight::db()` 使用它。 ## 基本用法 ### 注册 PDO 辅助工具 -首先,将 `PdoWrapper` 类与 Flight 注册: +首先,使用 Flight 注册 `PdoWrapper` 类: ```php Flight::register('db', \flight\database\PdoWrapper::class, [ @@ -27,15 +31,15 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ ]); ``` -现在,您可以在任何地方使用 `Flight::db()` 来获取数据库连接。 +现在,您可以在任何地方使用 `Flight::db()` 来获取您的数据库连接。 -### 运行查询 +### 执行查询 #### `runQuery()` `function runQuery(string $sql, array $params = []): PDOStatement` -用于 INSERT、UPDATE,或者当您想要手动获取结果时: +用于 INSERT、UPDATE,或者当您想手动获取结果时: ```php $db = Flight::db(); @@ -45,7 +49,7 @@ while ($row = $statement->fetch()) { } ``` -您也可以用于写入: +您也可以用于写入操作: ```php $db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); @@ -105,7 +109,7 @@ $users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", ['1,2,3'] ### 查询日志记录 & APM -如果您想要跟踪查询性能,请在注册时启用 APM 跟踪: +如果您想跟踪查询性能,在注册时启用 APM 跟踪: ```php Flight::register('db', \flight\database\PdoWrapper::class, [ @@ -113,7 +117,7 @@ Flight::register('db', \flight\database\PdoWrapper::class, [ ]); ``` -运行查询后,您可以手动记录它们,但如果启用,APM 会自动记录它们: +在执行查询后,您可以手动记录它们,但如果启用 APM,它会自动记录它们: ```php Flight::db()->logQueries(); @@ -162,14 +166,14 @@ Flight::route('/users', function () { ## 另请参阅 -- [Collections](/learn/collections) - 了解如何使用 Collection 类进行简单的数据访问。 +- [Collections](/learn/collections) - 了解如何使用 Collection 类进行轻松的数据访问。 ## 故障排除 -- 如果您收到关于数据库连接的错误,请检查您的 DSN、用户名、密码和选项。 -- 所有行都返回为 Collections——如果您需要普通数组,请使用 `$collection->getData()`。 +- 如果您遇到数据库连接错误,请检查您的 DSN、用户名、密码和选项。 +- 所有行都作为 Collection 返回——如果您需要普通数组,请使用 `$collection->getData()`。 - 对于 `IN (?)` 查询,请确保传递数组或逗号分隔的字符串。 ## 更新日志 -- v3.2.0 - PdoWrapper 的初始发布,带有基本查询和获取方法。 \ No newline at end of file +- v3.2.0 - PdoWrapper 的初始发布,带有基本的查询和获取方法。 \ No newline at end of file diff --git a/content/v3/zh/learn/simple_pdo.md b/content/v3/zh/learn/simple_pdo.md new file mode 100644 index 00000000..ea03074e --- /dev/null +++ b/content/v3/zh/learn/simple_pdo.md @@ -0,0 +1,320 @@ +# SimplePdo PDO 辅助类 + +## 概述 + +Flight 中的 `SimplePdo` 类是一个现代的、功能丰富的 PDO 数据库操作辅助类。它扩展了 `PdoWrapper`,并添加了用于常见数据库操作的便捷辅助方法,如 `insert()`、`update()`、`delete()` 和事务。它简化了数据库任务,将结果返回为 [Collections](/learn/collections) 以便于访问,并支持查询日志记录和应用程序性能监控 (APM) 以用于高级用例。 + +## 理解 + +`SimplePdo` 类旨在使 PHP 中的数据库操作变得更加容易。与处理预处理语句、获取模式和冗长的 SQL 操作相比,您可以获得用于常见任务的干净、简单的方方法。每行都返回为 Collection,因此您可以使用数组表示法 (`$row['name']`) 和对象表示法 (`$row->name`)。 + +这个类是 `PdoWrapper` 的超集,这意味着它包含了 `PdoWrapper` 的所有功能加上额外的辅助方法,使您的代码更干净、更易维护。如果您当前使用 `PdoWrapper`,升级到 `SimplePdo` 非常简单,因为它扩展了 `PdoWrapper`。 + +您可以将 `SimplePdo` 注册为 Flight 中的共享服务,然后通过 `Flight::db()` 在您的应用中的任何地方使用它。 + +## 基本用法 + +### 注册 SimplePdo + +首先,使用 Flight 注册 `SimplePdo` 类: + +```php +Flight::register('db', \flight\database\SimplePdo::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 + ] +]); +``` + +> **注意** +> +> 如果您没有指定 `PDO::ATTR_DEFAULT_FETCH_MODE`,`SimplePdo` 将自动为您设置为 `PDO::FETCH_ASSOC`。 + +现在,您可以在任何地方使用 `Flight::db()` 来获取数据库连接。 + +### 执行查询 + +#### `runQuery()` + +`function runQuery(string $sql, array $params = []): PDOStatement` + +用于 INSERT、UPDATE 或手动获取结果: + +```php +$db = Flight::db(); +$statement = $db->runQuery("SELECT * FROM users WHERE status = ?", ['active']); +while ($row = $statement->fetch()) { + // $row 是数组 +} +``` + +您也可以用于写入操作: + +```php +$db->runQuery("INSERT INTO users (name) VALUES (?)", ['Alice']); +$db->runQuery("UPDATE users SET name = ? WHERE id = ?", ['Bob', 1]); +``` + +#### `fetchField()` + +`function fetchField(string $sql, array $params = []): mixed` + +从数据库获取单个值: + +```php +$count = Flight::db()->fetchField("SELECT COUNT(*) FROM users WHERE status = ?", ['active']); +``` + +#### `fetchRow()` + +`function fetchRow(string $sql, array $params = []): ?Collection` + +获取单行作为 Collection(数组/对象访问): + +```php +$user = Flight::db()->fetchRow("SELECT * FROM users WHERE id = ?", [123]); +echo $user['name']; +// 或 +echo $user->name; +``` + +> **提示** +> +> `SimplePdo` 会自动在 `fetchRow()` 查询中添加 `LIMIT 1`,如果尚未存在的话,这会使您的查询更高效。 + +#### `fetchAll()` + +`function fetchAll(string $sql, array $params = []): array` + +获取所有行作为 Collection 数组: + +```php +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE status = ?", ['active']); +foreach ($users as $user) { + echo $user['name']; + // 或 + echo $user->name; +} +``` + +#### `fetchColumn()` + +`function fetchColumn(string $sql, array $params = []): array` + +获取单列作为数组: + +```php +$ids = Flight::db()->fetchColumn("SELECT id FROM users WHERE active = ?", [1]); +// 返回: [1, 2, 3, 4, 5] +``` + +#### `fetchPairs()` + +`function fetchPairs(string $sql, array $params = []): array` + +获取结果作为键值对(第一列作为键,第二列作为值): + +```php +$userNames = Flight::db()->fetchPairs("SELECT id, name FROM users"); +// 返回: [1 => 'John', 2 => 'Jane', 3 => 'Bob'] +``` + +### 使用 `IN()` 占位符 + +您可以在 `IN()` 子句中使用单个 `?` 并传递数组: + +```php +$ids = [1, 2, 3]; +$users = Flight::db()->fetchAll("SELECT * FROM users WHERE id IN (?)", [$ids]); +``` + +## 辅助方法 + +`SimplePdo` 相对于 `PdoWrapper` 的主要优势之一是添加了用于常见数据库操作的便捷辅助方法。 + +### `insert()` + +`function insert(string $table, array $data): string` + +插入一行或多行并返回最后插入的 ID。 + +**单个插入:** + +```php +$id = Flight::db()->insert('users', [ + 'name' => 'John', + 'email' => 'john@example.com' +]); +``` + +**批量插入:** + +```php +$id = Flight::db()->insert('users', [ + ['name' => 'John', 'email' => 'john@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'], +]); +``` + +### `update()` + +`function update(string $table, array $data, string $where, array $whereParams = []): int` + +更新行并返回受影响的行数: + +```php +$affected = Flight::db()->update( + 'users', + ['name' => 'Jane', 'email' => 'jane@example.com'], + 'id = ?', + [1] +); +``` + +> **注意** +> +> SQLite 的 `rowCount()` 返回实际更改数据的行数。如果您用相同的现有值更新一行,`rowCount()` 将返回 0。这与使用 `PDO::MYSQL_ATTR_FOUND_ROWS` 时的 MySQL 行为不同。 + +### `delete()` + +`function delete(string $table, string $where, array $whereParams = []): int` + +删除行并返回删除的行数: + +```php +$deleted = Flight::db()->delete('users', 'id = ?', [1]); +``` + +### `transaction()` + +`function transaction(callable $callback): mixed` + +在事务中执行回调。事务在成功时自动提交,在错误时回滚: + +```php +$result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John']); + $db->insert('logs', ['action' => 'user_created']); + return $db->lastInsertId(); +}); +``` + +如果在回调中抛出任何异常,事务将自动回滚并重新抛出异常。 + +## 高级用法 + +### 查询日志记录 & APM + +如果您想跟踪查询性能,请在注册时启用 APM 跟踪: + +```php +Flight::register('db', \flight\database\SimplePdo::class, [ + 'mysql:host=localhost;dbname=cool_db_name', + 'user', + 'pass', + [/* PDO options */], + [ + 'trackApmQueries' => true, + 'maxQueryMetrics' => 1000 + ] +]); +``` + +在执行查询后,您可以手动记录它们,但如果启用,APM 将自动记录它们: + +```php +Flight::db()->logQueries(); +``` + +这将触发一个事件 (`flight.db.queries`),包含连接和查询指标,您可以使用 Flight 的事件系统监听它。 + +### 完整示例 + +```php +Flight::route('/users', function () { + // 获取所有用户 + $users = Flight::db()->fetchAll('SELECT * FROM users'); + + // 流式传输所有用户 + $statement = Flight::db()->runQuery('SELECT * FROM users'); + while ($user = $statement->fetch()) { + echo $user['name']; + } + + // 获取单个用户 + $user = Flight::db()->fetchRow('SELECT * FROM users WHERE id = ?', [123]); + + // 获取单个值 + $count = Flight::db()->fetchField('SELECT COUNT(*) FROM users'); + + // 获取单列 + $ids = Flight::db()->fetchColumn('SELECT id FROM users'); + + // 获取键值对 + $userNames = Flight::db()->fetchPairs('SELECT id, name FROM users'); + + // 特殊的 IN() 语法 + $users = Flight::db()->fetchAll('SELECT * FROM users WHERE id IN (?)', [[1,2,3,4,5]]); + + // 插入新用户 + $id = Flight::db()->insert('users', [ + 'name' => 'Bob', + 'email' => 'bob@example.com' + ]); + + // 批量插入用户 + Flight::db()->insert('users', [ + ['name' => 'Bob', 'email' => 'bob@example.com'], + ['name' => 'Jane', 'email' => 'jane@example.com'] + ]); + + // 更新用户 + $affected = Flight::db()->update('users', ['name' => 'Bob'], 'id = ?', [123]); + + // 删除用户 + $deleted = Flight::db()->delete('users', 'id = ?', [123]); + + // 使用事务 + $result = Flight::db()->transaction(function($db) { + $db->insert('users', ['name' => 'John', 'email' => 'john@example.com']); + $db->insert('audit_log', ['action' => 'user_created']); + return $db->lastInsertId(); + }); +}); +``` + +## 从 PdoWrapper 迁移 + +如果您当前使用 `PdoWrapper`,迁移到 `SimplePdo` 非常简单: + +1. **更新您的注册:** + ```php + // 旧版 + Flight::register('db', \flight\database\PdoWrapper::class, [ /* ... */ ]); + + // 新版 + Flight::register('db', \flight\database\SimplePdo::class, [ /* ... */ ]); + ``` + +2. **所有现有的 `PdoWrapper` 方法在 `SimplePdo` 中都有效** - 没有破坏性更改。您现有的代码将继续工作。 + +3. **可选使用新辅助方法** - 开始使用 `insert()`、`update()`、`delete()` 和 `transaction()` 来简化您的代码。 + +## 另请参阅 + +- [Collections](/learn/collections) - 了解如何使用 Collection 类进行轻松数据访问。 +- [PdoWrapper](/learn/pdo-wrapper) - 遗留的 PDO 辅助类(已弃用)。 + +## 故障排除 + +- 如果您收到数据库连接错误,请检查您的 DSN、用户名、密码和选项。 +- 所有行都返回为 Collections——如果您需要普通数组,请使用 `$collection->getData()`。 +- 对于 `IN (?)` 查询,请确保传递数组。 +- 如果在长时间运行的进程中查询日志记录导致内存问题,请调整 `maxQueryMetrics` 选项。 + +## 更新日志 + +- v3.18.0 - SimplePdo 的初始发布,带有用于插入、更新、删除和事务的辅助方法。 \ No newline at end of file From 120c1b336f5793441587871d0e8ff65a98e5d682 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Wed, 14 Jan 2026 19:34:24 -0700 Subject: [PATCH 33/36] auto added date to when translation is run --- app/commands/TranslateCommand.php | 38 ++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/app/commands/TranslateCommand.php b/app/commands/TranslateCommand.php index 3492b6ff..f88508ec 100644 --- a/app/commands/TranslateCommand.php +++ b/app/commands/TranslateCommand.php @@ -12,8 +12,10 @@ * @property-read bool $dryRun * @property-read int $threads */ -class TranslateCommand extends AbstractBaseCommand { - public function __construct(array $config = []) { +class TranslateCommand extends AbstractBaseCommand +{ + public function __construct(array $config = []) + { parent::__construct('app:translate', 'Translate markdown documentation files to other languages.', $config); $this->option('--from-date', 'Skip files older than this date (YYYY-MM-DD)', null, 0) ->option('--skip-files', 'Comma separated list of filenames to skip', null, '') @@ -21,7 +23,8 @@ public function __construct(array $config = []) { ->option('--threads', 'Number of concurrent translation requests', null, 5); } - public function execute() { + public function execute() + { $io = $this->app()->io(); $chatgpt_key = $this->config['chatgpt_key'] ?? ''; @@ -38,6 +41,8 @@ public function execute() { $fromDate = $this->fromDate; if ($fromDate) { $fromDate = strtotime($fromDate . ' 00:00:00'); + } else { + $fromDate = strtotime($this->config['last_translation_run'] . ' 00:00:00'); } $dryRun = $this->dryRun; @@ -101,15 +106,14 @@ public function execute() { foreach ($translationJobs as $job) { $io->comment(" [DRY RUN] Would translate " . basename($job['file']) . " to {$job['language']}", true); } - return; } // Process jobs in batches based on thread count - $maxThreads = (int)$this->threads; + $maxThreads = (int) $this->threads; $totalJobs = count($translationJobs); $processedJobs = 0; - while ($processedJobs < $totalJobs) { + while (!$dryRun && $processedJobs < $totalJobs) { $batch = array_slice($translationJobs, $processedJobs, $maxThreads); $this->processBatch($batch, $chatgpt_key, $io); $processedJobs += count($batch); @@ -119,15 +123,19 @@ public function execute() { // Cleanup orphaned files if (!$dryRun) { $this->cleanupOrphanedFiles($files, $languages, $projectRoot, $io); + // update config.php to have the last time this was run + $this->app()->handle([PROJECT_ROOT . '/vendor/bin/runway', 'config:set', 'last_translation_run', date('Y-m-d')]); } else { $io->comment("[DRY RUN] Skipping orphaned file cleanup check.", true); } + } /** * Process a batch of translation jobs concurrently using curl_multi */ - protected function processBatch(array $batch, string $apiKey, $io) { + protected function processBatch(array $batch, string $apiKey, $io) + { $mh = curl_multi_init(); $handles = []; $jobData = []; @@ -149,8 +157,8 @@ protected function processBatch(array $batch, string $apiKey, $io) { $ch = $this->createCurlHandle($apiKey, $messages); curl_multi_add_handle($mh, $ch); - $handles[(int)$ch] = $ch; - $jobData[(int)$ch] = [ + $handles[(int) $ch] = $ch; + $jobData[(int) $ch] = [ 'job' => $job, 'messages' => $messages, 'full_response' => '', @@ -240,7 +248,8 @@ protected function processBatch(array $batch, string $apiKey, $io) { /** * Create a configured curl handle for the API request */ - protected function createCurlHandle(string $apiKey, array $messages) { + protected function createCurlHandle(string $apiKey, array $messages) + { $ch = curl_init('https://api.x.ai/v1/chat/completions'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); @@ -256,7 +265,8 @@ protected function createCurlHandle(string $apiKey, array $messages) { return $ch; } - protected function cleanupOrphanedFiles(array $files, array $languages, string $projectRoot, $io) { + protected function cleanupOrphanedFiles(array $files, array $languages, string $projectRoot, $io) + { $enFiles = []; foreach ($files as $file) { $enFiles[] = ltrim(str_replace(realpath($projectRoot . '/content/v3/en/'), '', realpath($file)), '/\\'); @@ -264,14 +274,16 @@ protected function cleanupOrphanedFiles(array $files, array $languages, string $ foreach ($languages as $languageAbbreviation) { $langDir = $projectRoot . "/content/v3/{$languageAbbreviation}/"; - if (!is_dir($langDir)) continue; + if (!is_dir($langDir)) + continue; $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($langDir, RecursiveDirectoryIterator::SKIP_DOTS) ); foreach ($iterator as $translatedFile) { - if ($translatedFile->getExtension() !== 'md') continue; + if ($translatedFile->getExtension() !== 'md') + continue; $relativePath = ltrim(str_replace(realpath($langDir), '', $translatedFile->getRealPath()), '/\\'); From 017e6636afb63987f9e36bd3ae569dfb15fbc63a Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Fri, 16 Jan 2026 07:47:39 -0700 Subject: [PATCH 34/36] updated ai language --- content/v3/de/awesome-plugins/runway.md | 58 ++++++----- content/v3/de/learn/ai.md | 49 ++++----- content/v3/en/learn/ai.md | 5 +- content/v3/es/awesome-plugins/runway.md | 12 +-- content/v3/es/learn/ai.md | 29 +++--- content/v3/fr/awesome-plugins/runway.md | 32 +++--- content/v3/fr/learn/ai.md | 33 +++--- content/v3/id/awesome-plugins/runway.md | 78 +++++++------- content/v3/id/learn/ai.md | 15 +-- content/v3/ja/awesome-plugins/runway.md | 60 +++++------ content/v3/ja/learn/ai.md | 37 +++---- content/v3/ko/awesome-plugins/runway.md | 132 ++++++++++++------------ content/v3/ko/learn/ai.md | 33 +++--- content/v3/lv/awesome-plugins/runway.md | 66 ++++++------ content/v3/lv/learn/ai.md | 67 ++++++------ content/v3/pt/awesome-plugins/runway.md | 40 +++---- content/v3/pt/learn/ai.md | 21 ++-- content/v3/ru/awesome-plugins/runway.md | 80 +++++++------- content/v3/ru/learn/ai.md | 11 +- content/v3/uk/awesome-plugins/runway.md | 64 ++++++------ content/v3/uk/learn/ai.md | 57 +++++----- content/v3/zh/awesome-plugins/runway.md | 32 +++--- content/v3/zh/learn/ai.md | 25 ++--- 23 files changed, 531 insertions(+), 505 deletions(-) diff --git a/content/v3/de/awesome-plugins/runway.md b/content/v3/de/awesome-plugins/runway.md index c011a45d..6b2c83fc 100644 --- a/content/v3/de/awesome-plugins/runway.md +++ b/content/v3/de/awesome-plugins/runway.md @@ -1,8 +1,8 @@ # Runway -Runway ist eine CLI-Anwendung, die Ihnen bei der Verwaltung Ihrer Flight-Anwendungen hilft. Sie kann Controller generieren, alle Routen anzeigen und mehr. Sie basiert auf der hervorragenden [adhocore/php-cli](https://github.com/adhocore/php-cli)-Bibliothek. +Runway ist eine CLI-Anwendung, die Ihnen hilft, Ihre Flight-Anwendungen zu verwalten. Sie kann Controller generieren, alle Routen anzeigen und mehr. Sie basiert auf der exzellenten [adhocore/php-cli](https://github.com/adhocore/php-cli)-Bibliothek. -Klicken Sie [hier](https://github.com/flightphp/runway), um den Code anzusehen. +Klicken Sie [hier](https://github.com/flightphp/runway), um den Code anzuzeigen. ## Installation @@ -14,7 +14,7 @@ composer require flightphp/runway ## Basis-Konfiguration -Beim ersten Ausführen von Runway sucht es nach einer `runway`-Konfiguration in `app/config/config.php` über den Schlüssel `'runway'`. +Beim ersten Ausführen von Runway versucht es, eine `runway`-Konfiguration in `app/config/config.php` über den Schlüssel `'runway'` zu finden. ```php **HINWEIS** - Ab **v1.2.0** ist `.runway-config.json` veraltet. Bitte migrieren Sie Ihre Konfiguration zu `app/config/config.php`. Sie können dies einfach mit dem Befehl `php runway config:migrate` tun. + + ### Projekt-Root-Erkennung -Runway ist intelligent genug, um das Root-Verzeichnis Ihres Projekts zu erkennen, auch wenn Sie es aus einem Unterverzeichnis ausführen. Es sucht nach Indikatoren wie `composer.json`, `.git` oder `app/config/config.php`, um zu bestimmen, wo das Projekt-Root liegt. Das bedeutet, Sie können Runway-Befehle von überall in Ihrem Projekt ausführen! +Runway ist intelligent genug, um das Root-Verzeichnis Ihres Projekts zu erkennen, auch wenn Sie es aus einem Unterverzeichnis ausführen. Es sucht nach Indikatoren wie `composer.json`, `.git` oder `app/config/config.php`, um zu bestimmen, wo das Projekt-Root liegt. Das bedeutet, Sie können Runway-Befehle von überall in Ihrem Projekt ausführen! ## Verwendung -Runway verfügt über eine Reihe von Befehlen, die Sie zur Verwaltung Ihrer Flight-Anwendung verwenden können. Es gibt zwei einfache Wege, Runway zu nutzen. +Runway verfügt über eine Reihe von Befehlen, die Sie verwenden können, um Ihre Flight-Anwendung zu verwalten. Es gibt zwei einfache Wege, Runway zu nutzen. -1. Wenn Sie das Skeleton-Projekt verwenden, können Sie `php runway [command]` vom Root-Verzeichnis Ihres Projekts ausführen. -1. Wenn Sie Runway als Paket über Composer installiert haben, können Sie `vendor/bin/runway [command]` vom Root-Verzeichnis Ihres Projekts ausführen. +1. Wenn Sie das Skeleton-Projekt verwenden, können Sie `php runway [command]` vom Root Ihres Projekts ausführen. +1. Wenn Sie Runway als über Composer installiertes Paket verwenden, können Sie `vendor/bin/runway [command]` vom Root Ihres Projekts ausführen. ### Befehlsliste @@ -50,13 +52,13 @@ php runway ### Befehls-Hilfe -Für jeden Befehl können Sie die `--help`-Flagge übergeben, um weitere Informationen zur Verwendung des Befehls zu erhalten. +Für jeden Befehl können Sie die `--help`-Flagge übergeben, um mehr Informationen darüber zu erhalten, wie der Befehl verwendet wird. ```bash php runway routes --help ``` -Hier sind einige Beispiele: +Hier sind ein paar Beispiele: ### Einen Controller generieren @@ -68,13 +70,13 @@ php runway make:controller MyController ### Ein Active Record-Modell generieren -Stellen Sie zuerst sicher, dass Sie das [Active Record](/awesome-plugins/active-record)-Plugin installiert haben. Basierend auf der Konfiguration in `runway.app_root` wird der Speicherort einen Datensatz für Sie im Verzeichnis `app/records/` generieren. +Stellen Sie zuerst sicher, dass Sie das [Active Record](/awesome-plugins/active-record)-Plugin installiert haben. Basierend auf der Konfiguration in `runway.app_root` wird der Speicherort einen Record für Sie im Verzeichnis `app/records/` generieren. ```bash php runway make:record users ``` -Falls Sie beispielsweise die Tabelle `users` mit dem folgenden Schema haben: `id`, `name`, `email`, `created_at`, `updated_at`, wird eine Datei ähnlich der folgenden in der Datei `app/records/UserRecord.php` erstellt: +Wenn Sie beispielsweise die `users`-Tabelle mit dem folgenden Schema haben: `id`, `name`, `email`, `created_at`, `updated_at`, wird eine Datei ähnlich der folgenden in der Datei `app/records/UserRecord.php` erstellt: ```php argument('', 'Der Name des lustigen GIFs'); } @@ -169,7 +171,7 @@ class ExampleCommand extends AbstractBaseCommand { $io = $this->app()->io(); - $io->info('Erstelle Beispiel...'); + $io->info('Erstellen des Beispiels...'); // Hier etwas tun @@ -182,7 +184,7 @@ Sehen Sie sich die [adhocore/php-cli-Dokumentation](https://github.com/adhocore/ ## Konfigurationsverwaltung -Da die Konfiguration ab `v1.2.0` zu `app/config/config.php` verschoben wurde, gibt es einige Hilfsbefehle zur Verwaltung der Konfiguration. +Da die Konfiguration ab `v1.2.0` zu `app/config/config.php` verschoben wurde, gibt es ein paar Hilfsbefehle zur Verwaltung der Konfiguration. ### Alte Konfiguration migrieren @@ -194,7 +196,7 @@ php runway config:migrate ### Konfigurationswert setzen -Sie können einen Konfigurationswert mit dem Befehl `config:set` setzen. Dies ist nützlich, wenn Sie einen Konfigurationswert aktualisieren möchten, ohne die Datei zu öffnen. +Sie können einen Konfigurationswert mit dem `config:set`-Befehl setzen. Dies ist nützlich, wenn Sie einen Konfigurationswert aktualisieren möchten, ohne die Datei zu öffnen. ```bash php runway config:set app_root "app/" @@ -202,7 +204,7 @@ php runway config:set app_root "app/" ### Konfigurationswert abrufen -Sie können einen Konfigurationswert mit dem Befehl `config:get` abrufen. +Sie können einen Konfigurationswert mit dem `config:get`-Befehl abrufen. ```bash php runway config:get app_root @@ -210,7 +212,7 @@ php runway config:get app_root ## Alle Runway-Konfigurationen -Wenn Sie die Konfiguration für Runway anpassen müssen, können Sie diese Werte in `app/config/config.php` setzen. Unten sind einige zusätzliche Konfigurationen, die Sie setzen können: +Wenn Sie die Konfiguration für Runway anpassen müssen, können Sie diese Werte in `app/config/config.php` setzen. Nachfolgend sind einige zusätzliche Konfigurationen, die Sie setzen können: ```php [ - '/includes/libs/vendor', // falls Sie einen wirklich einzigartigen Pfad für Ihr Vendor-Verzeichnis haben oder so + '/includes/libs/vendor', // wenn Sie einen wirklich einzigartigen Pfad für Ihr Vendor-Verzeichnis haben oder so ], // Finale Pfade sind Orte innerhalb eines Projekts, um nach Befehlsdateien zu suchen @@ -242,7 +244,7 @@ return [ 'app/module/admin/commands', ], - // Wenn Sie einfach den vollständigen Pfad hinzufügen möchten, tun Sie es ruhig (absolut oder relativ zum Projekt-Root) + // Wenn Sie den vollständigen Pfad hinzufügen möchten, gehen Sie einfach voran (absolut oder relativ zum Projekt-Root) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -254,7 +256,7 @@ return [ ### Zugriff auf Konfiguration -Wenn Sie die Konfigurationswerte effektiv abrufen müssen, können Sie sie über die `__construct`-Methode oder die `app()`-Methode abrufen. Es ist auch wichtig zu beachten, dass, wenn Sie eine Datei `app/config/services.php` haben, diese Dienste auch für Ihren Befehl verfügbar sind. +Wenn Sie die Konfigurationswerte effektiv abrufen müssen, können Sie sie über die `__construct`-Methode oder die `app()`-Methode abrufen. Es ist auch wichtig zu beachten, dass, wenn Sie eine `app/config/services.php`-Datei haben, diese Dienste ebenfalls für Ihren Befehl verfügbar sind. ```php public function execute() @@ -273,14 +275,14 @@ public function execute() ## AI-Hilfs-Wrapper -Runway hat einige Hilfs-Wrapper, die es AI einfacher machen, Befehle zu generieren. Sie können `addOption` und `addArgument` auf eine Weise verwenden, die ähnlich wie bei Symfony Console wirkt. Dies ist hilfreich, wenn Sie AI-Tools verwenden, um Ihre Befehle zu generieren. +Runway hat einige Hilfs-Wrapper, die es einfacher machen, für KI Befehle zu generieren. Sie können `addOption` und `addArgument` auf eine Weise verwenden, die ähnlich wie Symfony Console wirkt. Dies ist hilfreich, wenn Sie KI-Tools verwenden, um Ihre Befehle zu generieren. ```php public function __construct(array $config) { - parent::__construct('make:example', 'Erstellt ein Beispiel für die Dokumentation', $config); + parent::__construct('make:example', 'Erstellen eines Beispiels für die Dokumentation', $config); - // Der Name-Argument ist nullable und standardmäßig vollständig optional + // Der name-Argument ist nullable und standardmäßig vollständig optional $this->addOption('name', 'Der Name des Beispiels', null); } ``` \ No newline at end of file diff --git a/content/v3/de/learn/ai.md b/content/v3/de/learn/ai.md index 6b101681..8d3840bb 100644 --- a/content/v3/de/learn/ai.md +++ b/content/v3/de/learn/ai.md @@ -2,22 +2,22 @@ ## Überblick -Flight erleichtert es, Ihre PHP-Projekte mit KI-gestützten Tools und modernen Entwickler-Workflows zu superchargen. Mit integrierten Befehlen zum Verbinden mit LLM-Anbietern (Large Language Model) und zum Generieren projektspezifischer KI-Codierungsanweisungen hilft Flight Ihnen und Ihrem Team, das Maximum aus KI-Assistenten wie GitHub Copilot, Cursor und Windsurf herauszuholen. +Flight erleichtert es, Ihre PHP-Projekte mit KI-gestützten Tools und modernen Entwickler-Workflows aufzurüsten. Mit integrierten Befehlen zur Verbindung mit LLM-Anbietern (Large Language Model) und zur Generierung von projektspezifischen KI-Coding-Anweisungen hilft Flight Ihnen und Ihrem Team, das Maximum aus KI-Assistenten wie GitHub Copilot, Cursor, Windsurf und Antigravity (Gemini) herauszuholen. ## Verständnis -KI-Codierungsassistenten sind am hilfreichsten, wenn sie den Kontext, die Konventionen und die Ziele Ihres Projekts verstehen. Die KI-Hilfsprogramme von Flight ermöglichen es Ihnen: +KI-Coding-Assistenten sind am hilfreichsten, wenn sie den Kontext, die Konventionen und die Ziele Ihres Projekts verstehen. Die KI-Hilfsprogramme von Flight ermöglichen es Ihnen: - Ihr Projekt mit beliebten LLM-Anbietern zu verbinden (OpenAI, Grok, Claude usw.) - Projektspezifische Anweisungen für KI-Tools zu generieren und zu aktualisieren, damit alle konsistente, relevante Hilfe erhalten - Ihr Team ausgerichtet und produktiv zu halten, mit weniger Zeit für die Erklärung des Kontexts -Diese Funktionen sind in die Kern-CLI von Flight und das offizielle [flightphp/skeleton](https://github.com/flightphp/skeleton) Starter-Projekt integriert. +Diese Funktionen sind in die Flight-Core-CLI und das offizielle [flightphp/skeleton](https://github.com/flightphp/skeleton)-Starter-Projekt integriert. -## Grundlegende Verwendung +## Grundlegende Nutzung -### Einrichten von LLM-Zugangsdaten +### Einrichten von LLM-Anmeldeinformationen -Der Befehl `ai:init` führt Sie durch den Prozess, Ihr Projekt mit einem LLM-Anbieter zu verbinden. +Der Befehl `ai:init` führt Sie durch die Verbindung Ihres Projekts mit einem LLM-Anbieter. ```bash php runway ai:init @@ -28,48 +28,49 @@ Sie werden aufgefordert: - Ihren API-Schlüssel einzugeben - Die Basis-URL und den Modellnamen festzulegen -Dies erstellt eine `.runway-creds.json`-Datei im Stammverzeichnis Ihres Projekts (und stellt sicher, dass sie in Ihrer `.gitignore` ist). +Dies erstellt die notwendigen Anmeldeinformationen für zukünftige LLM-Anfragen. **Beispiel:** ``` -Willkommen bei AI Init! -Welchen LLM-API möchten Sie verwenden? [1] openai, [2] grok, [3] claude: 1 -Geben Sie die Basis-URL für die LLM-API ein [https://api.openai.com]: -Geben Sie Ihren API-Schlüssel für openai ein: sk-... -Geben Sie den Modellnamen ein, den Sie verwenden möchten (z. B. gpt-4, claude-3-opus usw.) [gpt-4o]: -Zugangsdaten in .runway-creds.json gespeichert +Welcome to AI Init! +Which LLM API do you want to use? [1] openai, [2] grok, [3] claude: 1 +Enter the base URL for the LLM API [https://api.openai.com]: +Enter your API key for openai: sk-... +Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: +Credentials saved to .runway-creds.json ``` -### Generieren projektspezifischer KI-Anweisungen +### Generieren von projektspezifischen KI-Anweisungen -Der Befehl `ai:generate-instructions` hilft Ihnen, Anweisungen für KI-Codierungsassistenten zu erstellen oder zu aktualisieren, die auf Ihr Projekt zugeschnitten sind. +Der Befehl `ai:generate-instructions` hilft Ihnen, Anweisungen für KI-Coding-Assistenten zu erstellen oder zu aktualisieren, die auf Ihr Projekt zugeschnitten sind. ```bash php runway ai:generate-instructions ``` -Sie beantworten ein paar Fragen zu Ihrem Projekt (Beschreibung, Datenbank, Templating, Sicherheit, Teamgröße usw.). Flight verwendet Ihren LLM-Anbieter, um Anweisungen zu generieren, und schreibt sie dann in: +Sie beantworten ein paar Fragen zu Ihrem Projekt (Beschreibung, Datenbank, Vorlagen, Sicherheit, Teamgröße usw.). Flight verwendet Ihren LLM-Anbieter, um Anweisungen zu generieren, und schreibt sie dann in: - `.github/copilot-instructions.md` (für GitHub Copilot) - `.cursor/rules/project-overview.mdc` (für Cursor) - `.windsurfrules` (für Windsurf) +- `.gemini/GEMINI.md` (für Antigravity) **Beispiel:** ``` -Beschreiben Sie bitte, wofür Ihr Projekt gedacht ist? Meine tolle API -Welche Datenbank planen Sie zu verwenden? MySQL -Welchen HTML-Templating-Engine planen Sie zu verwenden (falls zutreffend)? latte -Ist Sicherheit ein wichtiger Aspekt dieses Projekts? (y/n) y +Please describe what your project is for? My awesome API +What database are you planning on using? MySQL +What HTML templating engine will you plan on using (if any)? latte +Is security an important element of this project? (y/n) y ... -KI-Anweisungen erfolgreich aktualisiert. +AI instructions updated successfully. ``` Nun geben Ihre KI-Tools intelligentere, relevantere Vorschläge basierend auf den tatsächlichen Bedürfnissen Ihres Projekts. -## Erweiterte Verwendung +## Erweiterte Nutzung -- Sie können den Speicherort Ihrer Zugangsdaten- oder Anweisungsdateien mit Befehlsoptionen anpassen (siehe `--help` für jeden Befehl). +- Sie können den Speicherort Ihrer Anmeldeinformationen oder Anweisungsdateien mit Befehlsoptionen anpassen (siehe `--help` für jeden Befehl). - Die KI-Hilfsprogramme sind so konzipiert, dass sie mit jedem LLM-Anbieter funktionieren, der OpenAI-kompatible APIs unterstützt. -- Wenn Sie Ihre Anweisungen aktualisieren möchten, während sich Ihr Projekt weiterentwickelt, führen Sie einfach `ai:generate-instructions` erneut aus und beantworten Sie die Prompts erneut. +- Wenn Sie Ihre Anweisungen aktualisieren möchten, während sich Ihr Projekt weiterentwickelt, führen Sie einfach `ai:generate-instructions` erneut aus und beantworten Sie die Aufforderungen erneut. ## Siehe auch diff --git a/content/v3/en/learn/ai.md b/content/v3/en/learn/ai.md index 70357a54..ef22e6b0 100644 --- a/content/v3/en/learn/ai.md +++ b/content/v3/en/learn/ai.md @@ -2,7 +2,7 @@ ## Overview -Flight makes it easy to supercharge your PHP projects with AI-powered tools and modern developer workflows. With built-in commands for connecting to LLM (Large Language Model) providers and generating project-specific AI coding instructions, Flight helps you and your team get the most out of AI assistants like GitHub Copilot, Cursor, and Windsurf. +Flight makes it easy to supercharge your PHP projects with AI-powered tools and modern developer workflows. With built-in commands for connecting to LLM (Large Language Model) providers and generating project-specific AI coding instructions, Flight helps you and your team get the most out of AI assistants like GitHub Copilot, Cursor, Windsurf, and Antigravity (Gemini). ## Understanding @@ -28,7 +28,7 @@ You'll be prompted to: - Enter your API key - Set the base URL and model name -This creates a `.runway-creds.json` file in your project root (and ensures it's in your `.gitignore`). +This creates the necessary credentials for you to make future LLM requests. **Example:** ``` @@ -52,6 +52,7 @@ You'll answer a few questions about your project (description, database, templat - `.github/copilot-instructions.md` (for GitHub Copilot) - `.cursor/rules/project-overview.mdc` (for Cursor) - `.windsurfrules` (for Windsurf) +- `.gemini/GEMINI.md` (for Antigravity) **Example:** ``` diff --git a/content/v3/es/awesome-plugins/runway.md b/content/v3/es/awesome-plugins/runway.md index 7d45a232..7ac450ce 100644 --- a/content/v3/es/awesome-plugins/runway.md +++ b/content/v3/es/awesome-plugins/runway.md @@ -29,7 +29,7 @@ return [ > **NOTA** - A partir de **v1.2.0**, `.runway-config.json` está obsoleto. Por favor, migra tu configuración a `app/config/config.php`. Puedes hacerlo fácilmente con el comando `php runway config:migrate`. -### Detección de la Raíz del Proyecto +### Detección de Raíz del Proyecto Runway es lo suficientemente inteligente como para detectar la raíz de tu proyecto, incluso si lo ejecutas desde un subdirectorio. Busca indicadores como `composer.json`, `.git` o `app/config/config.php` para determinar dónde está la raíz del proyecto. Esto significa que puedes ejecutar comandos de Runway desde cualquier lugar en tu proyecto! @@ -74,7 +74,7 @@ Primero asegúrate de haber instalado el plugin [Active Record](/awesome-plugins php runway make:record users ``` -Por ejemplo, si tienes la tabla `users` con el siguiente esquema: `id`, `name`, `email`, `created_at`, `updated_at`, se creará un archivo similar al siguiente en el archivo `app/records/UserRecord.php`: +Si, por ejemplo, tienes la tabla `users` con el siguiente esquema: `id`, `name`, `email`, `created_at`, `updated_at`, se creará un archivo similar al siguiente en el archivo `app/records/UserRecord.php`: ```php **NOTE** - À partir de **v1.2.0**, `.runway-config.json` est déprécié. Veuillez migrer votre configuration vers `app/config/config.php`. Vous pouvez le faire facilement avec la commande `php runway config:migrate`. + + ### Détection de la Racine du Projet -Runway est assez intelligent pour détecter la racine de votre projet, même si vous l'exécutez depuis un sous-répertoire. Il recherche des indicateurs comme `composer.json`, `.git`, ou `app/config/config.php` pour déterminer où se trouve la racine du projet. Cela signifie que vous pouvez exécuter les commandes Runway depuis n'importe où dans votre projet ! +Runway est suffisamment intelligent pour détecter la racine de votre projet, même si vous l'exécutez depuis un sous-répertoire. Il recherche des indicateurs comme `composer.json`, `.git`, ou `app/config/config.php` pour déterminer où se trouve la racine du projet. Cela signifie que vous pouvez exécuter les commandes Runway de n'importe où dans votre projet ! ## Utilisation @@ -116,13 +118,13 @@ class UserRecord extends \flight\ActiveRecord ### Afficher Toutes les Routes -Cela affichera toutes les routes actuellement enregistrées avec Flight. +Cela affichera toutes les routes qui sont actuellement enregistrées avec Flight. ```bash php runway routes ``` -Si vous souhaitez voir uniquement des routes spécifiques, vous pouvez passer un drapeau pour filtrer les routes. +Si vous souhaitez ne voir que des routes spécifiques, vous pouvez passer un drapeau pour filtrer les routes. ```bash # Afficher uniquement les routes GET @@ -136,9 +138,9 @@ php runway routes --post ## Ajouter des Commandes Personnalisées à Runway -Si vous créez un package pour Flight, ou si vous souhaitez ajouter vos propres commandes personnalisées à votre projet, vous pouvez le faire en créant un répertoire `src/commands/`, `flight/commands/`, `app/commands/`, ou `commands/` pour votre projet/package. Si vous avez besoin de personnalisations supplémentaires, voir la section ci-dessous sur la Configuration. +Si vous créez un package pour Flight, ou si vous souhaitez ajouter vos propres commandes personnalisées à votre projet, vous pouvez le faire en créant un répertoire `src/commands/`, `flight/commands/`, `app/commands/`, ou `commands/` pour votre projet/package. Si vous avez besoin de personnalisations supplémentaires, consultez la section ci-dessous sur la Configuration. -Pour créer une commande, vous étendez simplement la classe `AbstractBaseCommand`, et implémentez au minimum une méthode `__construct` et une méthode `execute`. +Pour créer une commande, il vous suffit d'étendre la classe `AbstractBaseCommand` et d'implémenter au minimum une méthode `__construct` et une méthode `execute`. ```php [ - // C'est là que se trouve votre répertoire d'application + // C'est l'endroit où se trouve votre répertoire d'application 'app_root' => 'app/', // C'est le répertoire où se trouve votre fichier index racine @@ -231,9 +233,9 @@ return [ '/var/www/another-project' ], - // Les chemins de base n'ont probablement pas besoin d'être configurés, mais c'est là si vous le souhaitez + // Les chemins de base n'ont probablement pas besoin d'être configurés, mais ils sont là si vous en voulez 'base_paths' => [ - '/includes/libs/vendor', // si vous avez un chemin vraiment unique pour votre répertoire vendor ou quelque chose + '/includes/libs/vendor', // si vous avez un chemin vraiment unique pour votre répertoire vendor ou autre ], // Les chemins finaux sont des emplacements dans un projet pour rechercher les fichiers de commande @@ -254,7 +256,7 @@ return [ ### Accéder à la Configuration -Si vous avez besoin d'accéder efficacement aux valeurs de configuration, vous pouvez y accéder via la méthode `__construct` ou la méthode `app()`. Il est également important de noter que si vous avez un fichier `app/config/services.php`, ces services seront également disponibles pour votre commande. +Si vous devez accéder efficacement aux valeurs de configuration, vous pouvez les accéder via la méthode `__construct` ou la méthode `app()`. Il est également important de noter que si vous avez un fichier `app/config/services.php`, ces services seront également disponibles pour votre commande. ```php public function execute() @@ -271,9 +273,9 @@ public function execute() } ``` -## Enveloppeurs d'Aide IA +## Enveloppeurs d'Assistance IA -Runway dispose de quelques enveloppeurs d'aide qui facilitent la génération de commandes par l'IA. Vous pouvez utiliser `addOption` et `addArgument` d'une manière qui ressemble à Symfony Console. Cela est utile si vous utilisez des outils IA pour générer vos commandes. +Runway dispose de quelques enveloppeurs d'assistance qui facilitent la génération de commandes par l'IA. Vous pouvez utiliser `addOption` et `addArgument` de manière similaire à Symfony Console. C'est utile si vous utilisez des outils d'IA pour générer vos commandes. ```php public function __construct(array $config) diff --git a/content/v3/fr/learn/ai.md b/content/v3/fr/learn/ai.md index 86131c21..bc668ec6 100644 --- a/content/v3/fr/learn/ai.md +++ b/content/v3/fr/learn/ai.md @@ -2,13 +2,13 @@ ## Aperçu -Flight facilite le renforcement de vos projets PHP avec des outils alimentés par l'IA et des flux de travail modernes pour les développeurs. Avec des commandes intégrées pour se connecter aux fournisseurs de LLM (Large Language Model) et générer des instructions de codage IA spécifiques au projet, Flight vous aide, vous et votre équipe, à tirer le meilleur parti des assistants IA comme GitHub Copilot, Cursor et Windsurf. +Flight facilite le renforcement de vos projets PHP avec des outils alimentés par l'IA et des flux de travail modernes pour les développeurs. Avec des commandes intégrées pour se connecter aux fournisseurs de LLM (Large Language Model) et générer des instructions de codage IA spécifiques au projet, Flight vous aide, vous et votre équipe, à tirer le meilleur parti des assistants IA comme GitHub Copilot, Cursor, Windsurf et Antigravity (Gemini). ## Compréhension Les assistants de codage IA sont les plus utiles lorsqu'ils comprennent le contexte, les conventions et les objectifs de votre projet. Les aides IA de Flight vous permettent de : - Connecter votre projet à des fournisseurs de LLM populaires (OpenAI, Grok, Claude, etc.) -- Générer et mettre à jour des instructions spécifiques au projet pour les outils IA, afin que tout le monde reçoive une aide cohérente et pertinente +- Générer et mettre à jour des instructions spécifiques au projet pour les outils IA, afin que tout le monde obtienne une aide cohérente et pertinente - Maintenir votre équipe alignée et productive, avec moins de temps passé à expliquer le contexte Ces fonctionnalités sont intégrées au CLI principal de Flight et au projet de démarrage officiel [flightphp/skeleton](https://github.com/flightphp/skeleton). @@ -17,7 +17,7 @@ Ces fonctionnalités sont intégrées au CLI principal de Flight et au projet de ### Configuration des Identifiants LLM -La commande `ai:init` vous guide à travers la connexion de votre projet à un fournisseur de LLM. +La commande `ai:init` vous guide pour connecter votre projet à un fournisseur de LLM. ```bash php runway ai:init @@ -28,16 +28,16 @@ Vous serez invité à : - Entrer votre clé API - Définir l'URL de base et le nom du modèle -Cela crée un fichier `.runway-creds.json` à la racine de votre projet (et s'assure qu'il est dans votre `.gitignore`). +Cela crée les identifiants nécessaires pour effectuer de futures requêtes LLM. **Exemple :** ``` -Welcome to AI Init! -Which LLM API do you want to use? [1] openai, [2] grok, [3] claude: 1 -Enter the base URL for the LLM API [https://api.openai.com]: -Enter your API key for openai: sk-... -Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: -Credentials saved to .runway-creds.json +Bienvenue dans AI Init ! +Quel API LLM voulez-vous utiliser ? [1] openai, [2] grok, [3] claude : 1 +Entrez l'URL de base pour l'API LLM [https://api.openai.com] : +Entrez votre clé API pour openai : sk-... +Entrez le nom du modèle que vous voulez utiliser (ex. gpt-4, claude-3-opus, etc) [gpt-4o] : +Identifiants sauvegardés dans .runway-creds.json ``` ### Génération d'Instructions IA Spécifiques au Projet @@ -52,18 +52,19 @@ Vous répondrez à quelques questions sur votre projet (description, base de don - `.github/copilot-instructions.md` (pour GitHub Copilot) - `.cursor/rules/project-overview.mdc` (pour Cursor) - `.windsurfrules` (pour Windsurf) +- `.gemini/GEMINI.md` (pour Antigravity) **Exemple :** ``` -Please describe what your project is for? My awesome API -What database are you planning on using? MySQL -What HTML templating engine will you plan on using (if any)? latte -Is security an important element of this project? (y/n) y +Veuillez décrire à quoi sert votre projet ? Mon API géniale +Quelle base de données prévoyez-vous d'utiliser ? MySQL +Quel moteur de templating HTML prévoyez-vous d'utiliser (si applicable) ? latte +La sécurité est-elle un élément important de ce projet ? (o/n) o ... -AI instructions updated successfully. +Instructions IA mises à jour avec succès. ``` -Maintenant, vos outils IA fourniront des suggestions plus intelligentes et plus pertinentes basées sur les besoins réels de votre projet. +Désormais, vos outils IA fourniront des suggestions plus intelligentes et plus pertinentes basées sur les besoins réels de votre projet. ## Utilisation Avancée diff --git a/content/v3/id/awesome-plugins/runway.md b/content/v3/id/awesome-plugins/runway.md index bf6333c9..6e448b52 100644 --- a/content/v3/id/awesome-plugins/runway.md +++ b/content/v3/id/awesome-plugins/runway.md @@ -1,6 +1,6 @@ # Runway -Runway adalah aplikasi CLI yang membantu Anda mengelola aplikasi Flight Anda. Ini dapat menghasilkan controller, menampilkan semua rute, dan lainnya. Ini didasarkan pada pustaka [adhocore/php-cli](https://github.com/adhocore/php-cli) yang luar biasa. +Runway adalah aplikasi CLI yang membantu Anda mengelola aplikasi Flight Anda. Ini dapat menghasilkan controller, menampilkan semua rute, dan banyak lagi. Ini didasarkan pada pustaka [adhocore/php-cli](https://github.com/adhocore/php-cli) yang sangat baik. Klik [di sini](https://github.com/flightphp/runway) untuk melihat kode. @@ -14,7 +14,7 @@ composer require flightphp/runway ## Konfigurasi Dasar -Pada pertama kali Anda menjalankan Runway, itu akan mencoba mencari konfigurasi `runway` di `app/config/config.php` melalui kunci `'runway'`. +Untuk pertama kalinya Anda menjalankan Runway, itu akan mencoba mencari konfigurasi `runway` di `app/config/config.php` melalui kunci `'runway'`. ```php **CATATAN** - Mulai dari **v1.2.0**, `.runway-config.json` sudah tidak digunakan lagi. Silakan migrasikan konfigurasi Anda ke `app/config/config.php`. Anda dapat melakukan ini dengan mudah menggunakan perintah `php runway config:migrate`. + + ### Deteksi Root Proyek Runway cukup pintar untuk mendeteksi root proyek Anda, bahkan jika Anda menjalankannya dari subdirektori. Ini mencari indikator seperti `composer.json`, `.git`, atau `app/config/config.php` untuk menentukan di mana root proyek berada. Ini berarti Anda dapat menjalankan perintah Runway dari mana saja di proyek Anda! @@ -50,7 +52,7 @@ php runway ### Bantuan Perintah -Untuk perintah apa pun, Anda dapat menambahkan flag `--help` untuk mendapatkan informasi lebih lanjut tentang cara menggunakan perintah tersebut. +Untuk perintah apa pun, Anda dapat memberikan flag `--help` untuk mendapatkan informasi lebih lanjut tentang cara menggunakan perintah tersebut. ```bash php runway routes --help @@ -92,20 +94,20 @@ namespace app\records; * @property string $email * @property string $created_at * @property string $updated_at - * // Anda juga bisa menambahkan relasi di sini setelah mendefinisikannya di array $relations - * @property CompanyRecord $company Contoh relasi + * // you could also add relationships here once you define them in the $relations array + * @property CompanyRecord $company Example of a relationship */ class UserRecord extends \flight\ActiveRecord { /** - * @var array $relations Atur relasi untuk model + * @var array $relations Set the relationships for the model * https://docs.flightphp.com/awesome-plugins/active-record#relationships */ protected array $relations = []; /** - * Konstruktor - * @param mixed $databaseConnection Koneksi ke database + * Constructor + * @param mixed $databaseConnection The connection to the database */ public function __construct($databaseConnection) { @@ -122,23 +124,23 @@ Ini akan menampilkan semua rute yang saat ini terdaftar dengan Flight. php runway routes ``` -Jika Anda ingin hanya melihat rute tertentu, Anda dapat menambahkan flag untuk memfilter rute. +Jika Anda ingin hanya melihat rute tertentu, Anda dapat memberikan flag untuk memfilter rute. ```bash -# Tampilkan hanya rute GET +# Menampilkan hanya rute GET php runway routes --get -# Tampilkan hanya rute POST +# Menampilkan hanya rute POST php runway routes --post -# dst. +# dll. ``` ## Menambahkan Perintah Kustom ke Runway -Jika Anda sedang membuat paket untuk Flight, atau ingin menambahkan perintah kustom sendiri ke proyek Anda, Anda dapat melakukannya dengan membuat direktori `src/commands/`, `flight/commands/`, `app/commands/`, atau `commands/` untuk proyek/paket Anda. Jika Anda membutuhkan penyesuaian lebih lanjut, lihat bagian di bawah tentang Konfigurasi. +Jika Anda membuat paket untuk Flight, atau ingin menambahkan perintah kustom sendiri ke proyek Anda, Anda dapat melakukannya dengan membuat direktori `src/commands/`, `flight/commands/`, `app/commands/`, atau `commands/` untuk proyek/paket Anda. Jika Anda membutuhkan penyesuaian lebih lanjut, lihat bagian di bawah tentang Konfigurasi. -Untuk membuat perintah, Anda cukup memperluas kelas `AbstractBaseCommand`, dan mengimplementasikan minimal metode `__construct` dan metode `execute`. +Untuk membuat perintah, Anda cukup memperluas kelas `AbstractBaseCommand`, dan menerapkan setidaknya metode `__construct` dan metode `execute`. ```php $config Konfigurasi dari app/config/config.php + * @param array $config Config from app/config/config.php */ public function __construct(array $config) { - parent::__construct('make:example', 'Buat contoh untuk dokumentasi', $config); - $this->argument('', 'Nama dari gif lucu'); + parent::__construct('make:example', 'Create an example for the documentation', $config); + $this->argument('', 'The name of the funny gif'); } /** - * Menjalankan fungsi + * Executes the function * * @return void */ @@ -169,11 +171,11 @@ class ExampleCommand extends AbstractBaseCommand { $io = $this->app()->io(); - $io->info('Membuat contoh...'); + $io->info('Creating example...'); - // Lakukan sesuatu di sini + // Do something here - $io->ok('Contoh dibuat!'); + $io->ok('Example created!'); } } ``` @@ -216,33 +218,33 @@ Jika Anda perlu menyesuaikan konfigurasi untuk Runway, Anda dapat mengatur nilai [ - // Ini adalah lokasi direktori aplikasi Anda + // This is where your application directory is located 'app_root' => 'app/', - // Ini adalah direktori di mana file index root Anda berada + // This is the directory where your root index file is located 'index_root' => 'public/', - // Ini adalah path ke root proyek lainnya + // These are the paths to the roots of other projects 'root_paths' => [ '/home/user/different-project', '/var/www/another-project' ], - // Path dasar kemungkinan besar tidak perlu dikonfigurasi, tapi ini ada jika Anda menginginkannya + // Base paths most likely don't need to be configured, but it's here if you want it 'base_paths' => [ - '/includes/libs/vendor', // jika Anda memiliki path yang sangat unik untuk direktori vendor atau semacamnya + '/includes/libs/vendor', // if you have a really unique path for your vendor directory or something ], - // Path akhir adalah lokasi dalam proyek untuk mencari file perintah + // Final paths are locations within a project to search for the command files 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // Jika Anda ingin menambahkan path lengkap, silakan (absolut atau relatif terhadap root proyek) + // If you want to just add the full path, go right ahead (absolute or relative to project root) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -254,33 +256,33 @@ return [ ### Mengakses Konfigurasi -Jika Anda perlu mengakses nilai konfigurasi secara efektif, Anda dapat mengaksesnya melalui metode `__construct` atau metode `app()`. Penting juga untuk dicatat bahwa jika Anda memiliki file `app/config/services.php`, layanan tersebut juga akan tersedia untuk perintah Anda. +Jika Anda perlu mengakses nilai konfigurasi secara efektif, Anda dapat mengaksesnya melalui metode `__construct` atau metode `app()`. Penting juga untuk dicatat bahwa jika Anda memiliki file `app/config/services.php`, layanan-layanan tersebut juga akan tersedia untuk perintah Anda. ```php public function execute() { $io = $this->app()->io(); - // Akses konfigurasi + // Access configuration $app_root = $this->config['runway']['app_root']; - // Akses layanan seperti mungkin koneksi database + // Access services like maybe a database connection $database = $this->config['database'] // ... } ``` -## Wrapper Pembantu AI +## Wrapper Bantu AI -Runway memiliki beberapa wrapper pembantu yang membuat lebih mudah bagi AI untuk menghasilkan perintah. Anda dapat menggunakan `addOption` dan `addArgument` dengan cara yang mirip dengan Symfony Console. Ini membantu jika Anda menggunakan alat AI untuk menghasilkan perintah Anda. +Runway memiliki beberapa wrapper bantu yang memudahkan AI untuk menghasilkan perintah. Anda dapat menggunakan `addOption` dan `addArgument` dengan cara yang mirip dengan Symfony Console. Ini membantu jika Anda menggunakan alat AI untuk menghasilkan perintah Anda. ```php public function __construct(array $config) { - parent::__construct('make:example', 'Buat contoh untuk dokumentasi', $config); + parent::__construct('make:example', 'Create an example for the documentation', $config); - // Argumen mode bersifat nullable dan defaultnya sepenuhnya opsional - $this->addOption('name', 'Nama dari contoh', null); + // The mode argument is nullable and defaults to completely optional + $this->addOption('name', 'The name of the example', null); } ``` \ No newline at end of file diff --git a/content/v3/id/learn/ai.md b/content/v3/id/learn/ai.md index 8779ca19..629a603c 100644 --- a/content/v3/id/learn/ai.md +++ b/content/v3/id/learn/ai.md @@ -2,11 +2,11 @@ ## Gambaran Umum -Flight memudahkan Anda untuk meningkatkan proyek PHP Anda dengan alat berbasis AI dan alur kerja pengembang modern. Dengan perintah bawaan untuk menghubungkan ke penyedia LLM (Large Language Model) dan menghasilkan instruksi pengkodean AI khusus proyek, Flight membantu Anda dan tim Anda mendapatkan manfaat maksimal dari asisten AI seperti GitHub Copilot, Cursor, dan Windsurf. +Flight memudahkan Anda untuk meningkatkan proyek PHP Anda dengan alat berbasis AI dan alur kerja pengembang modern. Dengan perintah bawaan untuk terhubung ke penyedia LLM (Large Language Model) dan menghasilkan instruksi pengkodean AI khusus proyek, Flight membantu Anda dan tim Anda mendapatkan manfaat maksimal dari asisten AI seperti GitHub Copilot, Cursor, Windsurf, dan Antigravity (Gemini). ## Pemahaman -Asisten pengkodean AI paling membantu ketika mereka memahami konteks proyek Anda, konvensi, dan tujuan. Pembantu AI Flight memungkinkan Anda: +Asisten pengkodean AI paling membantu ketika mereka memahami konteks, konvensi, dan tujuan proyek Anda. Pembantu AI Flight memungkinkan Anda untuk: - Menghubungkan proyek Anda ke penyedia LLM populer (OpenAI, Grok, Claude, dll.) - Menghasilkan dan memperbarui instruksi khusus proyek untuk alat AI, sehingga semua orang mendapatkan bantuan yang konsisten dan relevan - Menjaga tim Anda tetap selaras dan produktif, dengan waktu yang lebih sedikit untuk menjelaskan konteks @@ -15,9 +15,9 @@ Fitur-fitur ini dibangun ke dalam CLI inti Flight dan proyek starter resmi [flig ## Penggunaan Dasar -### Menyiapkan Kredensial LLM +### Mengatur Kredensial LLM -Perintah `ai:init` memandu Anda melalui proses menghubungkan proyek Anda ke penyedia LLM. +Perintah `ai:init` akan memandu Anda melalui proses menghubungkan proyek Anda ke penyedia LLM. ```bash php runway ai:init @@ -28,7 +28,7 @@ Anda akan diminta untuk: - Memasukkan kunci API Anda - Mengatur URL dasar dan nama model -Ini membuat file `.runway-creds.json` di root proyek Anda (dan memastikan itu ada di `.gitignore` Anda). +Ini membuat kredensial yang diperlukan agar Anda dapat melakukan permintaan LLM di masa depan. **Contoh:** ``` @@ -42,7 +42,7 @@ Credentials saved to .runway-creds.json ### Menghasilkan Instruksi AI Khusus Proyek -Perintah `ai:generate-instructions` membantu Anda membuat atau memperbarui instruksi untuk asisten pengkodean AI, disesuaikan dengan proyek Anda. +Perintah `ai:generate-instructions` membantu Anda membuat atau memperbarui instruksi untuk asisten pengkodean AI, yang disesuaikan dengan proyek Anda. ```bash php runway ai:generate-instructions @@ -52,6 +52,7 @@ Anda akan menjawab beberapa pertanyaan tentang proyek Anda (deskripsi, database, - `.github/copilot-instructions.md` (untuk GitHub Copilot) - `.cursor/rules/project-overview.mdc` (untuk Cursor) - `.windsurfrules` (untuk Windsurf) +- `.gemini/GEMINI.md` (untuk Antigravity) **Contoh:** ``` @@ -63,7 +64,7 @@ Is security an important element of this project? (y/n) y AI instructions updated successfully. ``` -Sekarang, alat AI Anda akan memberikan saran yang lebih cerdas dan relevan berdasarkan kebutuhan nyata proyek Anda. +Sekarang, alat AI Anda akan memberikan saran yang lebih pintar dan lebih relevan berdasarkan kebutuhan nyata proyek Anda. ## Penggunaan Lanjutan diff --git a/content/v3/ja/awesome-plugins/runway.md b/content/v3/ja/awesome-plugins/runway.md index 2c233ac4..bdf3c7c0 100644 --- a/content/v3/ja/awesome-plugins/runway.md +++ b/content/v3/ja/awesome-plugins/runway.md @@ -1,8 +1,8 @@ # Runway -Runway は、Flight アプリケーションを管理するのに役立つ CLI アプリケーションです。コントローラーを生成したり、全ルートを表示したり、その他多くの機能を提供します。これは優れた [adhocore/php-cli](https://github.com/adhocore/php-cli) ライブラリを基にしています。 +Runway は、Flight アプリケーションを管理するための CLI アプリケーションです。コントローラーの生成、すべてのルートの表示などを行えます。[adhocore/php-cli](https://github.com/adhocore/php-cli) ライブラリを基にしています。 -コードを見るには [こちら](https://github.com/flightphp/runway) をクリックしてください。 +コードを表示するには [こちら](https://github.com/flightphp/runway) をクリックしてください。 ## インストール @@ -14,7 +14,7 @@ composer require flightphp/runway ## 基本設定 -Runway を初めて実行すると、`app/config/config.php` 内の `'runway'` キーから `runway` 設定を探そうとします。 +Runway を初めて実行すると、`app/config/config.php` 内の `'runway'` キーから `runway` 設定を探します。 ```php **注意** - **v1.2.0** 以降、`.runway-config.json` は非推奨です。設定を `app/config/config.php` に移行してください。これを簡単に実行するには、`php runway config:migrate` コマンドを使用できます。 +> **注意** - **v1.2.0** 以降、`.runway-config.json` は非推奨です。設定を `app/config/config.php` に移行してください。`php runway config:migrate` コマンドで簡単に実行できます。 + + ### プロジェクトルートの検出 -Runway は、プロジェクトのルートを検出するのに十分賢いです。サブディレクトリから実行した場合でも、`composer.json`、`.git`、または `app/config/config.php` などの指標を探してプロジェクトルートを決定します。これにより、プロジェクト内のどこからでも Runway コマンドを実行できます! +Runway は、プロジェクトのルートを検出するのに十分賢いです。サブディレクトリから実行した場合でも、`composer.json`、`.git`、または `app/config/config.php` などの指標を探してプロジェクトルートを決定します。これにより、プロジェクト内のどこからでも Runway コマンドを実行できます! ## 使用方法 @@ -42,7 +44,7 @@ Runway には、Flight アプリケーションを管理するためのいくつ ### コマンドリスト -`php runway` コマンドを実行することで、利用可能なすべてのコマンドのリストを表示できます。 +`php runway` コマンドを実行することで、すべての利用可能なコマンドのリストを表示できます。 ```bash php runway @@ -50,17 +52,17 @@ php runway ### コマンドヘルプ -任意のコマンドに対して、`--help` フラグを渡すことでコマンドの使用方法に関する詳細情報を取得できます。 +任意のコマンドに対して、`--help` フラグを渡すことでコマンドの使用方法についての詳細情報を取得できます。 ```bash php runway routes --help ``` -以下にいくつかの例を示します。 +以下にいくつかの例を示します: ### コントローラーの生成 -`runway.app_root` の設定に基づいて、場所が `app/controllers/` ディレクトリにコントローラーを生成します。 +`runway.app_root` の設定に基づいて、`app/controllers/` ディレクトリにコントローラーを生成します。 ```bash php runway make:controller MyController @@ -68,13 +70,13 @@ php runway make:controller MyController ### Active Record モデルの生成 -まず、[Active Record](/awesome-plugins/active-record) プラグインをインストールしたことを確認してください。`runway.app_root` の設定に基づいて、場所が `app/records/` ディレクトリにレコードを生成します。 +まず [Active Record](/awesome-plugins/active-record) プラグインをインストールしていることを確認してください。`runway.app_root` の設定に基づいて、`app/records/` ディレクトリにレコードを生成します。 ```bash php runway make:record users ``` -たとえば、`users` テーブルに以下のスキーマがある場合:`id`、`name`、`email`、`created_at`、`updated_at`、`app/records/UserRecord.php` ファイルに以下の類似したファイルが作成されます: +たとえば、`users` テーブルに `id`、`name`、`email`、`created_at`、`updated_at` のスキーマがある場合、`app/records/UserRecord.php` ファイルに以下のようないくつかのファイルが作成されます: ```php [ - // アプリケーション ディレクトリが配置されている場所 + // アプリケーション ディレクトリの場所 'app_root' => 'app/', - // ルートインデックスファイルが配置されているディレクトリ + // ルート index ファイルの場所のディレクトリ 'index_root' => 'public/', - // 他のプロジェクトのルートへのパス + // 他のプロジェクトのルートの経路 'root_paths' => [ '/home/user/different-project', '/var/www/another-project' ], - // ベースパスは通常設定する必要はありませんが、必要に応じてここにあります + // 基本経路は通常設定する必要はありませんが、必要に応じて使用 'base_paths' => [ - '/includes/libs/vendor', // vendor ディレクトリに非常に独自のパスがある場合など + '/includes/libs/vendor', // vendor ディレクトリなどに独自の経路がある場合 ], - // 最終パスは、プロジェクト内のコマンドファイルを検索する場所です + // 最終経路は、プロジェクト内のコマンドファイルを探す場所 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // フルパスを追加したい場合、問題ありません(プロジェクトルートからの絶対または相対パス) + // 完全な経路を追加したい場合(プロジェクトルートからの絶対または相対) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -254,7 +256,7 @@ return [ ### 設定へのアクセス -設定値に効果的にアクセスする必要がある場合、`__construct` メソッドまたは `app()` メソッド経由でアクセスできます。また、`app/config/services.php` ファイルがある場合、そのサービスもコマンドで利用可能であることに注意してください。 +設定値に効果的にアクセスする必要がある場合、`__construct` メソッドまたは `app()` メソッド経由でアクセスできます。また、`app/config/services.php` ファイルがある場合、そのサービスもコマンドで利用可能です。 ```php public function execute() @@ -273,14 +275,14 @@ public function execute() ## AI ヘルパー ラッパー -Runway には、AI がコマンドを生成しやすくするためのヘルパー ラッパーがいくつかあります。Symfony Console に似た方法で `addOption` および `addArgument` を使用できます。AI ツールを使用してコマンドを生成する場合に役立ちます。 +Runway には、AI がコマンドを生成しやすくするためのヘルパー ラッパーがあります。Symfony Console に似た方法で `addOption` および `addArgument` を使用できます。AI ツールを使用してコマンドを生成する場合に役立ちます。 ```php public function __construct(array $config) { parent::__construct('make:example', 'ドキュメント用の例を作成', $config); - // name オプションは null 可能で、完全にオプションのデフォルトです + // name オプションは null 可能で、完全にオプションのデフォルト $this->addOption('name', '例の名前', null); } ``` \ No newline at end of file diff --git a/content/v3/ja/learn/ai.md b/content/v3/ja/learn/ai.md index d5fd5579..c6c994d9 100644 --- a/content/v3/ja/learn/ai.md +++ b/content/v3/ja/learn/ai.md @@ -2,14 +2,14 @@ ## 概要 -Flight は、AI 駆動のツールと現代的な開発者ワークフローを使用して PHP プロジェクトを強化することを容易にします。LLM (Large Language Model) プロバイダへの接続やプロジェクト固有の AI コーディング指示の生成のための組み込みコマンドにより、Flight は GitHub Copilot、Cursor、Windsurf などの AI アシスタントから最大限の効果を得るのをあなたとあなたのチームを支援します。 +Flight は、AI 駆動のツールと現代的な開発者ワークフローを使用して PHP プロジェクトを強化することを容易にします。LLM (Large Language Model) プロバイダーへの接続のための組み込みコマンドと、プロジェクト固有の AI コーディング指示を生成するための機能により、Flight は GitHub Copilot、Cursor、Windsurf、Antigravity (Gemini) などの AI アシスタントを最大限に活用するのに役立ちます。 ## 理解 -AI コーディングアシスタントは、プロジェクトのコンテキスト、慣習、目標を理解しているときに最も役立ちます。Flight の AI ヘルパーは以下のことを可能にします: -- プロジェクトを人気の LLM プロバイダ (OpenAI、Grok、Claude など) に接続する -- AI ツール向けのプロジェクト固有の指示を生成および更新する。これにより、誰もが一貫した関連性の高いヘルプを得られる -- コンテキストの説明に費やす時間を減らし、チームを一致させ生産性を高める +AI コーディングアシスタントは、プロジェクトのコンテキスト、慣習、目標を理解しているときに最も役立ちます。Flight の AI ヘルパーは、以下のことを可能にします: +- プロジェクトを人気の LLM プロバイダー (OpenAI、Grok、Claude など) に接続する +- AI ツールのためのプロジェクト固有の指示を生成および更新し、すべての人が一貫性のある関連するヘルプを得られるようにする +- コンテキストの説明に費やす時間を減らし、チームを一致させ生産性を維持する これらの機能は、Flight コア CLI と公式の [flightphp/skeleton](https://github.com/flightphp/skeleton) スタータープロジェクトに組み込まれています。 @@ -17,18 +17,18 @@ AI コーディングアシスタントは、プロジェクトのコンテキ ### LLM 認証情報の設定 -`ai:init` コマンドは、プロジェクトを LLM プロバイダに接続するためのガイドを提供します。 +`ai:init` コマンドは、プロジェクトを LLM プロバイダーに接続するプロセスをガイドします。 ```bash php runway ai:init ``` 以下のプロンプトが表示されます: -- プロバイダを選択 (OpenAI、Grok、Claude など) -- API キーを入力 -- ベース URL とモデル名を設定 +- プロバイダーの選択 (OpenAI、Grok、Claude など) +- API キーの入力 +- ベース URL とモデル名の設定 -これにより、プロジェクトルートに `.runway-creds.json` ファイルが作成され (`.gitignore` に含まれることを確認)、。 +これにより、将来の LLM リクエストに必要な認証情報が作成されます。 **例:** ``` @@ -42,16 +42,17 @@ Credentials saved to .runway-creds.json ### プロジェクト固有の AI 指示の生成 -`ai:generate-instructions` コマンドは、プロジェクトに合わせた AI コーディングアシスタント向けの指示を作成または更新するのを支援します。 +`ai:generate-instructions` コマンドは、プロジェクトに合わせて調整された AI コーディングアシスタントのための指示を作成または更新するのに役立ちます。 ```bash php runway ai:generate-instructions ``` -プロジェクトについて (説明、データベース、テンプレート、セキュリティ、チームサイズなど) のいくつかの質問に答えます。Flight は LLM プロバイダを使用して指示を生成し、次のファイルに書き込みます: +プロジェクトについて (説明、データベース、テンプレート、セキュリティ、チームサイズなど) のいくつかの質問に答えます。Flight は LLM プロバイダーを使用して指示を生成し、それを以下の場所に書き込みます: - `.github/copilot-instructions.md` (GitHub Copilot 用) - `.cursor/rules/project-overview.mdc` (Cursor 用) - `.windsurfrules` (Windsurf 用) +- `.gemini/GEMINI.md` (Antigravity 用) **例:** ``` @@ -63,24 +64,24 @@ Is security an important element of this project? (y/n) y AI instructions updated successfully. ``` -これで、AI ツールはプロジェクトの実ニーズに基づいたより賢く関連性の高い提案を提供します。 +これで、AI ツールはプロジェクトの実ニーズに基づいた、より賢く関連性の高い提案を提供します。 ## 高度な使用方法 -- コマンドオプションを使用して認証情報や指示ファイルの場所をカスタマイズできます (各コマンドの `--help` を参照)。 -- AI ヘルパーは、OpenAI 互換 API をサポートする任意の LLM プロバイダで動作するよう設計されています。 +- コマンドオプションを使用して認証情報や指示ファイルの場所をカスタマイズできます (各コマンドで `--help` を参照)。 +- AI ヘルパーは、OpenAI 互換 API をサポートする任意の LLM プロバイダーと動作するように設計されています。 - プロジェクトが進化したら指示を更新したい場合、`ai:generate-instructions` を再実行してプロンプトに再度答えてください。 ## 関連項目 - [Flight Skeleton](https://github.com/flightphp/skeleton) – AI 統合付きの公式スターター -- [Runway CLI](/awesome-plugins/runway) – これらのコマンドを駆動する CLI ツールの詳細 +- [Runway CLI](/awesome-plugins/runway) – これらのコマンドを駆動する CLI ツールについて詳しく ## トラブルシューティング - 「Missing .runway-creds.json」が表示された場合、まず `php runway ai:init` を実行してください。 -- API キーが有効で選択したモデルにアクセス可能であることを確認してください。 -- 指示が更新されない場合、プロジェクトディレクトリのファイル権限を確認してください。 +- API キーが有効で、選択したモデルへのアクセス権があることを確認してください。 +- 指示が更新されない場合、プロジェクトディレクトリのファイルパーミッションを確認してください。 ## 変更履歴 diff --git a/content/v3/ko/awesome-plugins/runway.md b/content/v3/ko/awesome-plugins/runway.md index 071fee97..f2f42b6f 100644 --- a/content/v3/ko/awesome-plugins/runway.md +++ b/content/v3/ko/awesome-plugins/runway.md @@ -1,18 +1,18 @@ # Runway -Runway는 Flight 애플리케이션을 관리하는 데 도움이 되는 CLI 애플리케이션입니다. 컨트롤러를 생성하고, 모든 경로를 표시하며, 그 외 더 많은 기능을 제공합니다. 이는 우수한 [adhocore/php-cli](https://github.com/adhocore/php-cli) 라이브러리를 기반으로 합니다. +Runway는 Flight 애플리케이션을 관리하는 데 도움을 주는 CLI 애플리케이션입니다. 컨트롤러를 생성하고, 모든 경로를 표시하며, 그 이상의 기능을 제공합니다. 이는 훌륭한 [adhocore/php-cli](https://github.com/adhocore/php-cli) 라이브러리를 기반으로 합니다. -코드 보기: [여기](https://github.com/flightphp/runway)를 클릭하세요. +코드 보기 [여기](https://github.com/flightphp/runway)를 클릭하세요. -## Installation +## 설치 -composer를 사용하여 설치하세요. +Composer를 사용하여 설치하세요. ```bash composer require flightphp/runway ``` -## Basic Configuration +## 기본 구성 Runway를 처음 실행할 때, `app/config/config.php`의 `'runway'` 키를 통해 `runway` 구성을 찾으려고 시도합니다. @@ -27,30 +27,30 @@ return [ ]; ``` -> **NOTE** - **v1.2.0**부터 `.runway-config.json`은 더 이상 사용되지 않습니다. 구성을 `app/config/config.php`로 마이그레이션하세요. `php runway config:migrate` 명령으로 쉽게 할 수 있습니다. +> **참고** - **v1.2.0**부터 `.runway-config.json`은 더 이상 사용되지 않습니다. 구성을 `app/config/config.php`로 이전하세요. `php runway config:migrate` 명령어를 사용하여 쉽게 할 수 있습니다. -### Project Root Detection +### 프로젝트 루트 감지 -Runway는 하위 디렉토리에서 실행하더라도 프로젝트 루트를 감지할 수 있을 만큼 똑똑합니다. `composer.json`, `.git`, 또는 `app/config/config.php`와 같은 지표를 찾아 프로젝트 루트를 결정합니다. 따라서 프로젝트의 어디서나 Runway 명령을 실행할 수 있습니다! +Runway는 하위 디렉토리에서 실행하더라도 프로젝트의 루트를 감지할 만큼 똑똑합니다. `composer.json`, `.git`, 또는 `app/config/config.php`와 같은 지표를 찾아 프로젝트 루트가 어디인지 결정합니다. 이는 프로젝트의 어디서든 Runway 명령어를 실행할 수 있음을 의미합니다! -## Usage +## 사용법 -Runway에는 Flight 애플리케이션을 관리하는 데 사용할 수 있는 여러 명령이 있습니다. Runway를 사용하는 두 가지 쉬운 방법이 있습니다. +Runway에는 Flight 애플리케이션을 관리하는 데 사용할 수 있는 여러 명령어가 있습니다. Runway를 사용하는 두 가지 쉬운 방법이 있습니다. 1. 스켈레톤 프로젝트를 사용 중이라면, 프로젝트 루트에서 `php runway [command]`를 실행할 수 있습니다. -1. composer를 통해 설치된 패키지로 Runway를 사용 중이라면, 프로젝트 루트에서 `vendor/bin/runway [command]`를 실행할 수 있습니다. +1. Composer를 통해 설치된 패키지로 Runway를 사용 중이라면, 프로젝트 루트에서 `vendor/bin/runway [command]`를 실행할 수 있습니다. -### Command List +### 명령어 목록 -`php runway` 명령을 실행하여 모든 사용 가능한 명령 목록을 볼 수 있습니다. +`php runway` 명령어를 실행하여 사용 가능한 모든 명령어 목록을 볼 수 있습니다. ```bash php runway ``` -### Command Help +### 명령어 도움말 -어떤 명령에 대해서든 `--help` 플래그를 전달하여 명령 사용 방법에 대한 더 많은 정보를 얻을 수 있습니다. +어떤 명령어든 `--help` 플래그를 전달하여 명령어를 사용하는 방법에 대한 더 많은 정보를 얻을 수 있습니다. ```bash php runway routes --help @@ -58,23 +58,23 @@ php runway routes --help 다음은 몇 가지 예시입니다: -### Generate a Controller +### 컨트롤러 생성 -`runway.app_root`의 구성에 따라, `app/controllers/` 디렉토리에 컨트롤러를 생성합니다. +`runway.app_root`의 구성에 기반하여, `app/controllers/` 디렉토리에 컨트롤러를 생성합니다. ```bash php runway make:controller MyController ``` -### Generate an Active Record Model +### Active Record 모델 생성 -먼저 [Active Record](/awesome-plugins/active-record) 플러그인을 설치했는지 확인하세요. `runway.app_root`의 구성에 따라, `app/records/` 디렉토리에 레코드를 생성합니다. +먼저 [Active Record](/awesome-plugins/active-record) 플러그인이 설치되었는지 확인하세요. `runway.app_root`의 구성에 기반하여, `app/records/` 디렉토리에 레코드를 생성합니다. ```bash php runway make:record users ``` -예를 들어 `users` 테이블이 `id`, `name`, `email`, `created_at`, `updated_at` 스키마를 가진 경우, `app/records/UserRecord.php` 파일에 다음과 유사한 파일이 생성됩니다: +예를 들어, `users` 테이블에 다음 스키마가 있는 경우: `id`, `name`, `email`, `created_at`, `updated_at`, `app/records/UserRecord.php` 파일에 다음과 유사한 파일이 생성됩니다: ```php $config Config from app/config/config.php + * @param array $config app/config/config.php의 구성 */ public function __construct(array $config) { - parent::__construct('make:example', 'Create an example for the documentation', $config); - $this->argument('', 'The name of the funny gif'); + parent::__construct('make:example', '문서화를 위한 예시 생성', $config); + $this->argument('', '재미있는 GIF의 이름'); } /** - * Executes the function + * 함수 실행 * * @return void */ @@ -169,80 +169,80 @@ class ExampleCommand extends AbstractBaseCommand { $io = $this->app()->io(); - $io->info('Creating example...'); + $io->info('예시 생성 중...'); - // Do something here + // 여기에 무언가를 수행 - $io->ok('Example created!'); + $io->ok('예시가 생성되었습니다!'); } } ``` -Flight 애플리케이션에 사용자 지정 명령을 구축하는 방법에 대한 자세한 정보는 [adhocore/php-cli Documentation](https://github.com/adhocore/php-cli)을 참조하세요! +Flight 애플리케이션에 사용자 지정 명령어를 구축하는 방법에 대한 자세한 정보는 [adhocore/php-cli 문서](https://github.com/adhocore/php-cli)를 참조하세요! -## Configuration Management +## 구성 관리 -`v1.2.0`부터 구성이 `app/config/config.php`로 이동되었으므로, 구성을 관리하는 몇 가지 도우미 명령이 있습니다. +`v1.2.0`부터 구성이 `app/config/config.php`로 이동되었으므로, 구성을 관리하는 몇 가지 도우미 명령어가 있습니다. -### Migrate Old Config +### 이전 구성 마이그레이션 -이전 `.runway-config.json` 파일이 있다면, 다음 명령으로 `app/config/config.php`로 쉽게 마이그레이션할 수 있습니다: +이전 `.runway-config.json` 파일이 있다면, 다음 명령어로 `app/config/config.php`로 쉽게 마이그레이션할 수 있습니다: ```bash php runway config:migrate ``` -### Set Configuration Value +### 구성 값 설정 -`config:set` 명령을 사용하여 구성 값을 설정할 수 있습니다. 파일을 열지 않고 구성 값을 업데이트하려는 경우 유용합니다. +`config:set` 명령어를 사용하여 구성 값을 설정할 수 있습니다. 파일을 열지 않고 구성 값을 업데이트하려는 경우 유용합니다. ```bash php runway config:set app_root "app/" ``` -### Get Configuration Value +### 구성 값 가져오기 -`config:get` 명령을 사용하여 구성 값을 가져올 수 있습니다. +`config:get` 명령어를 사용하여 구성 값을 가져올 수 있습니다. ```bash php runway config:get app_root ``` -## All Runway Configurations +## 모든 Runway 구성 -Runway 구성을 사용자 지정해야 한다면, `app/config/config.php`에 이러한 값을 설정할 수 있습니다. 아래는 설정할 수 있는 몇 가지 추가 구성입니다: +Runway의 구성을 사용자 정의해야 한다면, `app/config/config.php`에 이러한 값을 설정할 수 있습니다. 아래는 설정할 수 있는 추가 구성입니다: ```php [ - // This is where your application directory is located + // 애플리케이션 디렉토리가 위치한 곳 'app_root' => 'app/', - // This is the directory where your root index file is located + // 루트 인덱스 파일이 위치한 디렉토리 'index_root' => 'public/', - // These are the paths to the roots of other projects + // 다른 프로젝트의 루트 경로들 'root_paths' => [ '/home/user/different-project', '/var/www/another-project' ], - // Base paths most likely don't need to be configured, but it's here if you want it + // 기본 경로는 대부분 구성할 필요가 없지만, 필요하다면 여기에 있습니다 'base_paths' => [ - '/includes/libs/vendor', // if you have a really unique path for your vendor directory or something + '/includes/libs/vendor', // 벤더 디렉토리에 정말 독특한 경로가 있는 경우 등 ], - // Final paths are locations within a project to search for the command files + // 최종 경로는 프로젝트 내 명령어 파일을 검색할 위치입니다 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // If you want to just add the full path, go right ahead (absolute or relative to project root) + // 전체 경로를 추가하려면, 그대로 진행하세요 (프로젝트 루트에 대한 절대 또는 상대 경로) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -252,35 +252,35 @@ return [ ]; ``` -### Accessing Configuration +### 구성 접근 -구성 값을 효과적으로 액세스해야 한다면, `__construct` 메서드나 `app()` 메서드를 통해 액세스할 수 있습니다. 또한 `app/config/services.php` 파일이 있는 경우, 해당 서비스도 명령에서 사용할 수 있습니다. +구성 값을 효과적으로 접근해야 한다면, `__construct` 메서드나 `app()` 메서드를 통해 접근할 수 있습니다. 또한 `app/config/services.php` 파일이 있는 경우, 해당 서비스도 명령어에서 사용할 수 있습니다. ```php public function execute() { $io = $this->app()->io(); - // Access configuration + // 구성 접근 $app_root = $this->config['runway']['app_root']; - // Access services like maybe a database connection + // 데이터베이스 연결과 같은 서비스 접근 $database = $this->config['database'] // ... } ``` -## AI Helper Wrappers +## AI 도우미 래퍼 -Runway에는 AI가 명령을 생성하기 쉽게 하는 몇 가지 도우미 래퍼가 있습니다. Symfony Console과 유사하게 `addOption`과 `addArgument`를 사용할 수 있습니다. AI 도구를 사용하여 명령을 생성하는 경우 유용합니다. +Runway에는 AI가 명령어를 생성하기 쉽게 하는 몇 가지 도우미 래퍼가 있습니다. Symfony Console과 유사하게 `addOption`과 `addArgument`를 사용할 수 있습니다. AI 도구를 사용하여 명령어를 생성하는 경우 유용합니다. ```php public function __construct(array $config) { - parent::__construct('make:example', 'Create an example for the documentation', $config); + parent::__construct('make:example', '문서화를 위한 예시 생성', $config); - // The mode argument is nullable and defaults to completely optional - $this->addOption('name', 'The name of the example', null); + // name 옵션은 null로 선택적이며 완전히 선택적입니다 + $this->addOption('name', '예시의 이름', null); } ``` \ No newline at end of file diff --git a/content/v3/ko/learn/ai.md b/content/v3/ko/learn/ai.md index 753028d0..a89ac70a 100644 --- a/content/v3/ko/learn/ai.md +++ b/content/v3/ko/learn/ai.md @@ -2,16 +2,16 @@ ## 개요 -Flight는 AI 기반 도구와 현대적인 개발자 워크플로우로 PHP 프로젝트를 쉽게 강화할 수 있게 해줍니다. LLM(대형 언어 모델) 제공자에 연결하는 내장 명령어와 프로젝트별 AI 코딩 지침을 생성하는 기능을 통해, Flight는 GitHub Copilot, Cursor, Windsurf와 같은 AI 어시스턴트에서 최대한의 이점을 얻도록 당신과 팀을 도와줍니다. +Flight는 AI 기반 도구와 현대적인 개발자 워크플로우를 통해 PHP 프로젝트를 쉽게 강화할 수 있게 해줍니다. LLM (Large Language Model) 제공자에 연결하고 프로젝트별 AI 코딩 지침을 생성하는 내장 명령어를 통해, Flight는 GitHub Copilot, Cursor, Windsurf, Antigravity (Gemini)와 같은 AI 어시스턴트로부터 최대한의 이점을 얻도록 도와줍니다. -## 이해하기 +## 이해 -AI 코딩 어시스턴트는 프로젝트의 맥락, 규칙, 목표를 이해할 때 가장 도움이 됩니다. Flight의 AI 도우미는 다음을 가능하게 합니다: -- 프로젝트를 인기 있는 LLM 제공자(OpenAI, Grok, Claude 등)에 연결 -- AI 도구를 위한 프로젝트별 지침을 생성하고 업데이트하여 모두가 일관되고 관련성 있는 도움을 받도록 함 -- 맥락 설명에 시간을 덜 들이고 팀을 일치시키며 생산성을 유지 +AI 코딩 어시스턴트는 프로젝트의 맥락, 규칙, 목표를 이해할 때 가장 유용합니다. Flight의 AI 도우미는 다음을 가능하게 합니다: +- 프로젝트를 인기 있는 LLM 제공자 (OpenAI, Grok, Claude 등)에 연결 +- AI 도구를 위한 프로젝트별 지침을 생성하고 업데이트하여 모든 사람이 일관되고 관련된 도움을 받도록 함 +- 맥락 설명에 소요되는 시간을 줄여 팀을 일치시키고 생산성을 유지 -이 기능들은 Flight 코어 CLI와 공식 [flightphp/skeleton](https://github.com/flightphp/skeleton) 시작 프로젝트에 내장되어 있습니다. +이 기능들은 Flight 코어 CLI와 공식 [flightphp/skeleton](https://github.com/flightphp/skeleton) 스타터 프로젝트에 내장되어 있습니다. ## 기본 사용법 @@ -23,12 +23,12 @@ AI 코딩 어시스턴트는 프로젝트의 맥락, 규칙, 목표를 이해할 php runway ai:init ``` -다음으로 안내됩니다: +다음에 대해 프롬프트가 표시됩니다: - 제공자 선택 (OpenAI, Grok, Claude 등) - API 키 입력 - 기본 URL 및 모델 이름 설정 -이로 인해 프로젝트 루트에 `.runway-creds.json` 파일이 생성되며 (`.gitignore`에 포함되도록 보장합니다). +이것은 향후 LLM 요청을 위한 필요한 자격 증명을 생성합니다. **예시:** ``` @@ -42,7 +42,7 @@ Credentials saved to .runway-creds.json ### 프로젝트별 AI 지침 생성 -`ai:generate-instructions` 명령어는 프로젝트에 맞춤형 AI 코딩 어시스턴트 지침을 생성하거나 업데이트하는 데 도움을 줍니다. +`ai:generate-instructions` 명령어는 프로젝트에 맞춤형 AI 코딩 어시스턴트를 위한 지침을 생성하거나 업데이트하는 데 도움을 줍니다. ```bash php runway ai:generate-instructions @@ -52,6 +52,7 @@ php runway ai:generate-instructions - `.github/copilot-instructions.md` (GitHub Copilot용) - `.cursor/rules/project-overview.mdc` (Cursor용) - `.windsurfrules` (Windsurf용) +- `.gemini/GEMINI.md` (Antigravity용) **예시:** ``` @@ -63,22 +64,22 @@ Is security an important element of this project? (y/n) y AI instructions updated successfully. ``` -이제 AI 도구는 프로젝트의 실제 요구사항에 기반한 더 스마트하고 관련성 있는 제안을 제공합니다. +이제 AI 도구는 프로젝트의 실제 요구사항에 기반한 더 스마트하고 관련된 제안을 제공합니다. ## 고급 사용법 -- 자격 증명 또는 지침 파일의 위치를 명령어 옵션을 사용하여 사용자 지정할 수 있습니다 (각 명령어의 `--help` 참조). -- AI 도우미는 OpenAI 호환 API를 지원하는 모든 LLM 제공자와 작동하도록 설계되었습니다. +- 명령어 옵션을 사용하여 자격 증명 또는 지침 파일의 위치를 사용자 지정할 수 있습니다 (각 명령어에 대해 `--help` 참조). +- AI 도우미는 OpenAI 호환 API를 지원하는 모든 LLM 제공자와 함께 작동하도록 설계되었습니다. - 프로젝트가 발전함에 따라 지침을 업데이트하려면 `ai:generate-instructions`를 다시 실행하고 프롬프트에 답변하세요. ## 관련 자료 -- [Flight Skeleton](https://github.com/flightphp/skeleton) – AI 통합이 포함된 공식 시작 프로젝트 -- [Runway CLI](/awesome-plugins/runway) – 이러한 명령어를 구동하는 CLI 도구에 대한 자세한 내용 +- [Flight Skeleton](https://github.com/flightphp/skeleton) – AI 통합이 포함된 공식 스타터 +- [Runway CLI](/awesome-plugins/runway) – 이러한 명령어를 구동하는 CLI 도구에 대해 자세히 ## 문제 해결 -- "Missing .runway-creds.json"이 보이면 먼저 `php runway ai:init`을 실행하세요. +- "Missing .runway-creds.json"이 표시되면 먼저 `php runway ai:init`을 실행하세요. - API 키가 유효하고 선택된 모델에 액세스할 수 있는지 확인하세요. - 지침이 업데이트되지 않으면 프로젝트 디렉토리의 파일 권한을 확인하세요. diff --git a/content/v3/lv/awesome-plugins/runway.md b/content/v3/lv/awesome-plugins/runway.md index fddae8dc..48a41370 100644 --- a/content/v3/lv/awesome-plugins/runway.md +++ b/content/v3/lv/awesome-plugins/runway.md @@ -1,6 +1,6 @@ -# Lidlaukums +# Runway -Lidlaukums ir CLI lietojumprogramma, kas palīdz pārvaldīt jūsu Flight lietojumprogrammas. Tā var ģenerēt kontrolierus, parādīt visas maršrutus un vairāk. Tā ir balstīta uz izcilo [adhocore/php-cli](https://github.com/adhocore/php-cli) bibliotēku. +Runway ir CLI lietojumprogramma, kas palīdz pārvaldīt jūsu Flight lietojumprogrammas. Tā var ģenerēt kontrolierus, parādīt visas maršrutus un vairāk. Tā ir balstīta uz izcilo [adhocore/php-cli](https://github.com/adhocore/php-cli) bibliotēku. Noklikšķiniet [šeit](https://github.com/flightphp/runway), lai skatītu kodu. @@ -14,7 +14,7 @@ composer require flightphp/runway ## Pamata konfigurācija -Pirmo reizi palaižot Lidlaukumu, tas mēģinās atrast `runway` konfigurāciju `app/config/config.php` caur `'runway'` atslēgu. +Pirmo reizi palaižot Runway, tā mēģinās atrast `runway` konfigurāciju `app/config/config.php` caur `'runway'` atslēgu. ```php **PIEZĪME** - Kopš **v1.2.0**, `.runway-config.json` ir atcelts. Lūdzu, migrējiet savu konfigurāciju uz `app/config/config.php`. Jūs varat to izdarīt viegli ar `php runway config:migrate` komandu. +> **PIEZĪME** - No **v1.2.0**, `.runway-config.json` ir novecojis. Lūdzu, migrējiet savu konfigurāciju uz `app/config/config.php`. Jūs varat to izdarīt viegli ar `php runway config:migrate` komandu. + + ### Projekta saknes noteikšana -Lidlaukums ir pietiekami gudrs, lai noteiktu jūsu projekta sakni, pat ja jūs to palaižat no apakšdirektorijas. Tas meklē indikatorus, piemēram, `composer.json`, `.git` vai `app/config/config.php`, lai noteiktu, kur ir projekta sakne. Tas nozīmē, ka jūs varat palaidīt Lidlaukuma komandas no jebkuras vietas jūsu projektā! +Runway ir pietiekami gudra, lai noteiktu jūsu projekta sakni, pat ja jūs to palaižat no apakšdirektorijas. Tā meklē indikatorus, piemēram, `composer.json`, `.git` vai `app/config/config.php`, lai noteiktu, kur ir projekta sakne. Tas nozīmē, ka jūs varat palaiž Runway komandas no jebkuras vietas savā projektā! -## Lietojums +## Lietošana -Lidlaukumam ir vairākas komandas, kuras jūs varat izmantot, lai pārvaldītu jūsu Flight lietojumprogrammu. Ir divi viegli veidi, kā izmantot Lidlaukumu. +Runway ir vairākas komandas, kuras jūs varat izmantot, lai pārvaldītu savu Flight lietojumprogrammu. Ir divi viegli veidi, kā izmantot Runway. -1. Ja jūs izmantojat skeletu projektu, jūs varat palaidīt `php runway [command]` no jūsu projekta saknes. -1. Ja jūs izmantojat Lidlaukumu kā paketi, kas instalēta caur composer, jūs varat palaidīt `vendor/bin/runway [command]` no jūsu projekta saknes. +1. Ja jūs izmantojat skeletu projektu, jūs varat palaiž `php runway [command]` no jūsu projekta saknes. +1. Ja jūs izmantojat Runway kā paketi, kas instalēta caur composer, jūs varat palaiž `vendor/bin/runway [command]` no jūsu projekta saknes. ### Komandu saraksts -Jūs varat skatīt visu pieejamo komandu sarakstu, palaižot `php runway` komandu. +Jūs varat skatīt sarakstu ar visām pieejamajām komandām, palaižot `php runway` komandu. ```bash php runway @@ -74,7 +76,7 @@ Vispirms pārliecinieties, ka esat instalējis [Active Record](/awesome-plugins/ php runway make:record users ``` -Ja, piemēram, jums ir `users` tabula ar šādu shēmu: `id`, `name`, `email`, `created_at`, `updated_at`, fails, līdzīgs sekojošajam, tiks izveidots `app/records/UserRecord.php` failā: +Ja, piemēram, jums ir `users` tabula ar šādu shēmu: `id`, `name`, `email`, `created_at`, `updated_at`, fails, līdzīgs šim, tiks izveidots `app/records/UserRecord.php` failā: ```php [ - // Šī ir jūsu lietojumprogrammas direktorijas atrašanās vieta + // Šī ir vieta, kur atrodas jūsu lietojumprogrammas direktorija 'app_root' => 'app/', // Šī ir direktorija, kur atrodas jūsu saknes indeksa fails @@ -231,9 +233,9 @@ return [ '/var/www/another-project' ], - // Bāzes ceļi, visticamāk, nav jākonfigurē, bet tas ir šeit, ja vēlaties + // Bāzes ceļi visticamāk nav jākonfigurē, bet tas ir šeit, ja vēlaties 'base_paths' => [ - '/includes/libs/vendor', // ja jums ir patiešām unikāls ceļš uz jūsu vendor direktoriju vai kaut ko + '/includes/libs/vendor', // ja jums ir patiesi unikāls ceļš uz jūsu vendor direktoriju vai kaut ko ], // Galīgie ceļi ir atrašanās vietas projektā, kur meklēt komandu failus @@ -242,7 +244,7 @@ return [ 'app/module/admin/commands', ], - // Ja vēlaties pievienot pilnu ceļu, dariet to (absolūts vai relatīvs pret projektu sakni) + // Ja vēlaties tikai pievienot pilnu ceļu, dariet to (absolūts vai relatīvs pret projektu sakni) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -252,19 +254,19 @@ return [ ]; ``` -### Konfigurācijas piekļuve +### Piekļuve konfigurācijai -Ja jums vajadzīga efektīva konfigurācijas vērtību piekļuve, jūs varat piekļūt tām caur `__construct` metodi vai `app()` metodi. Ir arī svarīgi atzīmēt, ka, ja jums ir `app/config/services.php` fails, šie servisi būs pieejami jūsu komandai. +Ja nepieciešams efektīvi piekļūt konfigurācijas vērtībām, jūs varat piekļūt tām caur `__construct` metodi vai `app()` metodi. Ir arī svarīgi atzīmēt, ka, ja jums ir `app/config/services.php` fails, šie servisi būs pieejami jūsu komandai. ```php public function execute() { $io = $this->app()->io(); - // Piekļūt konfigurācijai + // Piekļuve konfigurācijai $app_root = $this->config['runway']['app_root']; - // Piekļūt servisiem, piemēram, datubāzes savienojumam + // Piekļuve servisiem, piemēram, datubāzes savienojumam $database = $this->config['database'] // ... @@ -273,14 +275,14 @@ public function execute() ## AI palīglīdzekļu apvalki -Lidlaukumam ir daži palīglīdzekļu apvalki, kas atvieglo AI komandu ģenerēšanu. Jūs varat izmantot `addOption` un `addArgument` veidā, kas šķiet līdzīgs Symfony Console. Tas ir noderīgi, ja izmantojat AI rīkus, lai ģenerētu savas komandas. +Runway ir daži palīglīdzekļu apvalki, kas padara vieglāku AI ģenerēt komandas. Jūs varat izmantot `addOption` un `addArgument` veidā, kas šķiet līdzīgs Symfony Console. Tas ir noderīgi, ja izmantojat AI rīkus, lai ģenerētu savas komandas. ```php public function __construct(array $config) { parent::__construct('make:example', 'Izveidot piemēru dokumentācijai', $config); - // Name arguments ir null un pēc noklusējuma pilnībā izvēles + // Name arguments ir nullable un pēc noklusējuma pilnībā opcionāls $this->addOption('name', 'Piemēra nosaukums', null); } ``` \ No newline at end of file diff --git a/content/v3/lv/learn/ai.md b/content/v3/lv/learn/ai.md index c48063b5..a2df6eb1 100644 --- a/content/v3/lv/learn/ai.md +++ b/content/v3/lv/learn/ai.md @@ -2,18 +2,18 @@ ## Pārskats -Flight padara viegli uzlabot jūsu PHP projektus ar AI vadītiem rīkiem un mūsdienīgiem izstrādātāju darba plūsmu. Ar iebūvētiem komandām savienojumiem ar LLM (Large Language Model) sniedzējiem un ģenerēšanu projektu specifiskām AI kodēšanas instrukcijām, Flight palīdz jums un jūsu komandai iegūt maksimālo labumu no AI asistentiem, piemēram, GitHub Copilot, Cursor un Windsurf. +Flight padara viegli uzlabot jūsu PHP projektus ar AI vadītiem rīkiem un moderniem izstrādātāju darba plūsmu. Ar iebūvētiem komandām savienojumiem ar LLM (Large Language Model) sniedzējiem un ģenerēšanu projektu specifiskām AI kodēšanas instrukcijām, Flight palīdz jums un jūsu komandai iegūt maksimālu labumu no AI asistentiem, piemēram, GitHub Copilot, Cursor, Windsurf un Antigravity (Gemini). -## Izpratne +## Saprašana -AI kodēšanas asistenti ir visnoderīgākie, kad viņi saprot jūsu projekta kontekstu, konvencijas un mērķus. Flight AI palīgi ļauj jums: -- Savienot savu projektu ar populāriem LLM sniedzējiem (OpenAI, Grok, Claude utt.) +AI kodēšanas asistenti ir visnoderīgākie, kad tie saprot jūsu projekta kontekstu, konvencijas un mērķus. Flight AI palīgi ļauj jums: +- Savienot jūsu projektu ar populāriem LLM sniedzējiem (OpenAI, Grok, Claude utt.) - Ģenerēt un atjaunināt projektu specifiskas instrukcijas AI rīkiem, lai visi saņemtu konsekventu, atbilstošu palīdzību -- Turēt jūsu komandu saskaņotu un produktīvu, ar mazāku laiku, kas pavadīts konteksta skaidrošanā +- Turēt jūsu komandu saskaņotu un produktīvu, ar mazāk laika iztērētu konteksta skaidrošanai -Šīs funkcijas ir iebūvētas Flight kodolā CLI un oficiālajā [flightphp/skeleton](https://github.com/flightphp/skeleton) starter projektā. +Šīs funkcijas ir iebūvētas Flight kodola CLI un oficiālajā [flightphp/skeleton](https://github.com/flightphp/skeleton) sākuma projektā. -## Pamata lietošana +## Pamata izmantošana ### LLM akreditīvu iestatīšana @@ -23,62 +23,63 @@ AI kodēšanas asistenti ir visnoderīgākie, kad viņi saprot jūsu projekta ko php runway ai:init ``` -Jums tiks uzdots: -- Izvēlēties savu sniedzēju (OpenAI, Grok, Claude utt.) -- Ievadīt savu API atslēgu +Jums tiks prasīts: +- Izvēlēties jūsu sniedzēju (OpenAI, Grok, Claude utt.) +- Ievadīt jūsu API atslēgu - Iestatīt bāzes URL un modeļa nosaukumu -Tas izveido `.runway-creds.json` failu jūsu projekta saknē (un nodrošina, ka tas ir jūsu `.gitignore`). +Tas izveido nepieciešamos akreditīvus, lai jūs varētu veikt turpmākus LLM pieprasījumus. **Piemērs:** ``` -Welcome to AI Init! -Which LLM API do you want to use? [1] openai, [2] grok, [3] claude: 1 -Enter the base URL for the LLM API [https://api.openai.com]: -Enter your API key for openai: sk-... -Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: -Credentials saved to .runway-creds.json +Laipni lūgti AI Init! +Kuru LLM API jūs vēlaties izmantot? [1] openai, [2] grok, [3] claude: 1 +Ievadiet bāzes URL LLM API [https://api.openai.com]: +Ievadiet jūsu API atslēgu openai: sk-... +Ievadiet modeļa nosaukumu, kuru vēlaties izmantot (piem. gpt-4, claude-3-opus utt.) [gpt-4o]: +Akreditīvi saglabāti .runway-creds.json ``` -### Ģenerēšana projektu specifiskām AI instrukcijām +### Projekta specifisku AI instrukciju ģenerēšana -`ai:generate-instructions` komanda palīdz jums izveidot vai atjaunināt instrukcijas AI kodēšanas asistentiem, pielāgotas jūsu projektam. +`ai:generate-instructions` komanda palīdz izveidot vai atjaunināt instrukcijas AI kodēšanas asistentiem, pielāgotas jūsu projektam. ```bash php runway ai:generate-instructions ``` -Jūs atbildēsiet uz dažiem jautājumiem par jūsu projektu (apraksts, datubāze, veidnes, drošība, komandas lielums utt.). Flight izmanto jūsu LLM sniedzēju, lai ģenerētu instrukcijas, tad ieraksta tās: -- `.github/copilot-instructions.md` (for GitHub Copilot) -- `.cursor/rules/project-overview.mdc` (for Cursor) -- `.windsurfrules` (for Windsurf) +Jūs atbildēsiet uz dažiem jautājumiem par jūsu projektu (apraksts, datubāze, veidnes, drošība, komandas lielums utt.). Flight izmanto jūsu LLM sniedzēju, lai ģenerētu instrukcijas, pēc tam ieraksta tās: +- `.github/copilot-instructions.md` (GitHub Copilot) +- `.cursor/rules/project-overview.mdc` (Cursor) +- `.windsurfrules` (Windsurf) +- `.gemini/GEMINI.md` (Antigravity) **Piemērs:** ``` -Please describe what your project is for? My awesome API -What database are you planning on using? MySQL -What HTML templating engine will you plan on using (if any)? latte -Is security an important element of this project? (y/n) y +Lūdzu, aprakstiet, kam ir paredzēts jūsu projekts? Mans lieliskais API +Kuru datubāzi jūs plānojat izmantot? MySQL +Kuru HTML veidņu dzinēju jūs plānojat izmantot (ja kādu)? latte +Vai drošība ir svarīgs elements šim projektam? (y/n) y ... -AI instructions updated successfully. +AI instrukcijas atjauninātas veiksmīgi. ``` Tagad jūsu AI rīki sniegs gudrākus, atbilstošākus ieteikumus, balstītus uz jūsu projekta reālajām vajadzībām. -## Padziļinātā lietošana +## Uzlabota izmantošana -- Jūs varat pielāgot jūsu akreditīvu vai instrukciju failu atrašanās vietu, izmantojot komandas opcijas (skatiet `--help` katrai komandai). +- Jūs varat pielāgot jūsu akreditīvu vai instrukciju failu atrašanās vietu, izmantojot komandas opcijas (skat. `--help` katrai komandai). - AI palīgi ir paredzēti darbam ar jebkuru LLM sniedzēju, kas atbalsta OpenAI saderīgās API. -- Ja vēlaties atjaunināt jūsu instrukcijas, kad jūsu projekts attīstās, tikai palaidiet atkārtoti `ai:generate-instructions` un atbildiet uz uzvednēm vēlreiz. +- Ja vēlaties atjaunināt jūsu instrukcijas, kad jūsu projekts attīstās, vienkārši palaidiet atkārtoti `ai:generate-instructions` un atbildiet uz uzvednēm vēlreiz. ## Skatīt arī -- [Flight Skeleton](https://github.com/flightphp/skeleton) – Oficiālais starter ar AI integrāciju +- [Flight Skeleton](https://github.com/flightphp/skeleton) – Oficiālais sākuma projekts ar AI integrāciju - [Runway CLI](/awesome-plugins/runway) – Vairāk par CLI rīku, kas nodrošina šīs komandas ## Traucējummeklēšana -- Ja jūs redzat "Missing .runway-creds.json", palaidiet `php runway ai:init` vispirms. +- Ja redzat "Missing .runway-creds.json", vispirms palaidiet `php runway ai:init`. - Pārliecinieties, ka jūsu API atslēga ir derīga un tai ir piekļuve izvēlētajam modelim. - Ja instrukcijas neatjaunojas, pārbaudiet failu atļaujas jūsu projektu direktorijā. diff --git a/content/v3/pt/awesome-plugins/runway.md b/content/v3/pt/awesome-plugins/runway.md index 6384ad67..de0a5b9e 100644 --- a/content/v3/pt/awesome-plugins/runway.md +++ b/content/v3/pt/awesome-plugins/runway.md @@ -1,6 +1,6 @@ # Runway -Runway é um aplicativo CLI que ajuda você a gerenciar suas aplicações Flight. Ele pode gerar controladores, exibir todas as rotas e mais. É baseado na excelente biblioteca [adhocore/php-cli](https://github.com/adhocore/php-cli). +Runway é uma aplicação CLI que ajuda você a gerenciar suas aplicações Flight. Ela pode gerar controladores, exibir todas as rotas e mais. É baseada na excelente biblioteca [adhocore/php-cli](https://github.com/adhocore/php-cli). Clique [aqui](https://github.com/flightphp/runway) para visualizar o código. @@ -27,18 +27,18 @@ return [ ]; ``` -> **NOTA** - A partir da **v1.2.0**, o `.runway-config.json` está depreciado. Por favor, migre sua configuração para `app/config/config.php`. Você pode fazer isso facilmente com o comando `php runway config:migrate`. +> **NOTA** - A partir de **v1.2.0**, `.runway-config.json` está depreciado. Por favor, migre sua configuração para `app/config/config.php`. Você pode fazer isso facilmente com o comando `php runway config:migrate`. ### Detecção da Raiz do Projeto -O Runway é inteligente o suficiente para detectar a raiz do seu projeto, mesmo se você o executar de um subdiretório. Ele procura por indicadores como `composer.json`, `.git` ou `app/config/config.php` para determinar onde está a raiz do projeto. Isso significa que você pode executar comandos do Runway de qualquer lugar no seu projeto! +Runway é inteligente o suficiente para detectar a raiz do seu projeto, mesmo se você o executar de um subdiretório. Ele procura por indicadores como `composer.json`, `.git` ou `app/config/config.php` para determinar onde está a raiz do projeto. Isso significa que você pode executar comandos do Runway de qualquer lugar no seu projeto! ## Uso -O Runway tem vários comandos que você pode usar para gerenciar sua aplicação Flight. Há duas maneiras fáceis de usar o Runway. +Runway tem uma série de comandos que você pode usar para gerenciar sua aplicação Flight. Há duas maneiras fáceis de usar o Runway. -1. Se você estiver usando o projeto esqueleto, você pode executar `php runway [command]` da raiz do seu projeto. -1. Se você estiver usando o Runway como um pacote instalado via composer, você pode executar `vendor/bin/runway [command]` da raiz do seu projeto. +1. Se você estiver usando o projeto skeleton, você pode executar `php runway [command]` da raiz do seu projeto. +1. Se você estiver usando Runway como um pacote instalado via composer, você pode executar `vendor/bin/runway [command]` da raiz do seu projeto. ### Lista de Comandos @@ -68,13 +68,13 @@ php runway make:controller MyController ### Gerar um Modelo Active Record -Primeiro, certifique-se de ter instalado o plugin [Active Record](/awesome-plugins/active-record). Com base na configuração em `runway.app_root`, o local gerará um registro para você no diretório `app/records/`. +Primeiro, certifique-se de que você instalou o plugin [Active Record](/awesome-plugins/active-record). Com base na configuração em `runway.app_root`, o local gerará um registro para você no diretório `app/records/`. ```bash php runway make:record users ``` -Por exemplo, se você tiver a tabela `users` com o seguinte esquema: `id`, `name`, `email`, `created_at`, `updated_at`, um arquivo semelhante ao seguinte será criado no arquivo `app/records/UserRecord.php`: +Por exemplo, se você tiver a tabela `users` com o seguinte esquema: `id`, `name`, `email`, `created_at`, `updated_at`, um arquivo similar ao seguinte será criado no arquivo `app/records/UserRecord.php`: ```php 'app/', - // Este é o diretório onde o arquivo de índice raiz está localizado + // Este é o diretório onde o seu arquivo index raiz está localizado 'index_root' => 'public/', // Estes são os caminhos para as raízes de outros projetos @@ -236,13 +236,13 @@ return [ '/includes/libs/vendor', // se você tiver um caminho realmente único para o diretório vendor ou algo assim ], - // Caminhos finais são locais dentro de um projeto para procurar arquivos de comandos + // Caminhos finais são locais dentro de um projeto para procurar pelos arquivos de comando 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // Se você quiser adicionar o caminho completo, vá em frente (absoluto ou relativo à raiz do projeto) + // Se você quiser apenas adicionar o caminho completo, vá em frente (absoluto ou relativo à raiz do projeto) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -254,7 +254,7 @@ return [ ### Acessando a Configuração -Se você precisar acessar os valores de configuração de forma eficaz, pode acessá-los através do método `__construct` ou do método `app()`. Também é importante notar que, se você tiver um arquivo `app/config/services.php`, esses serviços também estarão disponíveis para o seu comando. +Se você precisar acessar os valores de configuração de forma eficaz, você pode acessá-los através do método `__construct` ou do método `app()`. Também é importante notar que, se você tiver um arquivo `app/config/services.php`, esses serviços também estarão disponíveis para o seu comando. ```php public function execute() @@ -264,23 +264,23 @@ public function execute() // Acessar configuração $app_root = $this->config['runway']['app_root']; - // Acessar serviços como talvez uma conexão de banco de dados + // Acessar serviços como talvez uma conexão com o banco de dados $database = $this->config['database'] // ... } ``` -## Wrappers de Auxílio de IA +## Wrappers de Auxílio para IA -O Runway tem alguns wrappers de auxílio que facilitam para a IA gerar comandos. Você pode usar `addOption` e `addArgument` de uma maneira que se sente semelhante ao Symfony Console. Isso é útil se você estiver usando ferramentas de IA para gerar seus comandos. +Runway tem alguns wrappers de auxílio que facilitam para a IA gerar comandos. Você pode usar `addOption` e `addArgument` de uma maneira que se sente similar ao Symfony Console. Isso é útil se você estiver usando ferramentas de IA para gerar seus comandos. ```php public function __construct(array $config) { parent::__construct('make:example', 'Criar um exemplo para a documentação', $config); - // O argumento mode é nulo e padrão para completamente opcional + // O argumento mode é anulável e padrão para completamente opcional $this->addOption('name', 'O nome do exemplo', null); } ``` \ No newline at end of file diff --git a/content/v3/pt/learn/ai.md b/content/v3/pt/learn/ai.md index 717ab1de..1d8c22c8 100644 --- a/content/v3/pt/learn/ai.md +++ b/content/v3/pt/learn/ai.md @@ -2,11 +2,11 @@ ## Visão Geral -Flight facilita o superpoder de seus projetos PHP com ferramentas alimentadas por IA e fluxos de trabalho modernos para desenvolvedores. Com comandos integrados para conectar a provedores de LLM (Large Language Model) e gerar instruções de codificação específicas do projeto alimentadas por IA, Flight ajuda você e sua equipe a tirar o máximo de assistentes de IA como GitHub Copilot, Cursor e Windsurf. +Flight facilita o superpoder de seus projetos PHP com ferramentas alimentadas por IA e fluxos de trabalho modernos para desenvolvedores. Com comandos integrados para conectar a provedores de LLM (Large Language Model) e gerar instruções de codificação específicas do projeto baseadas em IA, Flight ajuda você e sua equipe a tirar o máximo proveito de assistentes de IA como GitHub Copilot, Cursor, Windsurf e Antigravity (Gemini). ## Entendendo -Assistentes de codificação de IA são mais úteis quando entendem o contexto, convenções e objetivos do seu projeto. Os ajudantes de IA do Flight permitem que você: +Assistentes de codificação de IA são mais úteis quando entendem o contexto, as convenções e os objetivos do seu projeto. Os ajudantes de IA do Flight permitem que você: - Conecte seu projeto a provedores populares de LLM (OpenAI, Grok, Claude, etc.) - Gere e atualize instruções específicas do projeto para ferramentas de IA, para que todos recebam ajuda consistente e relevante - Mantenha sua equipe alinhada e produtiva, com menos tempo gasto explicando o contexto @@ -17,7 +17,7 @@ Esses recursos estão integrados ao CLI principal do Flight e ao projeto inicial ### Configurando Credenciais de LLM -O comando `ai:init` o guia na conexão do seu projeto a um provedor de LLM. +O comando `ai:init` o guia através da conexão do seu projeto a um provedor de LLM. ```bash php runway ai:init @@ -28,19 +28,19 @@ Você será solicitado a: - Inserir sua chave de API - Definir a URL base e o nome do modelo -Isso cria um arquivo `.runway-creds.json` na raiz do seu projeto (e garante que ele esteja no seu `.gitignore`). +Isso cria as credenciais necessárias para que você faça solicitações futuras de LLM. **Exemplo:** ``` Bem-vindo ao AI Init! Qual API de LLM você deseja usar? [1] openai, [2] grok, [3] claude: 1 -Insira a URL base para a API de LLM [https://api.openai.com]: -Insira sua chave de API para openai: sk-... -Insira o nome do modelo que você deseja usar (ex. gpt-4, claude-3-opus, etc) [gpt-4o]: +Digite a URL base para a API de LLM [https://api.openai.com]: +Digite sua chave de API para openai: sk-... +Digite o nome do modelo que você deseja usar (ex. gpt-4, claude-3-opus, etc) [gpt-4o]: Credenciais salvas em .runway-creds.json ``` -### Gerando Instruções Específicas do Projeto para IA +### Gerando Instruções de IA Específicas do Projeto O comando `ai:generate-instructions` ajuda você a criar ou atualizar instruções para assistentes de codificação de IA, adaptadas ao seu projeto. @@ -48,17 +48,18 @@ O comando `ai:generate-instructions` ajuda você a criar ou atualizar instruçõ php runway ai:generate-instructions ``` -Você responderá a algumas perguntas sobre seu projeto (descrição, banco de dados, templating, segurança, tamanho da equipe, etc.). Flight usa seu provedor de LLM para gerar instruções, depois as escreve em: +Você responderá a algumas perguntas sobre seu projeto (descrição, banco de dados, templating, segurança, tamanho da equipe, etc.). Flight usa seu provedor de LLM para gerar instruções e, em seguida, as escreve em: - `.github/copilot-instructions.md` (para GitHub Copilot) - `.cursor/rules/project-overview.mdc` (para Cursor) - `.windsurfrules` (para Windsurf) +- `.gemini/GEMINI.md` (para Antigravity) **Exemplo:** ``` Por favor, descreva para que serve seu projeto? Minha API incrível Qual banco de dados você planeja usar? MySQL Qual engine de templating HTML você planeja usar (se houver)? latte -A segurança é um elemento importante deste projeto? (y/n) y +A segurança é um elemento importante deste projeto? (s/n) s ... Instruções de IA atualizadas com sucesso. ``` diff --git a/content/v3/ru/awesome-plugins/runway.md b/content/v3/ru/awesome-plugins/runway.md index 6d3501a5..5919708e 100644 --- a/content/v3/ru/awesome-plugins/runway.md +++ b/content/v3/ru/awesome-plugins/runway.md @@ -14,7 +14,7 @@ composer require flightphp/runway ## Базовая конфигурация -Впервые запустив Runway, оно попытается найти конфигурацию `runway` в `app/config/config.php` через ключ `'runway'`. +В первый раз при запуске Runway попытается найти конфигурацию `runway` в `app/config/config.php` через ключ `'runway'`. ```php **ПРИМЕЧАНИЕ** - Начиная с **v1.2.0**, `.runway-config.json` устарел. Пожалуйста, мигрируйте вашу конфигурацию в `app/config/config.php`. Вы можете сделать это легко с помощью команды `php runway config:migrate`. + + ### Обнаружение корня проекта -Runway достаточно умён, чтобы обнаружить корень вашего проекта, даже если вы запускаете его из поддиректории. Оно ищет индикаторы, такие как `composer.json`, `.git` или `app/config/config.php`, чтобы определить, где находится корень проекта. Это значит, что вы можете запускать команды Runway откуда угодно в вашем проекте! +Runway достаточно умён, чтобы обнаружить корень вашего проекта, даже если вы запускаете его из поддиректории. Он ищет индикаторы, такие как `composer.json`, `.git` или `app/config/config.php`, чтобы определить, где находится корень проекта. Это значит, что вы можете запускать команды Runway откуда угодно в вашем проекте! ## Использование @@ -60,7 +62,7 @@ php runway routes --help ### Генерация контроллера -На основе конфигурации в `runway.app_root`, место будет генерировать контроллер для вас в директории `app/controllers/`. +На основе конфигурации в `runway.app_root` будет сгенерирован контроллер для вас в директории `app/controllers/`. ```bash php runway make:controller MyController @@ -68,13 +70,13 @@ php runway make:controller MyController ### Генерация модели Active Record -Сначала убедитесь, что вы установили плагин [Active Record](/awesome-plugins/active-record). На основе конфигурации в `runway.app_root`, место будет генерировать запись для вас в директории `app/records/`. +Сначала убедитесь, что вы установили плагин [Active Record](/awesome-plugins/active-record). На основе конфигурации в `runway.app_root` будет сгенерирована запись для вас в директории `app/records/`. ```bash php runway make:record users ``` -Если, например, у вас есть таблица `users` со следующей схемой: `id`, `name`, `email`, `created_at`, `updated_at`, файл, похожий на следующий, будет создан в файле `app/records/UserRecord.php`: +Если, например, у вас есть таблица `users` со следующей схемой: `id`, `name`, `email`, `created_at`, `updated_at`, будет создан файл, похожий на следующий, в файле `app/records/UserRecord.php`: ```php $config Config from app/config/config.php + * @param array $config Конфигурация из app/config/config.php */ public function __construct(array $config) { - parent::__construct('make:example', 'Create an example for the documentation', $config); - $this->argument('', 'The name of the funny gif'); + parent::__construct('make:example', 'Создать пример для документации', $config); + $this->argument('', 'Имя забавного GIF'); } /** - * Executes the function + * Выполняет функцию * * @return void */ @@ -169,11 +171,11 @@ class ExampleCommand extends AbstractBaseCommand { $io = $this->app()->io(); - $io->info('Creating example...'); + $io->info('Создание примера...'); - // Do something here + // Сделайте что-то здесь - $io->ok('Example created!'); + $io->ok('Пример создан!'); } } ``` @@ -216,33 +218,33 @@ php runway config:get app_root [ - // This is where your application directory is located + // Здесь находится директория вашего приложения 'app_root' => 'app/', - // This is the directory where your root index file is located + // Это директория, где находится ваш корневой индексный файл 'index_root' => 'public/', - // These are the paths to the roots of other projects + // Это пути к корням других проектов 'root_paths' => [ '/home/user/different-project', '/var/www/another-project' ], - // Base paths most likely don't need to be configured, but it's here if you want it + // Базовые пути, скорее всего, не нужно настраивать, но они здесь, если вы хотите 'base_paths' => [ - '/includes/libs/vendor', // if you have a really unique path for your vendor directory or something + '/includes/libs/vendor', // если у вас действительно уникальный путь для директории vendor или чего-то подобного ], - // Final paths are locations within a project to search for the command files + // Финальные пути — это места внутри проекта для поиска файлов команд 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // If you want to just add the full path, go right ahead (absolute or relative to project root) + // Если вы хотите просто добавить полный путь, пожалуйста (абсолютный или относительный к корню проекта) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -254,33 +256,33 @@ return [ ### Доступ к конфигурации -Если вам нужно эффективно получить доступ к значениям конфигурации, вы можете получить к ним доступ через метод `__construct` или метод `app()`. Также важно отметить, что если у вас есть файл `app/config/services.php`, эти сервисы также будут доступны для вашей команды. +Если вам нужно эффективно получить доступ к значениям конфигурации, вы можете обращаться к ним через метод `__construct` или метод `app()`. Также важно отметить, что если у вас есть файл `app/config/services.php`, эти сервисы также будут доступны для вашей команды. ```php public function execute() { $io = $this->app()->io(); - // Access configuration + // Доступ к конфигурации $app_root = $this->config['runway']['app_root']; - // Access services like maybe a database connection + // Доступ к сервисам, например, соединению с базой данных $database = $this->config['database'] // ... } ``` -## Обёртки помощников ИИ +## Обертки помощников ИИ -Runway имеет некоторые обёртки помощников, которые облегчают генерацию команд ИИ. Вы можете использовать `addOption` и `addArgument` таким образом, который похож на Symfony Console. Это полезно, если вы используете инструменты ИИ для генерации ваших команд. +Runway имеет некоторые обертки помощников, которые облегчают генерацию команд ИИ. Вы можете использовать `addOption` и `addArgument` таким образом, который похож на Symfony Console. Это полезно, если вы используете инструменты ИИ для генерации ваших команд. ```php public function __construct(array $config) { - parent::__construct('make:example', 'Create an example for the documentation', $config); + parent::__construct('make:example', 'Создать пример для документации', $config); - // The mode argument is nullable and defaults to completely optional - $this->addOption('name', 'The name of the example', null); + // Аргумент mode является nullable и по умолчанию полностью необязательным + $this->addOption('name', 'Имя примера', null); } ``` \ No newline at end of file diff --git a/content/v3/ru/learn/ai.md b/content/v3/ru/learn/ai.md index c4c34042..5284c983 100644 --- a/content/v3/ru/learn/ai.md +++ b/content/v3/ru/learn/ai.md @@ -2,11 +2,11 @@ ## Обзор -Flight упрощает суперзарядку ваших PHP-проектов с помощью инструментов на базе ИИ и современных рабочих процессов разработчика. С встроенными командами для подключения к провайдерам LLM (Large Language Model) и генерации специфических для проекта инструкций по кодированию с ИИ, Flight помогает вам и вашей команде извлекать максимум из ИИ-ассистентов, таких как GitHub Copilot, Cursor и Windsurf. +Flight упрощает суперзарядку ваших PHP-проектов с помощью инструментов на базе ИИ и современных рабочих процессов разработчика. С встроенными командами для подключения к провайдерам LLM (Large Language Model) и генерации специфических для проекта инструкций по кодированию с ИИ, Flight помогает вам и вашей команде извлечь максимум из ИИ-помощников, таких как GitHub Copilot, Cursor, Windsurf и Antigravity (Gemini). ## Понимание -ИИ-ассистенты для кодирования наиболее полезны, когда они понимают контекст, конвенции и цели вашего проекта. ИИ-помощники Flight позволяют вам: +ИИ-помощники по кодированию наиболее полезны, когда они понимают контекст, конвенции и цели вашего проекта. ИИ-помощники Flight позволяют вам: - Подключить ваш проект к популярным провайдерам LLM (OpenAI, Grok, Claude и т.д.) - Генерировать и обновлять специфические для проекта инструкции для ИИ-инструментов, чтобы все получали последовательную, релевантную помощь - Сохранять вашу команду в согласованности и продуктивности, тратя меньше времени на объяснение контекста @@ -28,7 +28,7 @@ php runway ai:init - Ввести ваш API-ключ - Установить базовый URL и имя модели -Это создаст файл `.runway-creds.json` в корне вашего проекта (и убедится, что он добавлен в ваш `.gitignore`). +Это создаст необходимые учетные данные для будущих запросов к LLM. **Пример:** ``` @@ -42,7 +42,7 @@ Credentials saved to .runway-creds.json ### Генерация специфических для проекта инструкций ИИ -Команда `ai:generate-instructions` помогает создать или обновить инструкции для ИИ-ассистентов кодирования, адаптированные к вашему проекту. +Команда `ai:generate-instructions` помогает создать или обновить инструкции для ИИ-помощников по кодированию, адаптированные к вашему проекту. ```bash php runway ai:generate-instructions @@ -52,6 +52,7 @@ php runway ai:generate-instructions - `.github/copilot-instructions.md` (для GitHub Copilot) - `.cursor/rules/project-overview.mdc` (для Cursor) - `.windsurfrules` (для Windsurf) +- `.gemini/GEMINI.md` (для Antigravity) **Пример:** ``` @@ -74,7 +75,7 @@ AI instructions updated successfully. ## См. также - [Flight Skeleton](https://github.com/flightphp/skeleton) – Официальный стартер с интеграцией ИИ -- [Runway CLI](/awesome-plugins/runway) – Подробнее о CLI-инструменте, обеспечивающем эти команды +- [Runway CLI](/awesome-plugins/runway) – Подробнее о CLI-инструменте, питающем эти команды ## Устранение неисправностей diff --git a/content/v3/uk/awesome-plugins/runway.md b/content/v3/uk/awesome-plugins/runway.md index 08879af2..e971ca2c 100644 --- a/content/v3/uk/awesome-plugins/runway.md +++ b/content/v3/uk/awesome-plugins/runway.md @@ -1,6 +1,6 @@ -# Паска +# Runway -Паска — це CLI-додаток, який допомагає керувати вашими додатками Flight. Він може генерувати контролери, відображати всі маршрути та багато іншого. Він базується на чудовій бібліотеці [adhocore/php-cli](https://github.com/adhocore/php-cli). +Runway — це додаток командного рядка (CLI), який допомагає керувати вашими додатками Flight. Він може генерувати контролери, відображати всі маршрути та багато іншого. Він базується на чудовій бібліотеці [adhocore/php-cli](https://github.com/adhocore/php-cli). Натисніть [тут](https://github.com/flightphp/runway), щоб переглянути код. @@ -12,9 +12,9 @@ composer require flightphp/runway ``` -## Базова конфігурація +## Базова Конфігурація -Вперше, коли ви запустите Паска, він спробує знайти конфігурацію `runway` у `app/config/config.php` через ключ `'runway'`. +Під час першого запуску Runway він спробує знайти конфігурацію `runway` у `app/config/config.php` через ключ `'runway'`. ```php **ПРИМІТКА** - Починаючи з **v1.2.0**, `.runway-config.json` є застарілим. Будь ласка, мігруйте вашу конфігурацію до `app/config/config.php`. Ви можете зробити це легко за допомогою команди `php runway config:migrate`. -### Виявлення кореня проекту -Паска достатньо розумний, щоб виявити корінь вашого проекту, навіть якщо ви запускаєте його з підкаталогу. Він шукає індикатори, такі як `composer.json`, `.git` або `app/config/config.php`, щоб визначити, де знаходиться корінь проекту. Це означає, що ви можете запускати команди Паска з будь-якого місця у вашому проекті! + +### Виявлення Кореня Проекту + +Runway достатньо розумний, щоб виявити корінь вашого проекту, навіть якщо ви запускаєте його з підкаталогу. Він шукає індикатори, такі як `composer.json`, `.git` або `app/config/config.php`, щоб визначити, де знаходиться корінь проекту. Це означає, що ви можете запускати команди Runway з будь-якого місця у вашому проекті! ## Використання -Паска має низку команд, які ви можете використовувати для керування вашим додатком Flight. Є два простих способи використовувати Паска. +Runway має низку команд, які ви можете використовувати для керування вашим додатком Flight. Є два простих способи використовувати Runway. 1. Якщо ви використовуєте скелетний проект, ви можете запустити `php runway [command]` з кореня вашого проекту. -1. Якщо ви використовуєте Паска як пакет, встановлений через composer, ви можете запустити `vendor/bin/runway [command]` з кореня вашого проекту. +1. Якщо ви використовуєте Runway як пакет, встановлений через composer, ви можете запустити `vendor/bin/runway [command]` з кореня вашого проекту. -### Список команд +### Список Команд Ви можете переглянути список усіх доступних команд, запустивши команду `php runway`. @@ -48,7 +50,7 @@ return [ php runway ``` -### Довідка по команді +### Довідка по Командах Для будь-якої команди ви можете передати прапорець `--help`, щоб отримати більше інформації про те, як використовувати команду. @@ -58,23 +60,23 @@ php runway routes --help Ось кілька прикладів: -### Генерація контролера +### Генерація Контролера -На основі конфігурації в `runway.app_root`, локація згенерує для вас контролер у директорії `app/controllers/`. +На основі конфігурації в `runway.app_root`, локація згенерує контролер для вас у директорії `app/controllers/`. ```bash php runway make:controller MyController ``` -### Генерація моделі Active Record +### Генерація Моделі Active Record -Спочатку переконайтеся, що ви встановили плагін [Active Record](/awesome-plugins/active-record). На основі конфігурації в `runway.app_root`, локація згенерує для вас запис у директорії `app/records/`. +Спочатку переконайтеся, що ви встановили плагін [Active Record](/awesome-plugins/active-record). На основі конфігурації в `runway.app_root`, локація згенерує запис для вас у директорії `app/records/`. ```bash php runway make:record users ``` -Наприклад, якщо у вас є таблиця `users` зі схемою: `id`, `name`, `email`, `created_at`, `updated_at`, буде створено файл, подібний до наступного, у файлі `app/records/UserRecord.php`: +Наприклад, якщо у вас є таблиця `users` з такою схемою: `id`, `name`, `email`, `created_at`, `updated_at`, файл, подібний до наступного, буде створено у файлі `app/records/UserRecord.php`: ```php Date: Mon, 19 Jan 2026 07:13:34 -0700 Subject: [PATCH 35/36] added more important reasons on why to choose flight --- composer.lock | 39 +++++---- content/v3/de/about.md | 60 ++++++++------ content/v3/de/awesome-plugins/runway.md | 56 +++++++------ content/v3/de/learn/ai.md | 36 ++++----- content/v3/en/about.md | 10 ++- content/v3/es/about.md | 87 ++++++++++++--------- content/v3/es/awesome-plugins/runway.md | 52 ++++++------ content/v3/es/learn/ai.md | 30 +++---- content/v3/fr/about.md | 60 ++++++++------ content/v3/fr/awesome-plugins/runway.md | 40 +++++----- content/v3/fr/learn/ai.md | 38 ++++----- content/v3/id/about.md | 76 ++++++++++-------- content/v3/id/awesome-plugins/runway.md | 80 +++++++++---------- content/v3/id/learn/ai.md | 12 +-- content/v3/ja/about.md | 77 ++++++++++-------- content/v3/ja/awesome-plugins/runway.md | 62 +++++++-------- content/v3/ja/learn/ai.md | 34 ++++---- content/v3/ko/about.md | 66 +++++++++------- content/v3/ko/awesome-plugins/runway.md | 36 ++++----- content/v3/ko/learn/ai.md | 44 +++++------ content/v3/lv/about.md | 76 ++++++++++-------- content/v3/lv/awesome-plugins/runway.md | 52 ++++++------ content/v3/lv/learn/ai.md | 56 ++++++------- content/v3/pt/about.md | 60 ++++++++------ content/v3/pt/awesome-plugins/runway.md | 30 +++---- content/v3/pt/learn/ai.md | 20 ++--- content/v3/ru/about.md | 64 ++++++++------- content/v3/ru/awesome-plugins/runway.md | 84 ++++++++++---------- content/v3/ru/learn/ai.md | 28 +++---- content/v3/uk/about.md | 70 +++++++++-------- content/v3/uk/awesome-plugins/runway.md | 100 ++++++++++++------------ content/v3/uk/learn/ai.md | 54 ++++++------- content/v3/zh/about.md | 74 ++++++++++-------- content/v3/zh/awesome-plugins/runway.md | 36 ++++----- content/v3/zh/learn/ai.md | 52 ++++++------ 35 files changed, 967 insertions(+), 884 deletions(-) diff --git a/composer.lock b/composer.lock index c09eb97f..103eb35a 100644 --- a/composer.lock +++ b/composer.lock @@ -301,16 +301,16 @@ }, { "name": "flightphp/core", - "version": "v3.17.2", + "version": "v3.18.0", "source": { "type": "git", "url": "https://github.com/flightphp/core.git", - "reference": "095a46663f7090c549f5c3459f0dada893b3b5d9" + "reference": "88d7032928c09b98e65ccd87b7f8a341a40cc3d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/flightphp/core/zipball/095a46663f7090c549f5c3459f0dada893b3b5d9", - "reference": "095a46663f7090c549f5c3459f0dada893b3b5d9", + "url": "https://api.github.com/repos/flightphp/core/zipball/88d7032928c09b98e65ccd87b7f8a341a40cc3d2", + "reference": "88d7032928c09b98e65ccd87b7f8a341a40cc3d2", "shasum": "" }, "require": { @@ -323,14 +323,13 @@ "require-dev": { "ext-pdo_sqlite": "*", "flightphp/container": "^1.0", - "flightphp/runway": "^0.2.3 || ^1.0", + "flightphp/runway": "^1.2", "league/container": "^4.2", "level-2/dice": "^4.0", "phpstan/extension-installer": "^1.4", "phpstan/phpstan": "^2.1", "phpunit/phpunit": "^9.6", "rregeer/phpunit-coverage-check": "^0.3.1", - "spatie/phpunit-watcher": "^1.23 || ^1.24", "squizlabs/php_codesniffer": "^3.11" }, "suggest": { @@ -371,22 +370,22 @@ "homepage": "http://flightphp.com", "support": { "issues": "https://github.com/flightphp/core/issues", - "source": "https://github.com/flightphp/core/tree/v3.17.2" + "source": "https://github.com/flightphp/core/tree/v3.18.0" }, - "time": "2025-10-03T21:05:48+00:00" + "time": "2026-01-15T01:44:32+00:00" }, { "name": "flightphp/runway", - "version": "v1.2.0", + "version": "v1.2.6", "source": { "type": "git", "url": "https://github.com/flightphp/runway.git", - "reference": "6924f511b6de47e6c6da32d17c6dfc4a963f5f52" + "reference": "50764ca235349886cc926d7b49b48e3fee55a146" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/flightphp/runway/zipball/6924f511b6de47e6c6da32d17c6dfc4a963f5f52", - "reference": "6924f511b6de47e6c6da32d17c6dfc4a963f5f52", + "url": "https://api.github.com/repos/flightphp/runway/zipball/50764ca235349886cc926d7b49b48e3fee55a146", + "reference": "50764ca235349886cc926d7b49b48e3fee55a146", "shasum": "" }, "require": { @@ -423,9 +422,9 @@ "description": "Console app for the Flight PHP Framework.", "support": { "issues": "https://github.com/flightphp/runway/issues", - "source": "https://github.com/flightphp/runway/tree/v1.2.0" + "source": "https://github.com/flightphp/runway/tree/v1.2.6" }, - "time": "2025-11-14T14:30:07+00:00" + "time": "2026-01-15T05:31:38+00:00" }, { "name": "latte/latte", @@ -905,16 +904,16 @@ }, { "name": "rector/rector", - "version": "2.2.14", + "version": "2.3.1", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "6d56bb0e94d4df4f57a78610550ac76ab403657d" + "reference": "9afc1bb43571b25629f353c61a9315b5ef31383a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/6d56bb0e94d4df4f57a78610550ac76ab403657d", - "reference": "6d56bb0e94d4df4f57a78610550ac76ab403657d", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/9afc1bb43571b25629f353c61a9315b5ef31383a", + "reference": "9afc1bb43571b25629f353c61a9315b5ef31383a", "shasum": "" }, "require": { @@ -953,7 +952,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.2.14" + "source": "https://github.com/rectorphp/rector/tree/2.3.1" }, "funding": [ { @@ -961,7 +960,7 @@ "type": "github" } ], - "time": "2025-12-09T10:57:55+00:00" + "time": "2026-01-13T15:13:58+00:00" } ], "aliases": [], diff --git a/content/v3/de/about.md b/content/v3/de/about.md index c448877d..3a8bfed7 100644 --- a/content/v3/de/about.md +++ b/content/v3/de/about.md @@ -1,14 +1,16 @@ -# Flight PHP-Framework +# Flight PHP Framework -Flight ist ein schnelles, simples, erweiterbares Framework für PHP – entwickelt für Entwickler, die Dinge schnell erledigen wollen, ohne Aufwand. Ob Sie eine klassische Web-App, eine blitzschnelle API oder mit den neuesten KI-gestützten Tools experimentieren, Flights geringer Fußabdruck und geradliniges Design machen es zur perfekten Wahl. Flight ist darauf ausgelegt, schlank zu sein, kann aber auch Anforderungen an eine Enterprise-Architektur erfüllen. +Flight ist ein schnelles, einfaches, erweiterbares Framework für PHP – gebaut für Entwickler, die Dinge schnell erledigen wollen, ohne Aufhebens. Egal, ob Sie eine klassische Web-App, eine ultraschnelle API oder mit den neuesten KI-gestützten Tools experimentieren, Flights geringer Footprint und unkompliziertes Design machen es zur perfekten Wahl. Flight ist schlank konzipiert, kann aber auch Anforderungen an Enterprise-Architekturen erfüllen. ## Warum Flight wählen? -- **Anfängerfreundlich:** Flight ist ein toller Einstiegspunkt für neue PHP-Entwickler. Seine klare Struktur und einfache Syntax helfen Ihnen, Web-Entwicklung zu lernen, ohne in Boilerplate-Code zu versinken. -- **Geliebt von Profis:** Erfahrene Entwickler lieben Flight für seine Flexibilität und Kontrolle. Sie können von einem kleinen Prototypen zu einer vollwertigen App skalieren, ohne das Framework zu wechseln. -- **KI-Freundlich:** Flights minimale Overhead und saubere Architektur machen es ideal für die Integration von KI-Tools und APIs. Ob Sie smarte Chatbots, KI-gesteuerte Dashboards bauen oder einfach experimentieren wollen, Flight hält sich zurück, damit Sie sich auf das Wesentliche konzentrieren können. Die [skeleton app](https://github.com/flightphp/skeleton) enthält vorkonfigurierte Anweisungsdateien für die großen KI-Coding-Assistenten! [Mehr erfahren über die Nutzung von KI mit Flight](/learn/ai) +- **Anfängerfreundlich:** Flight ist ein toller Einstieg für neue PHP-Entwickler. Seine klare Struktur und einfache Syntax helfen Ihnen, Web-Entwicklung zu lernen, ohne sich in Boilerplate-Code zu verlieren. +- **Geliebt von Profis:** Erfahrene Entwickler lieben Flight für seine Flexibilität und Kontrolle. Sie können von einem kleinen Prototyp zu einer voll ausgestatteten App skalieren, ohne das Framework zu wechseln. +- **Rückwärtskompatibel:** Wir schätzen Ihre Zeit. Flight v3 ist eine Erweiterung von v2 und behält fast das gesamte API bei. Wir glauben an Evolution, nicht an Revolution – keine weiteren „Weltuntergänge“ bei jedem Major-Release. +- **Keine Abhängigkeiten:** Der Kern von Flight ist vollständig abhängigkeitsfrei – keine Polyfills, keine externen Pakete, nicht einmal PSR-Schnittstellen. Das bedeutet weniger Angriffsvektoren, einen kleineren Footprint und keine überraschenden Breaking Changes von Upstream-Abhängigkeiten. Optionale Plugins können Abhängigkeiten enthalten, aber der Kern bleibt immer schlank und sicher. +- **KI-fokussiert:** Flights minimale Overhead und saubere Architektur machen es ideal für die Integration von KI-Tools und APIs. Egal, ob Sie smarte Chatbots, KI-gesteuerte Dashboards bauen oder einfach experimentieren wollen, Flight tritt beiseite, damit Sie sich auf das Wesentliche konzentrieren können. Die [Skeleton-App](https://github.com/flightphp/skeleton) kommt mit vorgefertigten Anweisungsdateien für die großen KI-Coding-Assistenten direkt aus der Box! [Mehr über die Nutzung von KI mit Flight](/learn/ai) -## Videoubersicht +## Video-Übersicht
          @@ -18,27 +20,27 @@ Flight ist ein schnelles, simples, erweiterbares Framework für PHP – entwicke
          Einfach genug, oder?
          - Mehr erfahren über Flight in der Dokumentation! + Erfahren Sie mehr über Flight in der Dokumentation!
          -## Schnellstart +## Schneller Einstieg -Für eine schnelle, grundlegende Installation installieren Sie es mit Composer: +Für eine schnelle, basische Installation installieren Sie es mit Composer: ```bash composer require flightphp/core ``` -Oder laden Sie ein ZIP des Repos [hier](https://github.com/flightphp/core) herunter. Dann haben Sie eine grundlegende `index.php`-Datei wie folgt: +Oder Sie laden ein Zip des Repos [hier](https://github.com/flightphp/core) herunter. Dann hätten Sie eine grundlegende `index.php`-Datei wie die folgende: ```php 8 würde für diese Benutzer Probleme verursachen. Das Framework unterstützt auch PHP >8. +**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. Eine Zwangsmigration zu PHP >8 würde vielen Nutzern Kopfschmerzen bereiten. Das Framework unterstützt auch PHP >8. # Lizenz diff --git a/content/v3/de/awesome-plugins/runway.md b/content/v3/de/awesome-plugins/runway.md index 6b2c83fc..314eb766 100644 --- a/content/v3/de/awesome-plugins/runway.md +++ b/content/v3/de/awesome-plugins/runway.md @@ -1,8 +1,8 @@ # Runway -Runway ist eine CLI-Anwendung, die Ihnen hilft, Ihre Flight-Anwendungen zu verwalten. Sie kann Controller generieren, alle Routen anzeigen und mehr. Sie basiert auf der exzellenten [adhocore/php-cli](https://github.com/adhocore/php-cli)-Bibliothek. +Runway ist eine CLI-Anwendung, die Ihnen hilft, Ihre Flight-Anwendungen zu verwalten. Sie kann Controller generieren, alle Routen anzeigen und mehr. Sie basiert auf der hervorragenden [adhocore/php-cli](https://github.com/adhocore/php-cli)-Bibliothek. -Klicken Sie [hier](https://github.com/flightphp/runway), um den Code anzuzeigen. +Klicken Sie [hier](https://github.com/flightphp/runway), um den Code anzusehen. ## Installation @@ -14,7 +14,7 @@ composer require flightphp/runway ## Basis-Konfiguration -Beim ersten Ausführen von Runway versucht es, eine `runway`-Konfiguration in `app/config/config.php` über den Schlüssel `'runway'` zu finden. +Beim ersten Ausführen von Runway versucht es, eine `runway`-Konfiguration in `app/config/config.php` über den `'runway'`-Schlüssel zu finden. ```php **HINWEIS** - Ab **v1.2.0** ist `.runway-config.json` veraltet. Bitte migrieren Sie Ihre Konfiguration zu `app/config/config.php`. Sie können dies einfach mit dem Befehl `php runway config:migrate` tun. - - ### Projekt-Root-Erkennung -Runway ist intelligent genug, um das Root-Verzeichnis Ihres Projekts zu erkennen, auch wenn Sie es aus einem Unterverzeichnis ausführen. Es sucht nach Indikatoren wie `composer.json`, `.git` oder `app/config/config.php`, um zu bestimmen, wo das Projekt-Root liegt. Das bedeutet, Sie können Runway-Befehle von überall in Ihrem Projekt ausführen! +Runway ist intelligent genug, um das Root-Verzeichnis Ihres Projekts zu erkennen, auch wenn Sie es aus einem Unterverzeichnis ausführen. Es sucht nach Indikatoren wie `composer.json`, `.git` oder `app/config/config.php`, um zu bestimmen, wo das Projekt-Root liegt. Das bedeutet, Sie können Runway-Befehle von überall in Ihrem Projekt ausführen! ## Verwendung Runway verfügt über eine Reihe von Befehlen, die Sie verwenden können, um Ihre Flight-Anwendung zu verwalten. Es gibt zwei einfache Wege, Runway zu nutzen. -1. Wenn Sie das Skeleton-Projekt verwenden, können Sie `php runway [command]` vom Root Ihres Projekts ausführen. -1. Wenn Sie Runway als über Composer installiertes Paket verwenden, können Sie `vendor/bin/runway [command]` vom Root Ihres Projekts ausführen. +1. Wenn Sie das Skeleton-Projekt verwenden, können Sie `php runway [command]` aus dem Root-Verzeichnis Ihres Projekts ausführen. +1. Wenn Sie Runway als über Composer installiertes Paket verwenden, können Sie `vendor/bin/runway [command]` aus dem Root-Verzeichnis Ihres Projekts ausführen. ### Befehlsliste @@ -52,13 +50,13 @@ php runway ### Befehls-Hilfe -Für jeden Befehl können Sie die `--help`-Flagge übergeben, um mehr Informationen darüber zu erhalten, wie der Befehl verwendet wird. +Für jeden Befehl können Sie die `--help`-Flagge übergeben, um mehr Informationen darüber zu erhalten, wie man den Befehl verwendet. ```bash php runway routes --help ``` -Hier sind ein paar Beispiele: +Hier sind einige Beispiele: ### Einen Controller generieren @@ -76,7 +74,7 @@ Stellen Sie zuerst sicher, dass Sie das [Active Record](/awesome-plugins/active- php runway make:record users ``` -Wenn Sie beispielsweise die `users`-Tabelle mit dem folgenden Schema haben: `id`, `name`, `email`, `created_at`, `updated_at`, wird eine Datei ähnlich der folgenden in der Datei `app/records/UserRecord.php` erstellt: +Falls Sie beispielsweise die `users`-Tabelle mit dem folgenden Schema haben: `id`, `name`, `email`, `created_at`, `updated_at`, wird eine Datei ähnlich der folgenden in der Datei `app/records/UserRecord.php` erstellt: ```php argument('', 'Der Name des lustigen GIFs'); } @@ -171,24 +169,24 @@ class ExampleCommand extends AbstractBaseCommand { $io = $this->app()->io(); - $io->info('Erstellen des Beispiels...'); + $io->info('Erstelle Beispiel...'); - // Hier etwas tun + // Etwas hier tun $io->ok('Beispiel erstellt!'); } } ``` -Sehen Sie sich die [adhocore/php-cli-Dokumentation](https://github.com/adhocore/php-cli) für weitere Informationen an, wie Sie eigene benutzerdefinierte Befehle in Ihre Flight-Anwendung einbauen können! +Sehen Sie die [adhocore/php-cli-Dokumentation](https://github.com/adhocore/php-cli) für weitere Informationen darüber, wie Sie eigene benutzerdefinierte Befehle in Ihre Flight-Anwendung einbauen! ## Konfigurationsverwaltung -Da die Konfiguration ab `v1.2.0` zu `app/config/config.php` verschoben wurde, gibt es ein paar Hilfsbefehle zur Verwaltung der Konfiguration. +Da die Konfiguration ab `v1.2.0` zu `app/config/config.php` verschoben wurde, gibt es einige Hilfsbefehle zur Verwaltung der Konfiguration. ### Alte Konfiguration migrieren -Wenn Sie eine alte `.runway-config.json`-Datei haben, können Sie sie einfach mit dem folgenden Befehl zu `app/config/config.php` migrieren: +Wenn Sie eine alte `.runway-config.json`-Datei haben, können Sie sie leicht zu `app/config/config.php` migrieren mit dem folgenden Befehl: ```bash php runway config:migrate @@ -235,7 +233,7 @@ return [ // Basis-Pfade müssen wahrscheinlich nicht konfiguriert werden, aber es ist hier, falls Sie es wünschen 'base_paths' => [ - '/includes/libs/vendor', // wenn Sie einen wirklich einzigartigen Pfad für Ihr Vendor-Verzeichnis haben oder so + '/includes/libs/vendor', // falls Sie einen wirklich einzigartigen Pfad für Ihr Vendor-Verzeichnis haben oder so ], // Finale Pfade sind Orte innerhalb eines Projekts, um nach Befehlsdateien zu suchen @@ -244,7 +242,7 @@ return [ 'app/module/admin/commands', ], - // Wenn Sie den vollständigen Pfad hinzufügen möchten, gehen Sie einfach voran (absolut oder relativ zum Projekt-Root) + // Wenn Sie einfach den vollständigen Pfad hinzufügen möchten, tun Sie es ruhig (absolut oder relativ zum Projekt-Root) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -263,10 +261,10 @@ public function execute() { $io = $this->app()->io(); - // Konfiguration abrufen + // Zugriff auf Konfiguration $app_root = $this->config['runway']['app_root']; - // Dienste abrufen, wie vielleicht eine Datenbankverbindung + // Zugriff auf Dienste wie vielleicht eine Datenbankverbindung $database = $this->config['database'] // ... @@ -275,14 +273,14 @@ public function execute() ## AI-Hilfs-Wrapper -Runway hat einige Hilfs-Wrapper, die es einfacher machen, für KI Befehle zu generieren. Sie können `addOption` und `addArgument` auf eine Weise verwenden, die ähnlich wie Symfony Console wirkt. Dies ist hilfreich, wenn Sie KI-Tools verwenden, um Ihre Befehle zu generieren. +Runway hat einige Hilfs-Wrapper, die es AI erleichtern, Befehle zu generieren. Sie können `addOption` und `addArgument` auf eine Weise verwenden, die ähnlich wie Symfony Console wirkt. Dies ist hilfreich, wenn Sie AI-Tools verwenden, um Ihre Befehle zu generieren. ```php public function __construct(array $config) { - parent::__construct('make:example', 'Erstellen eines Beispiels für die Dokumentation', $config); + parent::__construct('make:example', 'Erstellt ein Beispiel für die Dokumentation', $config); - // Der name-Argument ist nullable und standardmäßig vollständig optional + // Der name-Argument ist nullbar und standardmäßig vollständig optional $this->addOption('name', 'Der Name des Beispiels', null); } ``` \ No newline at end of file diff --git a/content/v3/de/learn/ai.md b/content/v3/de/learn/ai.md index 8d3840bb..8e9cabcd 100644 --- a/content/v3/de/learn/ai.md +++ b/content/v3/de/learn/ai.md @@ -2,11 +2,11 @@ ## Überblick -Flight erleichtert es, Ihre PHP-Projekte mit KI-gestützten Tools und modernen Entwickler-Workflows aufzurüsten. Mit integrierten Befehlen zur Verbindung mit LLM-Anbietern (Large Language Model) und zur Generierung von projektspezifischen KI-Coding-Anweisungen hilft Flight Ihnen und Ihrem Team, das Maximum aus KI-Assistenten wie GitHub Copilot, Cursor, Windsurf und Antigravity (Gemini) herauszuholen. +Flight erleichtert es, Ihre PHP-Projekte mit KI-gestützten Tools und modernen Entwickler-Workflows aufzurüsten. Mit integrierten Befehlen zur Verbindung mit LLM-Anbietern (Large Language Model) und zur Generierung projektspezifischer KI-Coding-Anweisungen hilft Flight Ihnen und Ihrem Team, das Maximum aus KI-Assistenten wie GitHub Copilot, Cursor, Windsurf und Antigravity (Gemini) herauszuholen. ## Verständnis -KI-Coding-Assistenten sind am hilfreichsten, wenn sie den Kontext, die Konventionen und die Ziele Ihres Projekts verstehen. Die KI-Hilfsprogramme von Flight ermöglichen es Ihnen: +KI-Coding-Assistenten sind am hilfreichsten, wenn sie den Kontext, die Konventionen und die Ziele Ihres Projekts verstehen. Die KI-Hilfen von Flight ermöglichen es Ihnen: - Ihr Projekt mit beliebten LLM-Anbietern zu verbinden (OpenAI, Grok, Claude usw.) - Projektspezifische Anweisungen für KI-Tools zu generieren und zu aktualisieren, damit alle konsistente, relevante Hilfe erhalten - Ihr Team ausgerichtet und produktiv zu halten, mit weniger Zeit für die Erklärung des Kontexts @@ -15,7 +15,7 @@ Diese Funktionen sind in die Flight-Core-CLI und das offizielle [flightphp/skele ## Grundlegende Nutzung -### Einrichten von LLM-Anmeldeinformationen +### Einrichten von LLM-Zugangsdaten Der Befehl `ai:init` führt Sie durch die Verbindung Ihres Projekts mit einem LLM-Anbieter. @@ -28,19 +28,19 @@ Sie werden aufgefordert: - Ihren API-Schlüssel einzugeben - Die Basis-URL und den Modellnamen festzulegen -Dies erstellt die notwendigen Anmeldeinformationen für zukünftige LLM-Anfragen. +Dies erstellt die notwendigen Zugangsdaten, damit Sie zukünftige LLM-Anfragen stellen können. **Beispiel:** ``` -Welcome to AI Init! -Which LLM API do you want to use? [1] openai, [2] grok, [3] claude: 1 -Enter the base URL for the LLM API [https://api.openai.com]: -Enter your API key for openai: sk-... -Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: -Credentials saved to .runway-creds.json +Willkommen bei AI Init! +Welchen LLM-API möchten Sie verwenden? [1] openai, [2] grok, [3] claude: 1 +Geben Sie die Basis-URL für die LLM-API ein [https://api.openai.com]: +Geben Sie Ihren API-Schlüssel für openai ein: sk-... +Geben Sie den Modellnamen ein, den Sie verwenden möchten (z. B. gpt-4, claude-3-opus usw.) [gpt-4o]: +Zugangsdaten wurden in .runway-creds.json gespeichert ``` -### Generieren von projektspezifischen KI-Anweisungen +### Generieren projektspezifischer KI-Anweisungen Der Befehl `ai:generate-instructions` hilft Ihnen, Anweisungen für KI-Coding-Assistenten zu erstellen oder zu aktualisieren, die auf Ihr Projekt zugeschnitten sind. @@ -56,20 +56,20 @@ Sie beantworten ein paar Fragen zu Ihrem Projekt (Beschreibung, Datenbank, Vorla **Beispiel:** ``` -Please describe what your project is for? My awesome API -What database are you planning on using? MySQL -What HTML templating engine will you plan on using (if any)? latte -Is security an important element of this project? (y/n) y +Bitte beschreiben Sie, wofür Ihr Projekt gedacht ist? Meine tolle API +Welche Datenbank planen Sie zu verwenden? MySQL +Welchen HTML-Vorlagen-Engine planen Sie zu verwenden (falls zutreffend)? latte +Ist Sicherheit ein wichtiger Aspekt dieses Projekts? (y/n) y ... -AI instructions updated successfully. +KI-Anweisungen erfolgreich aktualisiert. ``` Nun geben Ihre KI-Tools intelligentere, relevantere Vorschläge basierend auf den tatsächlichen Bedürfnissen Ihres Projekts. ## Erweiterte Nutzung -- Sie können den Speicherort Ihrer Anmeldeinformationen oder Anweisungsdateien mit Befehlsoptionen anpassen (siehe `--help` für jeden Befehl). -- Die KI-Hilfsprogramme sind so konzipiert, dass sie mit jedem LLM-Anbieter funktionieren, der OpenAI-kompatible APIs unterstützt. +- Sie können den Speicherort Ihrer Zugangsdaten- oder Anweisungsdateien mit Befehlsoptionen anpassen (siehe `--help` für jeden Befehl). +- Die KI-Hilfen sind so konzipiert, dass sie mit jedem LLM-Anbieter funktionieren, der OpenAI-kompatible APIs unterstützt. - Wenn Sie Ihre Anweisungen aktualisieren möchten, während sich Ihr Projekt weiterentwickelt, führen Sie einfach `ai:generate-instructions` erneut aus und beantworten Sie die Aufforderungen erneut. ## Siehe auch diff --git a/content/v3/en/about.md b/content/v3/en/about.md index 81bf1444..f927988b 100644 --- a/content/v3/en/about.md +++ b/content/v3/en/about.md @@ -6,7 +6,9 @@ Flight is a fast, simple, extensible framework for PHP—built for developers wh - **Beginner Friendly:** Flight is a great starting point for new PHP developers. Its clear structure and simple syntax help you learn web development without getting lost in boilerplate. - **Loved by Pros:** Experienced devs love Flight for its flexibility and control. You can scale from a tiny prototype to a full-featured app without switching frameworks. -- **AI Friendly:** Flight's minimal overhead and clean architecture make it ideal for integrating AI tools and APIs. Whether you're building smart chatbots, AI-driven dashboards, or just want to experiment, Flight gets out of your way so you can focus on what matters. The [skeleton app](https://github.com/flightphp/skeleton) comes with pre-built instructions files for the major AI coding assistants out of the box! [Learn more about using AI with Flight](/learn/ai) +- **Backwards Compatible:** We value your time. Flight v3 is an augmentation of v2, keeping almost all of the same API. We believe in evolution, not revolution—no more "breaking the world" every time a major version comes out. +- **Zero Dependencies:** Flight's core is completely dependency-free—no polyfills, no external packages, not even PSR interfaces. This means fewer attack vectors, a smaller footprint, and no surprise breaking changes from upstream dependencies. Optional plugins may include dependencies, but the core will always stay lean and secure. +- **AI Focused:** Flight's minimal overhead and clean architecture make it ideal for integrating AI tools and APIs. Whether you're building smart chatbots, AI-driven dashboards, or just want to experiment, Flight gets out of your way so you can focus on what matters. The [skeleton app](https://github.com/flightphp/skeleton) comes with pre-built instructions files for the major AI coding assistants out of the box! [Learn more about using AI with Flight](/learn/ai) ## Video Overview @@ -98,6 +100,12 @@ See the benchmark below with some other popular PHP frameworks. Curious how it handles AI? [Discover](/learn/ai) how Flight makes working with your favorite coding LLM easy! +## Stability and Backwards Compatibility + +We value your time. We've all seen frameworks that completely reinvent themselves every couple of years, leaving developers with broken code and expensive migrations. Flight is different. Flight v3 was designed as an augmentation of v2, which means that the API you know and love hasn't been stripped away. In fact, most v2 projects will work without any changes in v3. + +We're committed to keeping Flight stable so you can focus on building your app, not fixing your framework. + # Community We're on Matrix Chat diff --git a/content/v3/es/about.md b/content/v3/es/about.md index 7e21d67a..4e65c218 100644 --- a/content/v3/es/about.md +++ b/content/v3/es/about.md @@ -1,19 +1,21 @@ -# Marco de trabajo PHP Flight +# Flight PHP Framework -Flight es un framework rápido, simple y extensible para PHP, diseñado para desarrolladores que quieren hacer las cosas rápidamente, sin complicaciones. Ya sea que estés construyendo una aplicación web clásica, una API ultrarrápida o experimentando con las últimas herramientas impulsadas por IA, la huella baja de Flight y su diseño directo lo convierten en una opción perfecta. Flight está destinado a ser ligero, pero también puede manejar requisitos de arquitectura empresarial. +Flight es un framework rápido, simple y extensible para PHP—construido para desarrolladores que quieren hacer las cosas rápidamente, sin complicaciones. Ya sea que estés construyendo una aplicación web clásica, una API ultrarrápida o experimentando con las últimas herramientas impulsadas por IA, la baja huella y el diseño directo de Flight lo hacen perfecto. Flight está diseñado para ser ligero, pero también puede manejar requisitos de arquitectura empresarial. ## ¿Por qué elegir Flight? -- **Amigable para principiantes:** Flight es un gran punto de partida para nuevos desarrolladores de PHP. Su estructura clara y sintaxis simple te ayudan a aprender desarrollo web sin perderte en código innecesario. -- **Amado por los profesionales:** Los desarrolladores experimentados aman Flight por su flexibilidad y control. Puedes escalar desde un prototipo pequeño hasta una aplicación completa sin cambiar de framework. -- **Amigable con la IA:** La sobrecarga mínima y la arquitectura limpia de Flight lo hacen ideal para integrar herramientas y APIs de IA. Ya sea que estés construyendo chatbots inteligentes, tableros impulsados por IA o simplemente quieras experimentar, Flight se quita de en medio para que te enfoques en lo que importa. ¡La [aplicación esqueleto](https://github.com/flightphp/skeleton) viene con archivos de instrucciones precompilados para los principales asistentes de codificación de IA desde el principio! [Aprende más sobre el uso de IA con Flight](/learn/ai) +- **Amigable para principiantes:** Flight es un gran punto de partida para nuevos desarrolladores de PHP. Su estructura clara y sintaxis simple te ayudan a aprender desarrollo web sin perderte en código boilerplate. +- **Amado por profesionales:** Los desarrolladores experimentados aman Flight por su flexibilidad y control. Puedes escalar desde un prototipo pequeño hasta una aplicación completa sin cambiar de framework. +- **Compatible hacia atrás:** Valoramos tu tiempo. Flight v3 es una ampliación de v2, manteniendo casi toda la misma API. Creemos en la evolución, no en la revolución—no más "rompiendo el mundo" cada vez que sale una versión mayor. +- **Cero dependencias:** El núcleo de Flight es completamente libre de dependencias—no polyfills, no paquetes externos, ni siquiera interfaces PSR. Esto significa menos vectores de ataque, una huella más pequeña y no hay cambios rompedores sorpresa de dependencias upstream. Los plugins opcionales pueden incluir dependencias, pero el núcleo siempre permanecerá ligero y seguro. +- **Enfocado en IA:** La sobrecarga mínima y la arquitectura limpia de Flight lo hacen ideal para integrar herramientas y APIs de IA. Ya sea que estés construyendo chatbots inteligentes, tableros impulsados por IA o solo quieras experimentar, Flight se aparta para que puedas enfocarte en lo que importa. La [aplicación skeleton](https://github.com/flightphp/skeleton) viene con archivos de instrucciones pre-construidos para los principales asistentes de codificación de IA directamente de la caja! [Aprende más sobre el uso de IA con Flight](/learn/ai) -## Resumen en video +## Resumen en Video
          - +
          ¿Suficientemente simple, verdad? @@ -23,22 +25,22 @@ Flight es un framework rápido, simple y extensible para PHP, diseñado para des
          -## Inicio rápido +## Inicio Rápido -Para hacer una instalación básica y rápida, instálalo con Composer: +Para una instalación rápida y básica, instálalo con Composer: ```bash composer require flightphp/core ``` -O puedes descargar un zip del repositorio [aquí](https://github.com/flightphp/core). Luego, tendrías un archivo básico `index.php` como el siguiente: +O puedes descargar un zip del repositorio [aquí](https://github.com/flightphp/core). Luego tendrías un archivo `index.php` básico como el siguiente: ```php 8 causaría muchos problemas para esos usuarios. El framework también soporta PHP >8. +**Nota:** PHP 7.4 es soportado porque en el momento actual de escritura (2024) PHP 7.4 es la versión predeterminada para algunas distribuciones Linux LTS. Forzar un movimiento a PHP >8 causaría mucho dolor de cabeza para esos usuarios. El framework también soporta PHP >8. # Licencia -Flight se libera bajo la [licencia MIT](https://github.com/flightphp/core/blob/master/LICENSE). \ No newline at end of file +Flight se libera bajo la licencia [MIT](https://github.com/flightphp/core/blob/master/LICENSE). \ No newline at end of file diff --git a/content/v3/es/awesome-plugins/runway.md b/content/v3/es/awesome-plugins/runway.md index 7ac450ce..142ac85d 100644 --- a/content/v3/es/awesome-plugins/runway.md +++ b/content/v3/es/awesome-plugins/runway.md @@ -29,9 +29,9 @@ return [ > **NOTA** - A partir de **v1.2.0**, `.runway-config.json` está obsoleto. Por favor, migra tu configuración a `app/config/config.php`. Puedes hacerlo fácilmente con el comando `php runway config:migrate`. -### Detección de Raíz del Proyecto +### Detección de la Raíz del Proyecto -Runway es lo suficientemente inteligente como para detectar la raíz de tu proyecto, incluso si lo ejecutas desde un subdirectorio. Busca indicadores como `composer.json`, `.git` o `app/config/config.php` para determinar dónde está la raíz del proyecto. Esto significa que puedes ejecutar comandos de Runway desde cualquier lugar en tu proyecto! +Runway es lo suficientemente inteligente como para detectar la raíz de tu proyecto, incluso si lo ejecutas desde un subdirectorio. Busca indicadores como `composer.json`, `.git` o `app/config/config.php` para determinar dónde está la raíz del proyecto. Esto significa que puedes ejecutar comandos de Runway desde cualquier lugar en tu proyecto! ## Uso @@ -74,7 +74,7 @@ Primero asegúrate de haber instalado el plugin [Active Record](/awesome-plugins php runway make:record users ``` -Si, por ejemplo, tienes la tabla `users` con el siguiente esquema: `id`, `name`, `email`, `created_at`, `updated_at`, se creará un archivo similar al siguiente en el archivo `app/records/UserRecord.php`: +Por ejemplo, si tienes la tabla `users` con el siguiente esquema: `id`, `name`, `email`, `created_at`, `updated_at`, se creará un archivo similar al siguiente en el archivo `app/records/UserRecord.php`: ```php $config Config from app/config/config.php + * @param array $config Configuración de app/config/config.php */ public function __construct(array $config) { - parent::__construct('make:example', 'Create an example for the documentation', $config); - $this->argument('', 'The name of the funny gif'); + parent::__construct('make:example', 'Crear un ejemplo para la documentación', $config); + $this->argument('', 'El nombre del gif gracioso'); } /** - * Executes the function + * Ejecuta la función * * @return void */ @@ -169,11 +169,11 @@ class ExampleCommand extends AbstractBaseCommand { $io = $this->app()->io(); - $io->info('Creating example...'); + $io->info('Creando ejemplo...'); - // Do something here + // Haz algo aquí - $io->ok('Example created!'); + $io->ok('¡Ejemplo creado!'); } } ``` @@ -182,7 +182,7 @@ Consulta la [Documentación de adhocore/php-cli](https://github.com/adhocore/php ## Gestión de Configuración -Dado que la configuración se ha movido a `app/config/config.php` a partir de `v1.2.0`, hay algunos comandos auxiliares para gestionar la configuración. +Dado que la configuración se ha movido a `app/config/config.php` a partir de `v1.2.0`, hay algunos comandos de ayuda para gestionar la configuración. ### Migrar Configuración Antigua @@ -216,33 +216,33 @@ Si necesitas personalizar la configuración para Runway, puedes establecer estos [ - // This is where your application directory is located + // Aquí es donde se encuentra tu directorio de aplicación 'app_root' => 'app/', - // This is the directory where your root index file is located + // Este es el directorio donde se encuentra tu archivo index raíz 'index_root' => 'public/', - // These are the paths to the roots of other projects + // Estas son las rutas a las raíces de otros proyectos 'root_paths' => [ '/home/user/different-project', '/var/www/another-project' ], - // Base paths most likely don't need to be configured, but it's here if you want it + // Las rutas base probablemente no necesiten configurarse, pero está aquí si lo quieres 'base_paths' => [ - '/includes/libs/vendor', // if you have a really unique path for your vendor directory or something + '/includes/libs/vendor', // si tienes una ruta realmente única para tu directorio vendor o algo ], - // Final paths are locations within a project to search for the command files + // Las rutas finales son ubicaciones dentro de un proyecto para buscar los archivos de comandos 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // If you want to just add the full path, go right ahead (absolute or relative to project root) + // Si quieres agregar la ruta completa, adelante (absoluta o relativa a la raíz del proyecto) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -261,10 +261,10 @@ public function execute() { $io = $this->app()->io(); - // Access configuration + // Acceder a la configuración $app_root = $this->config['runway']['app_root']; - // Access services like maybe a database connection + // Acceder a servicios como quizás una conexión a la base de datos $database = $this->config['database'] // ... @@ -278,9 +278,9 @@ Runway tiene algunos envoltorios de ayudante que facilitan que la IA genere coma ```php public function __construct(array $config) { - parent::__construct('make:example', 'Create an example for the documentation', $config); + parent::__construct('make:example', 'Crear un ejemplo para la documentación', $config); - // The mode argument is nullable and defaults to completely optional - $this->addOption('name', 'The name of the example', null); + // El argumento mode es nullable y por defecto es completamente opcional + $this->addOption('name', 'El nombre del ejemplo', null); } ``` \ No newline at end of file diff --git a/content/v3/es/learn/ai.md b/content/v3/es/learn/ai.md index 257b17d0..b93809ba 100644 --- a/content/v3/es/learn/ai.md +++ b/content/v3/es/learn/ai.md @@ -2,20 +2,20 @@ ## Resumen -Flight facilita potenciar tus proyectos PHP con herramientas impulsadas por IA y flujos de trabajo modernos para desarrolladores. Con comandos integrados para conectar con proveedores de LLM (Modelo de Lenguaje Grande) y generar instrucciones de codificación específicas del proyecto con IA, Flight te ayuda a ti y a tu equipo a sacar el máximo provecho de asistentes de IA como GitHub Copilot, Cursor, Windsurf y Antigravity (Gemini). +Flight facilita potenciar tus proyectos PHP con herramientas impulsadas por IA y flujos de trabajo modernos para desarrolladores. Con comandos integrados para conectar con proveedores de LLM (Large Language Model) y generar instrucciones de codificación específicas del proyecto impulsadas por IA, Flight te ayuda a ti y a tu equipo a sacar el máximo provecho de asistentes de IA como GitHub Copilot, Cursor, Windsurf y Antigravity (Gemini). -## Comprensión +## Entendiendo Los asistentes de codificación con IA son más útiles cuando entienden el contexto, las convenciones y los objetivos de tu proyecto. Los ayudantes de IA de Flight te permiten: - Conectar tu proyecto con proveedores populares de LLM (OpenAI, Grok, Claude, etc.) - Generar y actualizar instrucciones específicas del proyecto para herramientas de IA, para que todos reciban ayuda consistente y relevante - Mantener a tu equipo alineado y productivo, con menos tiempo dedicado a explicar el contexto -Estas características están integradas en el CLI principal de Flight y en el proyecto inicial oficial [flightphp/skeleton](https://github.com/flightphp/skeleton). +Estas funciones están integradas en el CLI principal de Flight y en el proyecto inicial oficial [flightphp/skeleton](https://github.com/flightphp/skeleton). ## Uso Básico -### Configuración de Credenciales de LLM +### Configurando Credenciales de LLM El comando `ai:init` te guía a través de la conexión de tu proyecto con un proveedor de LLM. @@ -23,10 +23,10 @@ El comando `ai:init` te guía a través de la conexión de tu proyecto con un pr php runway ai:init ``` -Se te pedirá: -- Elegir tu proveedor (OpenAI, Grok, Claude, etc.) -- Ingresar tu clave de API -- Establecer la URL base y el nombre del modelo +Te se pedirá que: +- Elijas tu proveedor (OpenAI, Grok, Claude, etc.) +- Ingreses tu clave API +- Establezcas la URL base y el nombre del modelo Esto crea las credenciales necesarias para realizar solicitudes futuras a LLM. @@ -35,12 +35,12 @@ Esto crea las credenciales necesarias para realizar solicitudes futuras a LLM. ¡Bienvenido a AI Init! ¿Cuál API de LLM quieres usar? [1] openai, [2] grok, [3] claude: 1 Ingresa la URL base para la API de LLM [https://api.openai.com]: -Ingresa tu clave de API para openai: sk-... +Ingresa tu clave API para openai: sk-... Ingresa el nombre del modelo que quieres usar (ej. gpt-4, claude-3-opus, etc) [gpt-4o]: Credenciales guardadas en .runway-creds.json ``` -### Generación de Instrucciones Específicas del Proyecto para IA +### Generando Instrucciones de IA Específicas del Proyecto El comando `ai:generate-instructions` te ayuda a crear o actualizar instrucciones para asistentes de codificación con IA, adaptadas a tu proyecto. @@ -48,7 +48,7 @@ El comando `ai:generate-instructions` te ayuda a crear o actualizar instruccione php runway ai:generate-instructions ``` -Responderás algunas preguntas sobre tu proyecto (descripción, base de datos, plantillas, seguridad, tamaño del equipo, etc.). Flight utiliza tu proveedor de LLM para generar instrucciones y luego las escribe en: +Responderás a unas pocas preguntas sobre tu proyecto (descripción, base de datos, plantillas, seguridad, tamaño del equipo, etc.). Flight usa tu proveedor de LLM para generar instrucciones y luego las escribe en: - `.github/copilot-instructions.md` (para GitHub Copilot) - `.cursor/rules/project-overview.mdc` (para Cursor) - `.windsurfrules` (para Windsurf) @@ -56,7 +56,7 @@ Responderás algunas preguntas sobre tu proyecto (descripción, base de datos, p **Ejemplo:** ``` -Por favor describe para qué es tu proyecto: Mi API genial +Por favor describe para qué es tu proyecto? Mi awesome API ¿Qué base de datos planeas usar? MySQL ¿Qué motor de plantillas HTML planeas usar (si aplica)? latte ¿Es la seguridad un elemento importante de este proyecto? (y/n) y @@ -70,7 +70,7 @@ Ahora, tus herramientas de IA darán sugerencias más inteligentes y relevantes - Puedes personalizar la ubicación de tus archivos de credenciales o instrucciones usando opciones de comando (ver `--help` para cada comando). - Los ayudantes de IA están diseñados para funcionar con cualquier proveedor de LLM que soporte APIs compatibles con OpenAI. -- Si quieres actualizar tus instrucciones a medida que evoluciona tu proyecto, solo vuelve a ejecutar `ai:generate-instructions` y responde los prompts nuevamente. +- Si quieres actualizar tus instrucciones a medida que tu proyecto evoluciona, solo vuelve a ejecutar `ai:generate-instructions` y responde a los prompts nuevamente. ## Ver También @@ -79,8 +79,8 @@ Ahora, tus herramientas de IA darán sugerencias más inteligentes y relevantes ## Solución de Problemas -- Si ves "Falta .runway-creds.json", ejecuta `php runway ai:init` primero. -- Asegúrate de que tu clave de API sea válida y tenga acceso al modelo seleccionado. +- Si ves "Missing .runway-creds.json", ejecuta `php runway ai:init` primero. +- Asegúrate de que tu clave API sea válida y tenga acceso al modelo seleccionado. - Si las instrucciones no se actualizan, verifica los permisos de archivos en tu directorio de proyecto. ## Registro de Cambios diff --git a/content/v3/fr/about.md b/content/v3/fr/about.md index 1b5e3e66..8d389323 100644 --- a/content/v3/fr/about.md +++ b/content/v3/fr/about.md @@ -1,14 +1,16 @@ -# Cadre PHP Flight +# Framework PHP Flight -Flight est un framework rapide, simple et extensible pour PHP, conçu pour les développeurs qui veulent accomplir les choses rapidement, sans complications. Que vous construisiez une application web classique, une API ultra-rapide, ou que vous expérimentiez avec les derniers outils alimentés par l'IA, la petite empreinte et la conception directe de Flight en font un choix parfait. Flight est destiné à être léger, mais il peut aussi gérer les exigences d'une architecture d'entreprise. +Flight est un framework rapide, simple et extensible pour PHP — conçu pour les développeurs qui veulent accomplir les choses rapidement, sans tracas. Que vous construisiez une application web classique, une API ultra-rapide, ou que vous expérimentiez avec les derniers outils alimentés par l'IA, l'empreinte faible de Flight et son design direct en font un choix parfait. Flight est conçu pour être léger, mais il peut aussi gérer les exigences d'architecture d'entreprise. -## Pourquoi choisir Flight ? +## Pourquoi Choisir Flight ? -- **Accessible aux débutants :** Flight est un excellent point de départ pour les nouveaux développeurs PHP. Sa structure claire et sa syntaxe simple vous aident à apprendre le développement web sans vous perdre dans du code boilerplate. -- **Aimé par les professionnels :** Les développeurs expérimentés adorent Flight pour sa flexibilité et son contrôle. Vous pouvez passer d'un prototype minuscule à une application complète sans changer de framework. -- **Compatible avec l'IA :** La surcharge minimale et l'architecture propre de Flight en font un outil idéal pour intégrer des outils et des API d'IA. Que vous construisiez des chatbots intelligents, des tableaux de bord pilotés par l'IA, ou que vous souhaitiez simplement expérimenter, Flight s'efface pour que vous puissiez vous concentrer sur l'essentiel. L'[application squelette](https://github.com/flightphp/skeleton) est fournie avec des fichiers d'instructions pré-construits pour les principaux assistants de codage d'IA dès la sortie de la boîte ! [En savoir plus sur l'utilisation de l'IA avec Flight](/learn/ai) +- **Amical pour les Débutants :** Flight est un excellent point de départ pour les nouveaux développeurs PHP. Sa structure claire et sa syntaxe simple vous aident à apprendre le développement web sans vous perdre dans le code boilerplate. +- **Apprécié par les Pros :** Les développeurs expérimentés adorent Flight pour sa flexibilité et son contrôle. Vous pouvez passer d'un prototype minuscule à une application complète sans changer de framework. +- **Compatible Rétroactivement :** Nous valorisons votre temps. Flight v3 est une augmentation de v2, en conservant presque toute la même API. Nous croyons en l'évolution, pas en la révolution — plus de « casser le monde » à chaque sortie d'une version majeure. +- **Zéro Dépendances :** Le cœur de Flight est complètement sans dépendances — pas de polyfills, pas de paquets externes, pas même d'interfaces PSR. Cela signifie moins de vecteurs d'attaque, une empreinte plus petite, et pas de changements cassants surprises des dépendances en amont. Les plugins optionnels peuvent inclure des dépendances, mais le cœur restera toujours léger et sécurisé. +- **Orienté IA :** La surcharge minimale de Flight et son architecture propre en font un choix idéal pour intégrer des outils et des API IA. Que vous construisiez des chatbots intelligents, des tableaux de bord pilotés par l'IA, ou que vous vouliez simplement expérimenter, Flight s'efface pour que vous puissiez vous concentrer sur l'essentiel. L'[application squelette](https://github.com/flightphp/skeleton) est livrée avec des fichiers d'instructions pré-construits pour les principaux assistants de codage IA dès la sortie de la boîte ! [En savoir plus sur l'utilisation de l'IA avec Flight](/learn/ai) -## Aperçu vidéo +## Aperçu Vidéo
          @@ -23,7 +25,7 @@ Flight est un framework rapide, simple et extensible pour PHP, conçu pour les d
          -## Démarrage rapide +## Démarrage Rapide Pour une installation rapide et basique, installez-le avec Composer : @@ -31,7 +33,7 @@ Pour une installation rapide et basique, installez-le avec Composer : composer require flightphp/core ``` -Ou vous pouvez télécharger un zip du dépôt [ici](https://github.com/flightphp/core). Ensuite, vous aurez un fichier `index.php` de base comme suit : +Ou vous pouvez télécharger un zip du dépôt [ici](https://github.com/flightphp/core). Ensuite, vous auriez un fichier `index.php` basique comme suit : ```php 8 causerait beaucoup de problèmes pour ces utilisateurs. Le framework prend aussi en charge PHP >8. +**Note :** PHP 7.4 est supporté car, au moment de la rédaction (2024), PHP 7.4 est la version par défaut pour certaines distributions Linux LTS. Forcer un passage à PHP >8 causerait beaucoup de problèmes pour ces utilisateurs. Le framework supporte aussi PHP >8. # Licence diff --git a/content/v3/fr/awesome-plugins/runway.md b/content/v3/fr/awesome-plugins/runway.md index 58a4279d..72e2f40e 100644 --- a/content/v3/fr/awesome-plugins/runway.md +++ b/content/v3/fr/awesome-plugins/runway.md @@ -6,7 +6,7 @@ Cliquez [ici](https://github.com/flightphp/runway) pour voir le code. ## Installation -Installez avec Composer. +Installez avec composer. ```bash composer require flightphp/runway @@ -29,18 +29,16 @@ return [ > **NOTE** - À partir de **v1.2.0**, `.runway-config.json` est déprécié. Veuillez migrer votre configuration vers `app/config/config.php`. Vous pouvez le faire facilement avec la commande `php runway config:migrate`. - - ### Détection de la Racine du Projet -Runway est suffisamment intelligent pour détecter la racine de votre projet, même si vous l'exécutez depuis un sous-répertoire. Il recherche des indicateurs comme `composer.json`, `.git`, ou `app/config/config.php` pour déterminer où se trouve la racine du projet. Cela signifie que vous pouvez exécuter les commandes Runway de n'importe où dans votre projet ! +Runway est assez intelligent pour détecter la racine de votre projet, même si vous l'exécutez depuis un sous-répertoire. Il recherche des indicateurs comme `composer.json`, `.git`, ou `app/config/config.php` pour déterminer où se trouve la racine du projet. Cela signifie que vous pouvez exécuter les commandes Runway depuis n'importe où dans votre projet ! ## Utilisation Runway dispose d'un certain nombre de commandes que vous pouvez utiliser pour gérer votre application Flight. Il y a deux façons faciles d'utiliser Runway. -1. Si vous utilisez le projet squelette, vous pouvez exécuter `php runway [commande]` depuis la racine de votre projet. -1. Si vous utilisez Runway en tant que package installé via Composer, vous pouvez exécuter `vendor/bin/runway [commande]` depuis la racine de votre projet. +1. Si vous utilisez le projet squelette, vous pouvez exécuter `php runway [command]` depuis la racine de votre projet. +1. Si vous utilisez Runway en tant que package installé via composer, vous pouvez exécuter `vendor/bin/runway [command]` depuis la racine de votre projet. ### Liste des Commandes @@ -62,7 +60,7 @@ Voici quelques exemples : ### Générer un Contrôleur -Basé sur la configuration dans `runway.app_root`, l'emplacement générera un contrôleur pour vous dans le répertoire `app/controllers/`. +En se basant sur la configuration dans `runway.app_root`, l'emplacement générera un contrôleur pour vous dans le répertoire `app/controllers/`. ```bash php runway make:controller MyController @@ -70,13 +68,13 @@ php runway make:controller MyController ### Générer un Modèle Active Record -Assurez-vous d'abord d'avoir installé le plugin [Active Record](/awesome-plugins/active-record). Basé sur la configuration dans `runway.app_root`, l'emplacement générera un enregistrement pour vous dans le répertoire `app/records/`. +Assurez-vous d'abord d'avoir installé le plugin [Active Record](/awesome-plugins/active-record). En se basant sur la configuration dans `runway.app_root`, l'emplacement générera un enregistrement pour vous dans le répertoire `app/records/`. ```bash php runway make:record users ``` -Si, par exemple, vous avez la table `users` avec le schéma suivant : `id`, `name`, `email`, `created_at`, `updated_at`, un fichier similaire à celui-ci sera créé dans le fichier `app/records/UserRecord.php` : +Si, par exemple, vous avez la table `users` avec le schéma suivant : `id`, `name`, `email`, `created_at`, `updated_at`, un fichier similaire au suivant sera créé dans le fichier `app/records/UserRecord.php` : ```php [ - // C'est l'endroit où se trouve votre répertoire d'application + // C'est là que se trouve votre répertoire d'application 'app_root' => 'app/', // C'est le répertoire où se trouve votre fichier index racine @@ -233,9 +231,9 @@ return [ '/var/www/another-project' ], - // Les chemins de base n'ont probablement pas besoin d'être configurés, mais ils sont là si vous en voulez + // Les chemins de base n'ont probablement pas besoin d'être configurés, mais ils sont là si vous le souhaitez 'base_paths' => [ - '/includes/libs/vendor', // si vous avez un chemin vraiment unique pour votre répertoire vendor ou autre + '/includes/libs/vendor', // si vous avez un chemin vraiment unique pour votre répertoire vendor ou quelque chose ], // Les chemins finaux sont des emplacements dans un projet pour rechercher les fichiers de commande @@ -244,7 +242,7 @@ return [ 'app/module/admin/commands', ], - // Si vous voulez simplement ajouter le chemin complet, allez-y (absolu ou relatif à la racine du projet) + // Si vous voulez juste ajouter le chemin complet, allez-y (absolu ou relatif à la racine du projet) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -256,7 +254,7 @@ return [ ### Accéder à la Configuration -Si vous devez accéder efficacement aux valeurs de configuration, vous pouvez les accéder via la méthode `__construct` ou la méthode `app()`. Il est également important de noter que si vous avez un fichier `app/config/services.php`, ces services seront également disponibles pour votre commande. +Si vous avez besoin d'accéder efficacement aux valeurs de configuration, vous pouvez y accéder via la méthode `__construct` ou la méthode `app()`. Il est également important de noter que si vous avez un fichier `app/config/services.php`, ces services seront également disponibles pour votre commande. ```php public function execute() @@ -273,9 +271,9 @@ public function execute() } ``` -## Enveloppeurs d'Assistance IA +## Enveloppes d'Aide IA -Runway dispose de quelques enveloppeurs d'assistance qui facilitent la génération de commandes par l'IA. Vous pouvez utiliser `addOption` et `addArgument` de manière similaire à Symfony Console. C'est utile si vous utilisez des outils d'IA pour générer vos commandes. +Runway dispose de quelques enveloppes d'aide qui facilitent la génération de commandes par l'IA. Vous pouvez utiliser `addOption` et `addArgument` d'une manière qui ressemble à Symfony Console. Cela est utile si vous utilisez des outils IA pour générer vos commandes. ```php public function __construct(array $config) diff --git a/content/v3/fr/learn/ai.md b/content/v3/fr/learn/ai.md index bc668ec6..16091cf0 100644 --- a/content/v3/fr/learn/ai.md +++ b/content/v3/fr/learn/ai.md @@ -2,14 +2,14 @@ ## Aperçu -Flight facilite le renforcement de vos projets PHP avec des outils alimentés par l'IA et des flux de travail modernes pour les développeurs. Avec des commandes intégrées pour se connecter aux fournisseurs de LLM (Large Language Model) et générer des instructions de codage IA spécifiques au projet, Flight vous aide, vous et votre équipe, à tirer le meilleur parti des assistants IA comme GitHub Copilot, Cursor, Windsurf et Antigravity (Gemini). +Flight facilite le renforcement de vos projets PHP avec des outils alimentés par l'IA et des flux de travail modernes pour les développeurs. Avec des commandes intégrées pour se connecter à des fournisseurs de LLM (Large Language Model) et générer des instructions de codage IA spécifiques au projet, Flight vous aide, vous et votre équipe, à tirer le meilleur parti des assistants IA comme GitHub Copilot, Cursor, Windsurf et Antigravity (Gemini). ## Compréhension -Les assistants de codage IA sont les plus utiles lorsqu'ils comprennent le contexte, les conventions et les objectifs de votre projet. Les aides IA de Flight vous permettent de : +Les assistants de codage IA sont les plus utiles lorsqu'ils comprennent le contexte, les conventions et les objectifs de votre projet. Les helpers IA de Flight vous permettent de : - Connecter votre projet à des fournisseurs de LLM populaires (OpenAI, Grok, Claude, etc.) - Générer et mettre à jour des instructions spécifiques au projet pour les outils IA, afin que tout le monde obtienne une aide cohérente et pertinente -- Maintenir votre équipe alignée et productive, avec moins de temps passé à expliquer le contexte +- Garder votre équipe alignée et productive, avec moins de temps passé à expliquer le contexte Ces fonctionnalités sont intégrées au CLI principal de Flight et au projet de démarrage officiel [flightphp/skeleton](https://github.com/flightphp/skeleton). @@ -17,7 +17,7 @@ Ces fonctionnalités sont intégrées au CLI principal de Flight et au projet de ### Configuration des Identifiants LLM -La commande `ai:init` vous guide pour connecter votre projet à un fournisseur de LLM. +La commande `ai:init` vous guide à travers la connexion de votre projet à un fournisseur de LLM. ```bash php runway ai:init @@ -28,16 +28,16 @@ Vous serez invité à : - Entrer votre clé API - Définir l'URL de base et le nom du modèle -Cela crée les identifiants nécessaires pour effectuer de futures requêtes LLM. +Cela crée les identifiants nécessaires pour effectuer des requêtes LLM futures. **Exemple :** ``` -Bienvenue dans AI Init ! -Quel API LLM voulez-vous utiliser ? [1] openai, [2] grok, [3] claude : 1 -Entrez l'URL de base pour l'API LLM [https://api.openai.com] : -Entrez votre clé API pour openai : sk-... -Entrez le nom du modèle que vous voulez utiliser (ex. gpt-4, claude-3-opus, etc) [gpt-4o] : -Identifiants sauvegardés dans .runway-creds.json +Welcome to AI Init! +Which LLM API do you want to use? [1] openai, [2] grok, [3] claude: 1 +Enter the base URL for the LLM API [https://api.openai.com]: +Enter your API key for openai: sk-... +Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: +Credentials saved to .runway-creds.json ``` ### Génération d'Instructions IA Spécifiques au Projet @@ -48,7 +48,7 @@ La commande `ai:generate-instructions` vous aide à créer ou mettre à jour des php runway ai:generate-instructions ``` -Vous répondrez à quelques questions sur votre projet (description, base de données, templating, sécurité, taille de l'équipe, etc.). Flight utilise votre fournisseur de LLM pour générer les instructions, puis les écrit dans : +Vous répondrez à quelques questions sur votre projet (description, base de données, templating, sécurité, taille de l'équipe, etc.). Flight utilise votre fournisseur de LLM pour générer des instructions, puis les écrit dans : - `.github/copilot-instructions.md` (pour GitHub Copilot) - `.cursor/rules/project-overview.mdc` (pour Cursor) - `.windsurfrules` (pour Windsurf) @@ -56,20 +56,20 @@ Vous répondrez à quelques questions sur votre projet (description, base de don **Exemple :** ``` -Veuillez décrire à quoi sert votre projet ? Mon API géniale -Quelle base de données prévoyez-vous d'utiliser ? MySQL -Quel moteur de templating HTML prévoyez-vous d'utiliser (si applicable) ? latte -La sécurité est-elle un élément important de ce projet ? (o/n) o +Please describe what your project is for? My awesome API +What database are you planning on using? MySQL +What HTML templating engine will you plan on using (if any)? latte +Is security an important element of this project? (y/n) y ... -Instructions IA mises à jour avec succès. +AI instructions updated successfully. ``` -Désormais, vos outils IA fourniront des suggestions plus intelligentes et plus pertinentes basées sur les besoins réels de votre projet. +Maintenant, vos outils IA fourniront des suggestions plus intelligentes et plus pertinentes basées sur les besoins réels de votre projet. ## Utilisation Avancée - Vous pouvez personnaliser l'emplacement de vos fichiers d'identifiants ou d'instructions en utilisant des options de commande (voir `--help` pour chaque commande). -- Les aides IA sont conçues pour fonctionner avec n'importe quel fournisseur de LLM qui prend en charge les API compatibles avec OpenAI. +- Les helpers IA sont conçus pour fonctionner avec n'importe quel fournisseur de LLM qui prend en charge les API compatibles avec OpenAI. - Si vous souhaitez mettre à jour vos instructions au fur et à mesure que votre projet évolue, relancez simplement `ai:generate-instructions` et répondez aux invites à nouveau. ## Voir Aussi diff --git a/content/v3/id/about.md b/content/v3/id/about.md index 78515827..9909996d 100644 --- a/content/v3/id/about.md +++ b/content/v3/id/about.md @@ -1,14 +1,16 @@ -# Kerangka Kerja PHP Flight +# Flight PHP Framework -Flight adalah kerangka kerja yang cepat, sederhana, dan dapat diperluas untuk PHP—dibuat untuk pengembang yang ingin menyelesaikan pekerjaan dengan cepat, tanpa keributan. Baik Anda membangun aplikasi web klasik, API yang sangat cepat, atau bereksperimen dengan alat-alat terkini yang didukung AI, jejak rendah dan desain langsung Flight membuatnya cocok sempurna. Flight dimaksudkan untuk ringan, tetapi juga dapat menangani kebutuhan arsitektur perusahaan. +Flight adalah framework PHP yang cepat, sederhana, dan dapat diperluas—dibangun untuk pengembang yang ingin menyelesaikan pekerjaan dengan cepat, tanpa kerumitan. Baik Anda membangun aplikasi web klasik, API yang sangat cepat, atau bereksperimen dengan alat berbasis AI terbaru, jejak rendah dan desain sederhana Flight membuatnya cocok sempurna. Flight dirancang untuk tetap ramping, tetapi juga dapat menangani persyaratan arsitektur enterprise. ## Mengapa Memilih Flight? -- **Pemula Ramah:** Flight adalah titik awal yang bagus untuk pengembang PHP baru. Struktur yang jelas dan sintaks sederhana membantu Anda belajar pengembangan web tanpa tersesat dalam boilerplate. -- **Disukai oleh Profesional:** Pengembang berpengalaman mencintai Flight karena fleksibilitas dan kontrolnya. Anda dapat mengembangkan dari prototipe kecil hingga aplikasi lengkap tanpa berganti kerangka kerja. -- **Ramah AI:** Beban minimal dan arsitektur bersih Flight membuatnya ideal untuk mengintegrasikan alat dan API AI. Baik Anda membangun chatbot pintar, dasbor yang didukung AI, atau hanya ingin bereksperimen, Flight tidak menghalangi sehingga Anda dapat fokus pada hal yang penting. Aplikasi [skeleton app](https://github.com/flightphp/skeleton) dilengkapi dengan file instruksi yang sudah dibuat sebelumnya untuk asisten pengkodean AI utama langsung dari kotak! [Pelajari lebih lanjut tentang menggunakan AI dengan Flight](/learn/ai) +- **Ramah Pemula:** Flight adalah titik awal yang bagus untuk pengembang PHP baru. Strukturnya yang jelas dan sintaks sederhana membantu Anda belajar pengembangan web tanpa tersesat dalam kode boilerplate. +- **Disukai oleh Profesional:** Pengembang berpengalaman menyukai Flight karena fleksibilitas dan kendalinya. Anda dapat menskalakan dari prototipe kecil hingga aplikasi lengkap tanpa harus mengganti framework. +- **Kompatibel ke Belakang:** Kami menghargai waktu Anda. Flight v3 adalah peningkatan dari v2, mempertahankan hampir seluruh API yang sama. Kami percaya pada evolusi, bukan revolusi—tidak ada lagi "merusak dunia" setiap kali versi utama dirilis. +- **Tanpa Dependensi:** Inti Flight sepenuhnya bebas dependensi—tidak ada polyfills, tidak ada paket eksternal, bahkan tidak ada antarmuka PSR. Ini berarti lebih sedikit vektor serangan, jejak yang lebih kecil, dan tidak ada perubahan pemecah yang mengejutkan dari dependensi hulu. Plugin opsional mungkin menyertakan dependensi, tetapi inti akan selalu tetap ramping dan aman. +- **Berfokus pada AI:** Overhead minimal dan arsitektur bersih Flight membuatnya ideal untuk mengintegrasikan alat dan API AI. Baik Anda membangun chatbot pintar, dashboard berbasis AI, atau hanya ingin bereksperimen, Flight tidak menghalangi sehingga Anda dapat fokus pada hal yang penting. Aplikasi [skeleton](https://github.com/flightphp/skeleton) dilengkapi dengan file instruksi pra-bangun untuk asisten pengkodean AI utama langsung dari kotak! [Pelajari lebih lanjut tentang menggunakan AI dengan Flight](/learn/ai) -## Ikhtisar Video +## Video Overview
          @@ -16,16 +18,16 @@ Flight adalah kerangka kerja yang cepat, sederhana, dan dapat diperluas untuk PH
          - Cukup sederhana, kan? + Cukup sederhana, bukan?
          - Pelajari lebih lanjut tentang Flight dalam dokumentasi! + Pelajari lebih lanjut tentang Flight di dokumentasi!
          -## Mulai Cepat +## Quick Start -Untuk instalasi dasar yang cepat, instal dengan Composer: +Untuk instalasi cepat tanpa tambahan, instal dengan Composer: ```bash composer require flightphp/core @@ -36,9 +38,9 @@ Atau Anda dapat mengunduh zip dari repo [di sini](https://github.com/flightphp/c ```php 8 akan menimbulkan masalah bagi pengguna tersebut. Kerangka kerja juga mendukung PHP >8. +**Catatan:** PHP 7.4 didukung karena pada saat penulisan ini (2024) PHP 7.4 adalah versi default untuk beberapa distribusi Linux LTS. Memaksa perpindahan ke PHP >8 akan menyebabkan banyak masalah bagi pengguna tersebut. Framework juga mendukung PHP >8. -# Lisensi +# License -Flight dirilis di bawah [lisensi MIT](https://github.com/flightphp/core/blob/master/LICENSE). \ No newline at end of file +Flight dirilis di bawah lisensi [MIT](https://github.com/flightphp/core/blob/master/LICENSE). \ No newline at end of file diff --git a/content/v3/id/awesome-plugins/runway.md b/content/v3/id/awesome-plugins/runway.md index 6e448b52..08b17983 100644 --- a/content/v3/id/awesome-plugins/runway.md +++ b/content/v3/id/awesome-plugins/runway.md @@ -1,6 +1,6 @@ # Runway -Runway adalah aplikasi CLI yang membantu Anda mengelola aplikasi Flight Anda. Ini dapat menghasilkan controller, menampilkan semua rute, dan banyak lagi. Ini didasarkan pada pustaka [adhocore/php-cli](https://github.com/adhocore/php-cli) yang sangat baik. +Runway adalah aplikasi CLI yang membantu Anda mengelola aplikasi Flight Anda. Ini dapat menghasilkan controller, menampilkan semua rute, dan banyak lagi. Ini didasarkan pada pustaka [adhocore/php-cli](https://github.com/adhocore/php-cli) yang luar biasa. Klik [di sini](https://github.com/flightphp/runway) untuk melihat kode. @@ -29,18 +29,16 @@ return [ > **CATATAN** - Mulai dari **v1.2.0**, `.runway-config.json` sudah tidak digunakan lagi. Silakan migrasikan konfigurasi Anda ke `app/config/config.php`. Anda dapat melakukan ini dengan mudah menggunakan perintah `php runway config:migrate`. +### Deteksi Akar Proyek - -### Deteksi Root Proyek - -Runway cukup pintar untuk mendeteksi root proyek Anda, bahkan jika Anda menjalankannya dari subdirektori. Ini mencari indikator seperti `composer.json`, `.git`, atau `app/config/config.php` untuk menentukan di mana root proyek berada. Ini berarti Anda dapat menjalankan perintah Runway dari mana saja di proyek Anda! +Runway cukup pintar untuk mendeteksi akar proyek Anda, bahkan jika Anda menjalankannya dari subdirektori. Ini mencari indikator seperti `composer.json`, `.git`, atau `app/config/config.php` untuk menentukan di mana akar proyek berada. Ini berarti Anda dapat menjalankan perintah Runway dari mana saja di proyek Anda! ## Penggunaan Runway memiliki sejumlah perintah yang dapat Anda gunakan untuk mengelola aplikasi Flight Anda. Ada dua cara mudah untuk menggunakan Runway. -1. Jika Anda menggunakan proyek skeleton, Anda dapat menjalankan `php runway [command]` dari root proyek Anda. -1. Jika Anda menggunakan Runway sebagai paket yang diinstal melalui composer, Anda dapat menjalankan `vendor/bin/runway [command]` dari root proyek Anda. +1. Jika Anda menggunakan proyek skeleton, Anda dapat menjalankan `php runway [command]` dari akar proyek Anda. +1. Jika Anda menggunakan Runway sebagai paket yang diinstal melalui composer, Anda dapat menjalankan `vendor/bin/runway [command]` dari akar proyek Anda. ### Daftar Perintah @@ -52,7 +50,7 @@ php runway ### Bantuan Perintah -Untuk perintah apa pun, Anda dapat memberikan flag `--help` untuk mendapatkan informasi lebih lanjut tentang cara menggunakan perintah tersebut. +Untuk perintah apa pun, Anda dapat meneruskan flag `--help` untuk mendapatkan informasi lebih lanjut tentang cara menggunakan perintah tersebut. ```bash php runway routes --help @@ -94,20 +92,20 @@ namespace app\records; * @property string $email * @property string $created_at * @property string $updated_at - * // you could also add relationships here once you define them in the $relations array - * @property CompanyRecord $company Example of a relationship + * // Anda juga bisa menambahkan hubungan di sini setelah mendefinisikannya di array $relations + * @property CompanyRecord $company Contoh hubungan */ class UserRecord extends \flight\ActiveRecord { /** - * @var array $relations Set the relationships for the model + * @var array $relations Atur hubungan untuk model * https://docs.flightphp.com/awesome-plugins/active-record#relationships */ protected array $relations = []; /** - * Constructor - * @param mixed $databaseConnection The connection to the database + * Konstruktor + * @param mixed $databaseConnection Koneksi ke database */ public function __construct($databaseConnection) { @@ -124,16 +122,16 @@ Ini akan menampilkan semua rute yang saat ini terdaftar dengan Flight. php runway routes ``` -Jika Anda ingin hanya melihat rute tertentu, Anda dapat memberikan flag untuk memfilter rute. +Jika Anda ingin hanya melihat rute tertentu, Anda dapat meneruskan flag untuk memfilter rute. ```bash -# Menampilkan hanya rute GET +# Tampilkan hanya rute GET php runway routes --get -# Menampilkan hanya rute POST +# Tampilkan hanya rute POST php runway routes --post -# dll. +# dst. ``` ## Menambahkan Perintah Kustom ke Runway @@ -152,18 +150,18 @@ namespace flight\commands; class ExampleCommand extends AbstractBaseCommand { /** - * Construct + * Konstruktor * - * @param array $config Config from app/config/config.php + * @param array $config Konfigurasi dari app/config/config.php */ public function __construct(array $config) { - parent::__construct('make:example', 'Create an example for the documentation', $config); - $this->argument('', 'The name of the funny gif'); + parent::__construct('make:example', 'Buat contoh untuk dokumentasi', $config); + $this->argument('', 'Nama dari gif lucu'); } /** - * Executes the function + * Menjalankan fungsi * * @return void */ @@ -171,11 +169,11 @@ class ExampleCommand extends AbstractBaseCommand { $io = $this->app()->io(); - $io->info('Creating example...'); + $io->info('Membuat contoh...'); - // Do something here + // Lakukan sesuatu di sini - $io->ok('Example created!'); + $io->ok('Contoh dibuat!'); } } ``` @@ -184,7 +182,7 @@ Lihat [Dokumentasi adhocore/php-cli](https://github.com/adhocore/php-cli) untuk ## Manajemen Konfigurasi -Karena konfigurasi telah dipindahkan ke `app/config/config.php` mulai dari `v1.2.0`, ada beberapa perintah bantu untuk mengelola konfigurasi. +Karena konfigurasi telah dipindahkan ke `app/config/config.php` mulai dari `v1.2.0`, ada beberapa perintah pembantu untuk mengelola konfigurasi. ### Migrasi Konfigurasi Lama @@ -218,33 +216,33 @@ Jika Anda perlu menyesuaikan konfigurasi untuk Runway, Anda dapat mengatur nilai [ - // This is where your application directory is located + // Ini adalah lokasi direktori aplikasi Anda 'app_root' => 'app/', - // This is the directory where your root index file is located + // Ini adalah direktori di mana file index akar Anda berada 'index_root' => 'public/', - // These are the paths to the roots of other projects + // Ini adalah path ke akar proyek lain 'root_paths' => [ '/home/user/different-project', '/var/www/another-project' ], - // Base paths most likely don't need to be configured, but it's here if you want it + // Path dasar kemungkinan besar tidak perlu dikonfigurasi, tapi ini ada jika Anda menginginkannya 'base_paths' => [ - '/includes/libs/vendor', // if you have a really unique path for your vendor directory or something + '/includes/libs/vendor', // jika Anda memiliki path yang sangat unik untuk direktori vendor atau semacamnya ], - // Final paths are locations within a project to search for the command files + // Path akhir adalah lokasi dalam proyek untuk mencari file perintah 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // If you want to just add the full path, go right ahead (absolute or relative to project root) + // Jika Anda ingin menambahkan path lengkap, silakan (absolut atau relatif terhadap akar proyek) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -263,26 +261,26 @@ public function execute() { $io = $this->app()->io(); - // Access configuration + // Akses konfigurasi $app_root = $this->config['runway']['app_root']; - // Access services like maybe a database connection + // Akses layanan seperti mungkin koneksi database $database = $this->config['database'] // ... } ``` -## Wrapper Bantu AI +## Wrapper Pembantu AI -Runway memiliki beberapa wrapper bantu yang memudahkan AI untuk menghasilkan perintah. Anda dapat menggunakan `addOption` dan `addArgument` dengan cara yang mirip dengan Symfony Console. Ini membantu jika Anda menggunakan alat AI untuk menghasilkan perintah Anda. +Runway memiliki beberapa wrapper pembantu yang membuat lebih mudah bagi AI untuk menghasilkan perintah. Anda dapat menggunakan `addOption` dan `addArgument` dengan cara yang mirip dengan Symfony Console. Ini membantu jika Anda menggunakan alat AI untuk menghasilkan perintah Anda. ```php public function __construct(array $config) { - parent::__construct('make:example', 'Create an example for the documentation', $config); + parent::__construct('make:example', 'Buat contoh untuk dokumentasi', $config); - // The mode argument is nullable and defaults to completely optional - $this->addOption('name', 'The name of the example', null); + // Argumen mode bersifat nullable dan defaultnya sepenuhnya opsional + $this->addOption('name', 'Nama dari contoh', null); } ``` \ No newline at end of file diff --git a/content/v3/id/learn/ai.md b/content/v3/id/learn/ai.md index 629a603c..a59376dc 100644 --- a/content/v3/id/learn/ai.md +++ b/content/v3/id/learn/ai.md @@ -2,7 +2,7 @@ ## Gambaran Umum -Flight memudahkan Anda untuk meningkatkan proyek PHP Anda dengan alat berbasis AI dan alur kerja pengembang modern. Dengan perintah bawaan untuk terhubung ke penyedia LLM (Large Language Model) dan menghasilkan instruksi pengkodean AI khusus proyek, Flight membantu Anda dan tim Anda mendapatkan manfaat maksimal dari asisten AI seperti GitHub Copilot, Cursor, Windsurf, dan Antigravity (Gemini). +Flight memudahkan Anda untuk meningkatkan proyek PHP Anda dengan alat berbasis AI dan alur kerja pengembang modern. Dengan perintah bawaan untuk terhubung ke penyedia LLM (Large Language Model) dan menghasilkan instruksi pengkodean AI khusus proyek, Flight membantu Anda dan tim Anda memanfaatkan maksimal asisten AI seperti GitHub Copilot, Cursor, Windsurf, dan Antigravity (Gemini). ## Pemahaman @@ -15,9 +15,9 @@ Fitur-fitur ini dibangun ke dalam CLI inti Flight dan proyek starter resmi [flig ## Penggunaan Dasar -### Mengatur Kredensial LLM +### Menyiapkan Kredensial LLM -Perintah `ai:init` akan memandu Anda melalui proses menghubungkan proyek Anda ke penyedia LLM. +Perintah `ai:init` memandu Anda melalui proses menghubungkan proyek Anda ke penyedia LLM. ```bash php runway ai:init @@ -42,7 +42,7 @@ Credentials saved to .runway-creds.json ### Menghasilkan Instruksi AI Khusus Proyek -Perintah `ai:generate-instructions` membantu Anda membuat atau memperbarui instruksi untuk asisten pengkodean AI, yang disesuaikan dengan proyek Anda. +Perintah `ai:generate-instructions` membantu Anda membuat atau memperbarui instruksi untuk asisten pengkodean AI, disesuaikan dengan proyek Anda. ```bash php runway ai:generate-instructions @@ -64,7 +64,7 @@ Is security an important element of this project? (y/n) y AI instructions updated successfully. ``` -Sekarang, alat AI Anda akan memberikan saran yang lebih pintar dan lebih relevan berdasarkan kebutuhan nyata proyek Anda. +Sekarang, alat AI Anda akan memberikan saran yang lebih cerdas dan relevan berdasarkan kebutuhan nyata proyek Anda. ## Penggunaan Lanjutan @@ -85,4 +85,4 @@ Sekarang, alat AI Anda akan memberikan saran yang lebih pintar dan lebih relevan ## Changelog -- v3.16.0 – Menambahkan perintah CLI `ai:init` dan `ai:generate-instructions` untuk integrasi AI. \ No newline at end of file +- v3.16.0 – Ditambahkan perintah CLI `ai:init` dan `ai:generate-instructions` untuk integrasi AI. \ No newline at end of file diff --git a/content/v3/ja/about.md b/content/v3/ja/about.md index 7601e190..7d8f4467 100644 --- a/content/v3/ja/about.md +++ b/content/v3/ja/about.md @@ -1,14 +1,16 @@ -# Flight PHP フレームワーク +# Flight PHP Framework -Flight は、速く、シンプルで、拡張可能な PHP フレームワークです。開発者が素早く作業を完了させ、一切の面倒なことを避けたい場合に最適です。クラシックな Web アプリ、超高速 API、または最新の AI 駆動ツールの実験を行う場合、Flight の低負荷でシンプルな設計はぴったりです。Flight は軽量に設計されていますが、エンタープライズアーキテクチャの要件にも対応可能です。 +Flight は、迅速に作業を進めたい開発者向けに構築された、速く、シンプルで拡張可能な PHP フレームワークです。面倒なことは一切なし。クラシックなウェブアプリ、超高速 API、または最新の AI 駆動ツールの実験など、どのような用途でも、Flight の小さなフットプリントとストレートな設計がぴったりです。Flight はスリムを志向していますが、エンタープライズアーキテクチャの要件にも対応可能です。 -## Flight を選ぶ理由? +## Flight を選ぶ理由は? -- **初心者向け:** Flight は新しい PHP 開発者にとって素晴らしい出発点です。明確な構造とシンプルな構文により、余計なコードに迷うことなく Web 開発を学べます。 -- **プロが愛用:** 経験豊富な開発者は、Flight の柔軟性と制御性を好みます。小さなプロトタイプからフル機能のアプリまでスケールアップでき、フレームワークを切り替える必要はありません。 -- **AI 向け:** Flight の最小限のオーバーヘッドとクリーンなアーキテクチャは、AI ツールと API の統合に理想的です。スマートチャットボット、AI 駆動ダッシュボードの実装、または実験を行う場合、Flight は邪魔をせずに本質に集中できます。 [skeleton app](https://github.com/flightphp/skeleton) には、主要な AI コーディングアシスタント向けの事前構築済み指示ファイルが最初から含まれています! [AI を使用した Flight の詳細について学ぶ](/learn/ai) +- **初心者向け:** Flight は新しい PHP 開発者の優れたスタート地点です。その明確な構造とシンプルな構文により、ボイラープレートに迷子になることなくウェブ開発を学べます。 +- **プロに愛される:** 経験豊富な開発者は、Flight の柔軟性と制御性を愛しています。小さなプロトタイプからフル機能のアプリまでスケールアップでき、フレームワークの切り替えは不要です。 +- **後方互換性:** あなたの時間を大切にします。Flight v3 は v2 の拡張版で、ほぼすべての API を維持しています。私たちは進化を信じ、革命を起こしません。主要バージョンのリリースごとに「世界を壊す」ようなことはありません。 +- **ゼロ依存:** Flight のコアは完全に依存関係フリーです。ポリフィルなし、外部パッケージなし、PSR インターフェースさえありません。これにより、攻撃ベクターが少なくなり、フットプリントが小さく、上流依存からの予期せぬ破壊的変更もありません。オプションのプラグインに依存関係が含まれる場合もありますが、コアは常にスリムでセキュアです。 +- **AI 指向:** Flight の最小限のオーバーヘッドとクリーンなアーキテクチャは、AI ツールや API の統合に理想的です。スマートチャットボット、AI 駆動ダッシュボードの構築、または単なる実験など、Flight は邪魔にならず、重要なことに集中できます。[skeleton app](https://github.com/flightphp/skeleton) には、主要な AI コーディングアシスタント向けのプリビルド指示ファイルが最初から含まれています! [Flight での AI の使用について詳しく学ぶ](/learn/ai) -## ビデオ概要 +## Video Overview
          @@ -16,29 +18,29 @@ Flight は、速く、シンプルで、拡張可能な PHP フレームワー
          - シンプルですよね? + シンプルでしょ?
          - 詳細を学ぶ ドキュメントで Flight について! + ドキュメントで Flight について詳しく学ぶ
          -## クイックスタート +## Quick Start -素早い最小限のインストールを行うには、Composer でインストールしてください: +高速なベアボーンインストールを行うには、Composer でインストールしてください: ```bash composer require flightphp/core ``` -または、リポジトリの ZIP を [こちら](https://github.com/flightphp/core) からダウンロードできます。その場合、基本的な `index.php` ファイルは次のようになります: +または、リポジトリの zip を [ここ](https://github.com/flightphp/core) からダウンロードできます。その後、以下の基本的な `index.php` ファイルを作成します: ```php 8 への移行を強制すると、ユーザーに問題を引き起こす可能性があるためです。フレームワークは PHP >8 もサポートしています。 +**Note:** PHP 7.4 はサポートされています。なぜなら、執筆時点(2024 年)で一部の LTS Linux ディストリビューションのデフォルトバージョンが PHP 7.4 だからです。PHP >8 への強制移行は、そうしたユーザーにとって大きな負担となります。フレームワークは PHP >8 もサポートします。 -# ライセンス +# License Flight は [MIT](https://github.com/flightphp/core/blob/master/LICENSE) ライセンスでリリースされています。 \ No newline at end of file diff --git a/content/v3/ja/awesome-plugins/runway.md b/content/v3/ja/awesome-plugins/runway.md index bdf3c7c0..dc91d46e 100644 --- a/content/v3/ja/awesome-plugins/runway.md +++ b/content/v3/ja/awesome-plugins/runway.md @@ -1,12 +1,12 @@ # Runway -Runway は、Flight アプリケーションを管理するための CLI アプリケーションです。コントローラーの生成、すべてのルートの表示などを行えます。[adhocore/php-cli](https://github.com/adhocore/php-cli) ライブラリを基にしています。 +Runway は、Flight アプリケーションを管理するのに役立つ CLI アプリケーションです。コントローラーを生成したり、すべてのルートを表示したり、その他さまざまな機能を提供します。これは優れた [adhocore/php-cli](https://github.com/adhocore/php-cli) ライブラリを基にしています。 -コードを表示するには [こちら](https://github.com/flightphp/runway) をクリックしてください。 +コードを見るには [ここ](https://github.com/flightphp/runway) をクリックしてください。 ## インストール -Composer を使用してインストールします。 +Composer でインストールします。 ```bash composer require flightphp/runway @@ -14,7 +14,7 @@ composer require flightphp/runway ## 基本設定 -Runway を初めて実行すると、`app/config/config.php` 内の `'runway'` キーから `runway` 設定を探します。 +Runway を初めて実行すると、`app/config/config.php` の `'runway'` キー経由で `runway` 設定を探そうとします。 ```php **注意** - **v1.2.0** 以降、`.runway-config.json` は非推奨です。設定を `app/config/config.php` に移行してください。`php runway config:migrate` コマンドで簡単に実行できます。 - - +> **注意** - **v1.2.0** 以降、`.runway-config.json` は非推奨です。設定を `app/config/config.php` に移行してください。`php runway config:migrate` コマンドで簡単に移行できます。 ### プロジェクトルートの検出 -Runway は、プロジェクトのルートを検出するのに十分賢いです。サブディレクトリから実行した場合でも、`composer.json`、`.git`、または `app/config/config.php` などの指標を探してプロジェクトルートを決定します。これにより、プロジェクト内のどこからでも Runway コマンドを実行できます! +Runway は、プロジェクトのルートを検出するのに十分賢いです。サブディレクトリから実行した場合でも、`composer.json`、`.git`、または `app/config/config.php` などの指標を探してプロジェクトルートを決定します。これにより、プロジェクト内のどこからでも Runway コマンドを実行できます! ## 使用方法 -Runway には、Flight アプリケーションを管理するためのいくつかのコマンドがあります。Runway を使用する簡単な方法は 2 つあります。 +Runway には、Flight アプリケーションを管理するためのさまざまなコマンドがあります。Runway を使用する簡単な方法は 2 つあります。 1. スケルトンプロジェクトを使用している場合、プロジェクトのルートから `php runway [command]` を実行できます。 -1. Composer を介してインストールしたパッケージとして Runway を使用している場合、プロジェクトのルートから `vendor/bin/runway [command]` を実行できます。 +1. Composer 経由でインストールしたパッケージとして Runway を使用している場合、プロジェクトのルートから `vendor/bin/runway [command]` を実行できます。 ### コマンドリスト @@ -52,13 +50,13 @@ php runway ### コマンドヘルプ -任意のコマンドに対して、`--help` フラグを渡すことでコマンドの使用方法についての詳細情報を取得できます。 +任意のコマンドに対して、`--help` フラグを渡すことでコマンドの使用方法に関する詳細情報を取得できます。 ```bash php runway routes --help ``` -以下にいくつかの例を示します: +以下にいくつかの例を示します。 ### コントローラーの生成 @@ -70,13 +68,13 @@ php runway make:controller MyController ### Active Record モデルの生成 -まず [Active Record](/awesome-plugins/active-record) プラグインをインストールしていることを確認してください。`runway.app_root` の設定に基づいて、`app/records/` ディレクトリにレコードを生成します。 +まず [Active Record](/awesome-plugins/active-record) プラグインをインストールしたことを確認してください。`runway.app_root` の設定に基づいて、`app/records/` ディレクトリにレコードを生成します。 ```bash php runway make:record users ``` -たとえば、`users` テーブルに `id`、`name`、`email`、`created_at`、`updated_at` のスキーマがある場合、`app/records/UserRecord.php` ファイルに以下のようないくつかのファイルが作成されます: +例えば、`users` テーブルに以下のスキーマがある場合:`id`、`name`、`email`、`created_at`、`updated_at`、`app/records/UserRecord.php` ファイルに以下の類似したファイルが作成されます: ```php [ - // アプリケーション ディレクトリの場所 + // アプリケーション ディレクトリが所在する場所 'app_root' => 'app/', - // ルート index ファイルの場所のディレクトリ + // ルートインデックスファイルが所在するディレクトリ 'index_root' => 'public/', - // 他のプロジェクトのルートの経路 + // 他のプロジェクトのルートへのパス 'root_paths' => [ '/home/user/different-project', '/var/www/another-project' ], - // 基本経路は通常設定する必要はありませんが、必要に応じて使用 + // ベースパスは通常設定する必要はありませんが、必要に応じて使用できます 'base_paths' => [ - '/includes/libs/vendor', // vendor ディレクトリなどに独自の経路がある場合 + '/includes/libs/vendor', // vendor ディレクトリの特殊なパスがある場合など ], - // 最終経路は、プロジェクト内のコマンドファイルを探す場所 + // 最終パスは、コマンドファイルを検索するプロジェクト内の場所 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // 完全な経路を追加したい場合(プロジェクトルートからの絶対または相対) + // フルパスを追加したい場合、プロジェクトルートからの絶対パスまたは相対パスで指定できます 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -256,7 +254,7 @@ return [ ### 設定へのアクセス -設定値に効果的にアクセスする必要がある場合、`__construct` メソッドまたは `app()` メソッド経由でアクセスできます。また、`app/config/services.php` ファイルがある場合、そのサービスもコマンドで利用可能です。 +設定値に効果的にアクセスする必要がある場合、`__construct` メソッドまたは `app()` メソッド経由でアクセスできます。また、`app/config/services.php` ファイルがある場合、そのサービスもコマンドで利用可能であることに注意してください。 ```php public function execute() @@ -275,7 +273,7 @@ public function execute() ## AI ヘルパー ラッパー -Runway には、AI がコマンドを生成しやすくするためのヘルパー ラッパーがあります。Symfony Console に似た方法で `addOption` および `addArgument` を使用できます。AI ツールを使用してコマンドを生成する場合に役立ちます。 +Runway には、AI がコマンドを生成しやすくするためのヘルパー ラッパーがいくつかあります。Symfony Console に似た方法で `addOption` と `addArgument` を使用できます。AI ツールを使用してコマンドを生成する場合に役立ちます。 ```php public function __construct(array $config) diff --git a/content/v3/ja/learn/ai.md b/content/v3/ja/learn/ai.md index c6c994d9..d7766ff1 100644 --- a/content/v3/ja/learn/ai.md +++ b/content/v3/ja/learn/ai.md @@ -1,15 +1,15 @@ -# Flight を使った AI と開発者エクスペリエンス +# Flight を使用した AI と開発者エクスペリエンス ## 概要 -Flight は、AI 駆動のツールと現代的な開発者ワークフローを使用して PHP プロジェクトを強化することを容易にします。LLM (Large Language Model) プロバイダーへの接続のための組み込みコマンドと、プロジェクト固有の AI コーディング指示を生成するための機能により、Flight は GitHub Copilot、Cursor、Windsurf、Antigravity (Gemini) などの AI アシスタントを最大限に活用するのに役立ちます。 +Flight は、AI 駆動のツールと現代的な開発者ワークフローを使用して PHP プロジェクトを強化することを容易にします。LLM (Large Language Model) プロバイダに接続するための組み込みコマンドと、プロジェクト固有の AI コーディング指示を生成するための機能により、Flight は GitHub Copilot、Cursor、Windsurf、Antigravity (Gemini) などの AI アシスタントを最大限に活用するのに役立ちます。 ## 理解 AI コーディングアシスタントは、プロジェクトのコンテキスト、慣習、目標を理解しているときに最も役立ちます。Flight の AI ヘルパーは、以下のことを可能にします: -- プロジェクトを人気の LLM プロバイダー (OpenAI、Grok、Claude など) に接続する -- AI ツールのためのプロジェクト固有の指示を生成および更新し、すべての人が一貫性のある関連するヘルプを得られるようにする -- コンテキストの説明に費やす時間を減らし、チームを一致させ生産性を維持する +- プロジェクトを人気の LLM プロバイダ (OpenAI、Grok、Claude など) に接続 +- AI ツール向けのプロジェクト固有の指示を生成および更新し、一貫性があり関連性の高いヘルプを全員に提供 +- コンテキストの説明に費やす時間を減らし、チームを調整し生産性を維持 これらの機能は、Flight コア CLI と公式の [flightphp/skeleton](https://github.com/flightphp/skeleton) スタータープロジェクトに組み込まれています。 @@ -17,16 +17,16 @@ AI コーディングアシスタントは、プロジェクトのコンテキ ### LLM 認証情報の設定 -`ai:init` コマンドは、プロジェクトを LLM プロバイダーに接続するプロセスをガイドします。 +`ai:init` コマンドは、プロジェクトを LLM プロバイダに接続するための手順をガイドします。 ```bash php runway ai:init ``` 以下のプロンプトが表示されます: -- プロバイダーの選択 (OpenAI、Grok、Claude など) -- API キーの入力 -- ベース URL とモデル名の設定 +- プロバイダを選択 (OpenAI、Grok、Claude など) +- API キーを入力 +- ベース URL とモデル名を設定 これにより、将来の LLM リクエストに必要な認証情報が作成されます。 @@ -42,13 +42,13 @@ Credentials saved to .runway-creds.json ### プロジェクト固有の AI 指示の生成 -`ai:generate-instructions` コマンドは、プロジェクトに合わせて調整された AI コーディングアシスタントのための指示を作成または更新するのに役立ちます。 +`ai:generate-instructions` コマンドは、プロジェクトに合わせた AI コーディングアシスタント向けの指示を作成または更新するのに役立ちます。 ```bash php runway ai:generate-instructions ``` -プロジェクトについて (説明、データベース、テンプレート、セキュリティ、チームサイズなど) のいくつかの質問に答えます。Flight は LLM プロバイダーを使用して指示を生成し、それを以下の場所に書き込みます: +プロジェクトの説明、データベース、テンプレート、セキュリティ、チームサイズなどについて数個の質問に答えます。Flight は LLM プロバイダを使用して指示を生成し、次のファイルに書き込みます: - `.github/copilot-instructions.md` (GitHub Copilot 用) - `.cursor/rules/project-overview.mdc` (Cursor 用) - `.windsurfrules` (Windsurf 用) @@ -68,21 +68,21 @@ AI instructions updated successfully. ## 高度な使用方法 -- コマンドオプションを使用して認証情報や指示ファイルの場所をカスタマイズできます (各コマンドで `--help` を参照)。 -- AI ヘルパーは、OpenAI 互換 API をサポートする任意の LLM プロバイダーと動作するように設計されています。 +- コマンドオプションを使用して認証情報や指示ファイルの場所をカスタマイズできます (各コマンドの `--help` を参照)。 +- AI ヘルパーは、OpenAI 互換 API をサポートする任意の LLM プロバイダと連携するように設計されています。 - プロジェクトが進化したら指示を更新したい場合、`ai:generate-instructions` を再実行してプロンプトに再度答えてください。 ## 関連項目 - [Flight Skeleton](https://github.com/flightphp/skeleton) – AI 統合付きの公式スターター -- [Runway CLI](/awesome-plugins/runway) – これらのコマンドを駆動する CLI ツールについて詳しく +- [Runway CLI](/awesome-plugins/runway) – これらのコマンドを駆動する CLI ツールの詳細 ## トラブルシューティング - 「Missing .runway-creds.json」が表示された場合、まず `php runway ai:init` を実行してください。 -- API キーが有効で、選択したモデルへのアクセス権があることを確認してください。 -- 指示が更新されない場合、プロジェクトディレクトリのファイルパーミッションを確認してください。 +- API キーが有効で、選択したモデルにアクセス可能であることを確認してください。 +- 指示が更新されない場合、プロジェクトディレクトリのファイル権限を確認してください。 ## 変更履歴 -- v3.16.0 – AI 統合のための `ai:init` および `ai:generate-instructions` CLI コマンドを追加。 \ No newline at end of file +- v3.16.0 – AI 統合のための `ai:init` と `ai:generate-instructions` CLI コマンドを追加。 \ No newline at end of file diff --git a/content/v3/ko/about.md b/content/v3/ko/about.md index d231fc65..d90d6d8b 100644 --- a/content/v3/ko/about.md +++ b/content/v3/ko/about.md @@ -1,12 +1,14 @@ # Flight PHP 프레임워크 -Flight은 빠르고, 간단하며, 확장 가능한 PHP 프레임워크입니다. 개발자들이 빠르게 작업을 완료하고 싶을 때, 불필요한 복잡함 없이 사용할 수 있도록 설계되었습니다. 클래식 웹 앱, 빠른 API, 또는 최신 AI 기반 도구 실험을 하든, Flight의 낮은 부하와 직관적인 설계가 완벽한 선택입니다. Flight은 경량으로 설계되었지만, 기업급 아키텍처 요구사항도 처리할 수 있습니다. +Flight는 빠르고 간단하며 확장 가능한 PHP 프레임워크로, 신속하게 작업을 완료하고자 하는 개발자를 위해 만들어졌으며, 불필요한 복잡함 없이 사용할 수 있습니다. 전통적인 웹 앱을 구축하든, 초고속 API를 만들든, 최신 AI 기반 도구를 실험하든, Flight의 낮은 메모리 사용량과 직관적인 설계가 완벽한 선택입니다. Flight는 가볍게 유지되도록 설계되었지만, 엔터프라이즈 아키텍처 요구 사항도 처리할 수 있습니다. -## 왜 Flight을 선택하나요? +## Flight를 선택하는 이유 -- **초보자 친화적:** Flight은 새로운 PHP 개발자를 위한 훌륭한 출발점입니다. 명확한 구조와 간단한 구문으로, 불필요한 코드 덩어리에 빠지지 않고 웹 개발을 배울 수 있습니다. -- **전문가들의 사랑:** 경험이 풍부한 개발자들은 Flight의 유연성과 제어성을 좋아합니다. 작은 프로토타입에서 완전한 기능을 갖춘 앱으로 확장할 수 있으며, 프레임워크를 변경할 필요가 없습니다. -- **AI 친화적:** Flight의 최소한의 오버헤드와 깨끗한 아키텍처는 AI 도구와 API 통합에 이상적입니다. 스마트 채팅봇, AI 기반 대시보드 제작, 또는 실험을 하려면 Flight이 방해가 되지 않고 중요한 일에 집중할 수 있게 합니다. [skeleton app](https://github.com/flightphp/skeleton)은 주요 AI 코딩 도우미를 위한 미리 작성된 지침 파일을 기본으로 포함합니다! [Flight와 AI 사용에 대해 자세히 알아보기](/learn/ai) +- **초보자 친화적:** Flight는 새로운 PHP 개발자에게 훌륭한 출발점입니다. 명확한 구조와 간단한 구문으로 보일러플레이트 코드에 빠지지 않고 웹 개발을 배울 수 있습니다. +- **전문가들이 사랑함:** 경험 많은 개발자들은 Flight의 유연성과 제어 기능을 사랑합니다. 작은 프로토타입에서 완전한 기능을 갖춘 앱으로 확장할 때 프레임워크를 바꿀 필요가 없습니다. +- **하위 호환성:** 우리는 당신의 시간을 소중히 여깁니다. Flight v3는 v2의 확장으로, 거의 모든 API를 동일하게 유지합니다. 우리는 혁명이 아닌 진화를 믿습니다. 주요 버전이 나올 때마다 "세계를 깨뜨리는" 일은 더 이상 없습니다. +- **의존성 제로:** Flight의 코어는 완전히 의존성 없이 작동합니다. 폴리필, 외부 패키지, 심지어 PSR 인터페이스조차 없습니다. 이는 공격 벡터를 줄이고, 작은 메모리 사용량을 유지하며, 상위 의존성에서 발생하는 예상치 못한 변경을 피할 수 있습니다. 선택적 플러그인에는 의존성이 포함될 수 있지만, 코어는 항상 가볍고 안전하게 유지됩니다. +- **AI 중심:** Flight의 최소 오버헤드와 깔끔한 아키텍처는 AI 도구와 API 통합에 이상적입니다. 스마트 챗봇, AI 기반 대시보드, 또는 단순 실험을 하든, Flight는 방해하지 않고 중요한 부분에 집중할 수 있게 합니다. [skeleton app](https://github.com/flightphp/skeleton)은 주요 AI 코딩 어시스턴트에 대한 사전 구축 지침 파일을 기본으로 제공합니다! [Flight와 AI 사용에 대해 더 알아보기](/learn/ai) ## 비디오 개요 @@ -16,29 +18,29 @@ Flight은 빠르고, 간단하며, 확장 가능한 PHP 프레임워크입니다
          - 그렇게 간단하죠? + 충분히 간단하죠?
          - 자세히 알아보기 Flight 문서에서 Flight에 대해! + 문서에서 Flight에 대해 더 알아보기!
          ## 빠른 시작 -빠른 기본 설치하기 위해 Composer를 사용하세요: +빠른 기본 설치의 경우 Composer를 사용해 설치하세요: ```bash composer require flightphp/core ``` -또는 [여기](https://github.com/flightphp/core)에서 레포 저장소를 ZIP으로 다운로드할 수 있습니다. 그런 다음 기본 `index.php` 파일은 다음과 같습니다: +또는 [여기](https://github.com/flightphp/core)에서 저장소의 zip 파일을 다운로드할 수 있습니다. 그런 다음 다음과 같은 기본 `index.php` 파일을 가지게 됩니다: ```php 8로 강제 이동하면 사용자들에게 문제가 될 수 있으므로, 프레임워크는 PHP >8도 지원합니다. +**참고:** PHP 7.4는 작성 시점(2024)에서 일부 LTS Linux 배포판의 기본 버전이기 때문에 지원됩니다. PHP >8로 강제 이동하면 해당 사용자들에게 많은 불편을 초래할 것입니다. 프레임워크는 PHP >8도 지원합니다. # 라이선스 -Flight은 [MIT](https://github.com/flightphp/core/blob/master/LICENSE) 라이선스 하에 배포됩니다. \ No newline at end of file +Flight는 [MIT](https://github.com/flightphp/core/blob/master/LICENSE) 라이선스 하에 배포됩니다. \ No newline at end of file diff --git a/content/v3/ko/awesome-plugins/runway.md b/content/v3/ko/awesome-plugins/runway.md index f2f42b6f..e684e1ea 100644 --- a/content/v3/ko/awesome-plugins/runway.md +++ b/content/v3/ko/awesome-plugins/runway.md @@ -1,6 +1,6 @@ # Runway -Runway는 Flight 애플리케이션을 관리하는 데 도움을 주는 CLI 애플리케이션입니다. 컨트롤러를 생성하고, 모든 경로를 표시하며, 그 이상의 기능을 제공합니다. 이는 훌륭한 [adhocore/php-cli](https://github.com/adhocore/php-cli) 라이브러리를 기반으로 합니다. +Runway는 Flight 애플리케이션을 관리하는 데 도움이 되는 CLI 애플리케이션입니다. 컨트롤러를 생성하고, 모든 경로를 표시하며, 그 외 더 많은 기능을 제공합니다. 이는 우수한 [adhocore/php-cli](https://github.com/adhocore/php-cli) 라이브러리를 기반으로 합니다. 코드 보기 [여기](https://github.com/flightphp/runway)를 클릭하세요. @@ -14,7 +14,7 @@ composer require flightphp/runway ## 기본 구성 -Runway를 처음 실행할 때, `app/config/config.php`의 `'runway'` 키를 통해 `runway` 구성을 찾으려고 시도합니다. +Runway를 처음 실행할 때, `app/config/config.php`에서 `'runway'` 키를 통해 `runway` 구성을 찾으려고 시도합니다. ```php **참고** - **v1.2.0**부터 `.runway-config.json`은 더 이상 사용되지 않습니다. 구성을 `app/config/config.php`로 이전하세요. `php runway config:migrate` 명령어를 사용하여 쉽게 할 수 있습니다. +> **참고** - **v1.2.0**부터 `.runway-config.json`은 더 이상 사용되지 않습니다. 구성을 `app/config/config.php`로 마이그레이션하세요. `php runway config:migrate` 명령어를 사용하여 쉽게 수행할 수 있습니다. ### 프로젝트 루트 감지 -Runway는 하위 디렉토리에서 실행하더라도 프로젝트의 루트를 감지할 만큼 똑똑합니다. `composer.json`, `.git`, 또는 `app/config/config.php`와 같은 지표를 찾아 프로젝트 루트가 어디인지 결정합니다. 이는 프로젝트의 어디서든 Runway 명령어를 실행할 수 있음을 의미합니다! +Runway는 하위 디렉토리에서 실행하더라도 프로젝트 루트를 충분히 스마트하게 감지합니다. `composer.json`, `.git`, 또는 `app/config/config.php`와 같은 지표를 찾아 프로젝트 루트가 어디인지 결정합니다. 이는 프로젝트의 어디서든 Runway 명령어를 실행할 수 있음을 의미합니다! ## 사용법 @@ -42,7 +42,7 @@ Runway에는 Flight 애플리케이션을 관리하는 데 사용할 수 있는 ### 명령어 목록 -`php runway` 명령어를 실행하여 사용 가능한 모든 명령어 목록을 볼 수 있습니다. +`php runway` 명령어를 실행하여 모든 사용 가능한 명령어 목록을 볼 수 있습니다. ```bash php runway @@ -74,7 +74,7 @@ php runway make:controller MyController php runway make:record users ``` -예를 들어, `users` 테이블에 다음 스키마가 있는 경우: `id`, `name`, `email`, `created_at`, `updated_at`, `app/records/UserRecord.php` 파일에 다음과 유사한 파일이 생성됩니다: +예를 들어 `users` 테이블이 `id`, `name`, `email`, `created_at`, `updated_at` 스키마를 가지고 있다면, `app/records/UserRecord.php` 파일에 다음과 유사한 파일이 생성됩니다: ```php info('예시 생성 중...'); - // 여기에 무언가를 수행 + // 여기에 무언가 수행 $io->ok('예시가 생성되었습니다!'); } @@ -186,7 +186,7 @@ Flight 애플리케이션에 사용자 지정 명령어를 구축하는 방법 ### 이전 구성 마이그레이션 -이전 `.runway-config.json` 파일이 있다면, 다음 명령어로 `app/config/config.php`로 쉽게 마이그레이션할 수 있습니다: +이전 `.runway-config.json` 파일이 있다면, 다음 명령어로 쉽게 `app/config/config.php`로 마이그레이션할 수 있습니다: ```bash php runway config:migrate @@ -210,7 +210,7 @@ php runway config:get app_root ## 모든 Runway 구성 -Runway의 구성을 사용자 정의해야 한다면, `app/config/config.php`에 이러한 값을 설정할 수 있습니다. 아래는 설정할 수 있는 추가 구성입니다: +Runway 구성을 사용자 정의해야 한다면, `app/config/config.php`에서 이러한 값을 설정할 수 있습니다. 아래는 설정할 수 있는 몇 가지 추가 구성입니다: ```php [ - '/includes/libs/vendor', // 벤더 디렉토리에 정말 독특한 경로가 있는 경우 등 + '/includes/libs/vendor', // 벤더 디렉토리의 고유한 경로가 있는 경우 등 ], - // 최종 경로는 프로젝트 내 명령어 파일을 검색할 위치입니다 + // 최종 경로는 명령어 파일을 검색할 프로젝트 내 위치 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // 전체 경로를 추가하려면, 그대로 진행하세요 (프로젝트 루트에 대한 절대 또는 상대 경로) + // 전체 경로를 추가하려면, 그대로 진행하세요 (프로젝트 루트에 대한 절대 또는 상대) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -254,7 +254,7 @@ return [ ### 구성 접근 -구성 값을 효과적으로 접근해야 한다면, `__construct` 메서드나 `app()` 메서드를 통해 접근할 수 있습니다. 또한 `app/config/services.php` 파일이 있는 경우, 해당 서비스도 명령어에서 사용할 수 있습니다. +구성 값을 효과적으로 접근해야 한다면, `__construct` 메서드나 `app()` 메서드를 통해 접근할 수 있습니다. 또한 `app/config/services.php` 파일이 있는 경우, 해당 서비스들도 명령어에서 사용할 수 있습니다. ```php public function execute() @@ -264,7 +264,7 @@ public function execute() // 구성 접근 $app_root = $this->config['runway']['app_root']; - // 데이터베이스 연결과 같은 서비스 접근 + // 데이터베이스 연결 같은 서비스 접근 $database = $this->config['database'] // ... @@ -280,7 +280,7 @@ public function __construct(array $config) { parent::__construct('make:example', '문서화를 위한 예시 생성', $config); - // name 옵션은 null로 선택적이며 완전히 선택적입니다 + // name 옵션은 null 가능하며 완전히 선택적입니다 $this->addOption('name', '예시의 이름', null); } ``` \ No newline at end of file diff --git a/content/v3/ko/learn/ai.md b/content/v3/ko/learn/ai.md index a89ac70a..c657896a 100644 --- a/content/v3/ko/learn/ai.md +++ b/content/v3/ko/learn/ai.md @@ -2,16 +2,16 @@ ## 개요 -Flight는 AI 기반 도구와 현대적인 개발자 워크플로우를 통해 PHP 프로젝트를 쉽게 강화할 수 있게 해줍니다. LLM (Large Language Model) 제공자에 연결하고 프로젝트별 AI 코딩 지침을 생성하는 내장 명령어를 통해, Flight는 GitHub Copilot, Cursor, Windsurf, Antigravity (Gemini)와 같은 AI 어시스턴트로부터 최대한의 이점을 얻도록 도와줍니다. +Flight는 AI 기반 도구와 현대적인 개발자 워크플로우를 통해 PHP 프로젝트를 쉽게 강화할 수 있게 합니다. LLM (Large Language Model) 제공자에 연결하는 내장 명령어와 프로젝트별 AI 코딩 지침을 생성하는 기능을 통해, Flight는 GitHub Copilot, Cursor, Windsurf, Antigravity (Gemini)와 같은 AI 어시스턴트를 최대한 활용할 수 있도록 도와줍니다. ## 이해 -AI 코딩 어시스턴트는 프로젝트의 맥락, 규칙, 목표를 이해할 때 가장 유용합니다. Flight의 AI 도우미는 다음을 가능하게 합니다: +AI 코딩 어시스턴트는 프로젝트의 맥락, 규칙, 목표를 이해할 때 가장 도움이 됩니다. Flight의 AI 도우미는 다음을 가능하게 합니다: - 프로젝트를 인기 있는 LLM 제공자 (OpenAI, Grok, Claude 등)에 연결 -- AI 도구를 위한 프로젝트별 지침을 생성하고 업데이트하여 모든 사람이 일관되고 관련된 도움을 받도록 함 -- 맥락 설명에 소요되는 시간을 줄여 팀을 일치시키고 생산성을 유지 +- AI 도구를 위한 프로젝트별 지침을 생성하고 업데이트하여 모두가 일관되고 관련성 있는 도움을 받을 수 있도록 함 +- 팀을 일치시키고 생산성을 유지하며, 맥락 설명에 소요되는 시간을 줄임 -이 기능들은 Flight 코어 CLI와 공식 [flightphp/skeleton](https://github.com/flightphp/skeleton) 스타터 프로젝트에 내장되어 있습니다. +이러한 기능은 Flight 코어 CLI와 공식 [flightphp/skeleton](https://github.com/flightphp/skeleton) 스타터 프로젝트에 내장되어 있습니다. ## 기본 사용법 @@ -23,7 +23,7 @@ AI 코딩 어시스턴트는 프로젝트의 맥락, 규칙, 목표를 이해할 php runway ai:init ``` -다음에 대해 프롬프트가 표시됩니다: +다음에 대해 입력하라는 프롬프트가 나타납니다: - 제공자 선택 (OpenAI, Grok, Claude 등) - API 키 입력 - 기본 URL 및 모델 이름 설정 @@ -32,17 +32,17 @@ php runway ai:init **예시:** ``` -Welcome to AI Init! -Which LLM API do you want to use? [1] openai, [2] grok, [3] claude: 1 -Enter the base URL for the LLM API [https://api.openai.com]: -Enter your API key for openai: sk-... -Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: -Credentials saved to .runway-creds.json +AI Init에 오신 것을 환영합니다! +어떤 LLM API를 사용하시겠습니까? [1] openai, [2] grok, [3] claude: 1 +LLM API의 기본 URL을 입력하세요 [https://api.openai.com]: +openai용 API 키를 입력하세요: sk-... +사용할 모델 이름을 입력하세요 (예: gpt-4, claude-3-opus 등) [gpt-4o]: +자격 증명이 .runway-creds.json에 저장되었습니다. ``` ### 프로젝트별 AI 지침 생성 -`ai:generate-instructions` 명령어는 프로젝트에 맞춤형 AI 코딩 어시스턴트를 위한 지침을 생성하거나 업데이트하는 데 도움을 줍니다. +`ai:generate-instructions` 명령어는 프로젝트에 맞춘 AI 코딩 어시스턴트를 위한 지침을 생성하거나 업데이트하는 데 도움을 줍니다. ```bash php runway ai:generate-instructions @@ -56,30 +56,30 @@ php runway ai:generate-instructions **예시:** ``` -Please describe what your project is for? My awesome API -What database are you planning on using? MySQL -What HTML templating engine will you plan on using (if any)? latte -Is security an important element of this project? (y/n) y +프로젝트가 무엇을 위한 것인지 설명해 주세요? 내 멋진 API +어떤 데이터베이스를 사용할 계획인가요? MySQL +어떤 HTML 템플릿 엔진을 사용할 계획인가요 (없는 경우)? latte +이 프로젝트에서 보안이 중요한 요소인가요? (y/n) y ... -AI instructions updated successfully. +AI 지침이 성공적으로 업데이트되었습니다. ``` -이제 AI 도구는 프로젝트의 실제 요구사항에 기반한 더 스마트하고 관련된 제안을 제공합니다. +이제 AI 도구는 프로젝트의 실제 요구사항에 기반한 더 스마트하고 관련성 있는 제안을 제공합니다. ## 고급 사용법 -- 명령어 옵션을 사용하여 자격 증명 또는 지침 파일의 위치를 사용자 지정할 수 있습니다 (각 명령어에 대해 `--help` 참조). +- 명령어 옵션을 사용하여 자격 증명 또는 지침 파일의 위치를 사용자 정의할 수 있습니다 (각 명령어의 `--help` 참조). - AI 도우미는 OpenAI 호환 API를 지원하는 모든 LLM 제공자와 함께 작동하도록 설계되었습니다. - 프로젝트가 발전함에 따라 지침을 업데이트하려면 `ai:generate-instructions`를 다시 실행하고 프롬프트에 답변하세요. ## 관련 자료 - [Flight Skeleton](https://github.com/flightphp/skeleton) – AI 통합이 포함된 공식 스타터 -- [Runway CLI](/awesome-plugins/runway) – 이러한 명령어를 구동하는 CLI 도구에 대해 자세히 +- [Runway CLI](/awesome-plugins/runway) – 이러한 명령어를 구동하는 CLI 도구에 대한 자세한 내용 ## 문제 해결 -- "Missing .runway-creds.json"이 표시되면 먼저 `php runway ai:init`을 실행하세요. +- "Missing .runway-creds.json"이 표시되면 먼저 `php runway ai:init`를 실행하세요. - API 키가 유효하고 선택된 모델에 액세스할 수 있는지 확인하세요. - 지침이 업데이트되지 않으면 프로젝트 디렉토리의 파일 권한을 확인하세요. diff --git a/content/v3/lv/about.md b/content/v3/lv/about.md index 6d46d353..e6cf973a 100644 --- a/content/v3/lv/about.md +++ b/content/v3/lv/about.md @@ -1,14 +1,16 @@ # Flight PHP Framework -Flight ir ātrs, vienkāršs, paplašināms ietvars PHP—izveidots izstrādātājiem, kuri vēlas ātri paveikt darbus, bez liekām raizēm. Vai jūs veidojat klasisku tīmekļa lietotni, ātru API vai eksperimentējat ar jaunākajām AI balstītajām rīkiem, Flight zems nospiedums un vienkāršais dizains padara to par ideālu izvēli. Flight ir domāts, lai būtu viegls, bet tas var arī tikt galā ar uzņēmuma arhitektūras prasībām. +Flight ir ātrs, vienkāršs, paplašināms PHP ietvars — izveidots izstrādātājiem, kuri vēlas ātri paveikt lietas, bez liekiem sarežģījumiem. Vai jūs veidojat klasisku tīmekļa lietotni, ātru API vai eksperimentējat ar jaunākajām AI balstītām rīkiem, Flight mazais pēdaizmērs un skaidrais dizains padara to par ideālu izvēli. Flight paredzēts būt vieglam, bet tas var arī apstrādāt uzņēmējdarbības arhitektūras prasības. ## Kāpēc izvēlēties Flight? -- **Sācējiem draudzīgs:** Flight ir lielisks sākumpunkts jauniem PHP izstrādātājiem. Tā skaidrā struktūra un vienkāršā sintakse palīdz iemācīties tīmekļa attīstību, nezaudējot laiku liekā kodā. -- **Profesionāļu mīlulis:** Pieredzējuši izstrādātāji mīl Flight par tās elastību un kontroli. Jūs varat augt no neliela prototipa līdz pilnvērtīgai lietotnei, neizmainot ietvarus. -- **AI draudzīgs:** Flight minimālais slogs un tīrais arhitektūras dizains padara to ideālu AI rīku un API integrācijai. Vai jūs veidojat gudrus čatbotus, AI vadītas paneļus vai vienkārši vēlaties eksperimentēt, Flight netraucē, ļaujot koncentrēties uz svarīgo. [Skeletapp](https://github.com/flightphp/skeleton) nāk ar iepriekš sagatavotiem instrukciju failiem galvenajiem AI kodēšanas asistentiem jau no kastes! [Uzziniet vairāk par AI izmantošanu ar Flight](/learn/ai) +- **Draudzīgs iesācējiem:** Flight ir lielisks sākumpunkts jaunajiem PHP izstrādātājiem. Tā skaidrā struktūra un vienkāršā sintakse palīdz mācīties tīmekļa izstrādi, neaizmirstoties veidlapās. +- **Mīlēts profesionāļu vidū:** Pieredzējuši izstrādātāji mīl Flight par tā elastību un kontroli. Jūs varat skalēt no mazas prototipa līdz pilnvērtīgai lietotnei, nevis mainot ietvarus. +- **Atpakaļ savietojams:** Mēs augstu vērtējam jūsu laiku. Flight v3 ir v2 papildinājums, saglabājot gandrīz visu to pašu API. Mēs ticam evolūcijai, nevis revolūcijai — vairs nav "laupīšanas pasaulei" katru reizi, kad iznāk lielāka versija. +- **Bez atkarībām:** Flight kodols ir pilnībā bez atkarībām — bez polifiliem, bez ārējiem pakotnēm, pat bez PSR saskarnēm. Tas nozīmē mazāk uzbrukuma vektoru, mazāku pēdaizmēru un bez negaidītiem salauztiem izmaiņām no augšupstrēmes atkarībām. Neobligātie spraudņi var ietvert atkarības, bet kodols vienmēr paliks viegls un drošs. +- **Vairāks AI:** Flight minimālais overhead un tīrā arhitektūra padara to ideālu AI rīku un API integrācijai. Vai jūs veidojat gudrus čatbotus, AI vadītus panelus vai tikai vēlaties eksperimentēt, Flight netraucē, lai jūs varētu koncentrēties uz svarīgo. [Skeleton app](https://github.com/flightphp/skeleton) nāk ar iepriekš sagatavotiem instrukciju failiem galvenajām AI kodēšanas asistentēm jau no kastes! [Uzzināt vairāk par AI izmantošanu ar Flight](/learn/ai) -## Video Overview +## Video pārskats
          @@ -16,29 +18,29 @@ Flight ir ātrs, vienkāršs, paplašināms ietvars PHP—izveidots izstrādāt
          - Vai tas nav pietiekami vienkārši? + pietiekami vienkārši, vai ne?
          - Uzziniet vairāk par Flight dokumentācijā! + Uzzināt vairāk par Flight dokumentācijā!
          -## Quick Start +## Ātrais starts -Lai veiktu ātru, pamata instalāciju, instalējiet to ar Composer: +Lai veiktu ātru, vienkāršu instalāciju, instalējiet to ar Composer: ```bash composer require flightphp/core ``` -Vai jūs varat lejupielādēt zip failu no repozitorijas [šeit](https://github.com/flightphp/core). Tad jums būs pamata `index.php` fails, piemēram, šāds: +Vai arī lejupielādējiet repo zip [šeit](https://github.com/flightphp/core). Tad jums būs pamata `index.php` fails kā sekojošais: ```php 8 izraisītu daudz neērtību lietotājiem. Ietvars arī atbalsta PHP >8. +**Piezīme:** PHP 7.4 ir atbalstīts, jo pašreizējā rakstīšanas laikā (2024) PHP 7.4 ir noklusējuma versija dažām LTS Linux distribūcijām. Piespiežot pāreju uz PHP >8 radītu daudz sāpju tiem lietotājiem. Ietvars arī atbalsta PHP >8. -# License +# Licence -Flight ir izlaists zem [MIT](https://github.com/flightphp/core/blob/master/LICENSE) licences. \ No newline at end of file +Flight ir izlaists saskaņā ar [MIT](https://github.com/flightphp/core/blob/master/LICENSE) licenci. \ No newline at end of file diff --git a/content/v3/lv/awesome-plugins/runway.md b/content/v3/lv/awesome-plugins/runway.md index 48a41370..df93caf4 100644 --- a/content/v3/lv/awesome-plugins/runway.md +++ b/content/v3/lv/awesome-plugins/runway.md @@ -4,7 +4,7 @@ Runway ir CLI lietojumprogramma, kas palīdz pārvaldīt jūsu Flight lietojumpr Noklikšķiniet [šeit](https://github.com/flightphp/runway), lai skatītu kodu. -## Instalēšana +## Uzstādīšana Instalējiet ar composer. @@ -27,9 +27,7 @@ return [ ]; ``` -> **PIEZĪME** - No **v1.2.0**, `.runway-config.json` ir novecojis. Lūdzu, migrējiet savu konfigurāciju uz `app/config/config.php`. Jūs varat to izdarīt viegli ar `php runway config:migrate` komandu. - - +> **PIEZĪME** - Sākot no **v1.2.0**, `.runway-config.json` ir novecojis. Lūdzu, migrējiet savu konfigurāciju uz `app/config/config.php`. Jūs varat to izdarīt viegli ar `php runway config:migrate` komandu. ### Projekta saknes noteikšana @@ -62,7 +60,7 @@ php runway routes --help ### Ģenerēt kontrolieri -Pamatojoties uz konfigurāciju `runway.app_root`, atrašanās vieta ģenerēs kontrolieri jums `app/controllers/` direktorijā. +Balstoties uz konfigurāciju `runway.app_root`, atrašanās vieta ģenerēs kontrolieri jums `app/controllers/` direktorijā. ```bash php runway make:controller MyController @@ -70,7 +68,7 @@ php runway make:controller MyController ### Ģenerēt Active Record modeli -Vispirms pārliecinieties, ka esat instalējis [Active Record](/awesome-plugins/active-record) spraudni. Pamatojoties uz konfigurāciju `runway.app_root`, atrašanās vieta ģenerēs ierakstu jums `app/records/` direktorijā. +Vispirms pārliecinieties, ka esat instalējis [Active Record](/awesome-plugins/active-record) spraudni. Balstoties uz konfigurāciju `runway.app_root`, atrašanās vieta ģenerēs ierakstu jums `app/records/` direktorijā. ```bash php runway make:record users @@ -95,12 +93,12 @@ namespace app\records; * @property string $created_at * @property string $updated_at * // jūs varētu arī pievienot attiecības šeit, kad definēsiet tās $relations masīvā - * @property CompanyRecord $company Attiecību piemērs + * @property CompanyRecord $company Attiecības piemērs */ class UserRecord extends \flight\ActiveRecord { /** - * @var array $relations Iestatīt attiecības modelim + * @var array $relations Iestatīt modeļa attiecības * https://docs.flightphp.com/awesome-plugins/active-record#relationships */ protected array $relations = []; @@ -116,7 +114,7 @@ class UserRecord extends \flight\ActiveRecord } ``` -### Parādīt visas maršrutus +### Parādīt visus maršrutus Tas parādīs visus maršrutus, kas pašlaik ir reģistrēti ar Flight. @@ -124,7 +122,7 @@ Tas parādīs visus maršrutus, kas pašlaik ir reģistrēti ar Flight. php runway routes ``` -Ja vēlaties skatīt tikai specifiskus maršrutus, jūs varat pievienot karodziņu, lai filtrētu maršrutus. +Ja jūs vēlaties skatīt tikai specifiskus maršrutus, jūs varat pievienot karodziņu, lai filtrētu maršrutus. ```bash # Parādīt tikai GET maršrutus @@ -138,7 +136,7 @@ php runway routes --post ## Pievienot pielāgotas komandas Runway -Ja jūs vai nu izveidojat paketi Flight, vai vēlaties pievienot savas pielāgotas komandas savam projektam, jūs varat to izdarīt, izveidojot `src/commands/`, `flight/commands/`, `app/commands/` vai `commands/` direktoriju savam projektam/paketei. Ja nepieciešama tālāk customization, skatiet sadaļu zemāk par Konfigurāciju. +Ja jūs vai nu izveidojat paketi Flight, vai vēlaties pievienot savas pielāgotas komandas savam projektam, jūs varat to izdarīt, izveidojot `src/commands/`, `flight/commands/`, `app/commands/` vai `commands/` direktoriju savam projektam/paketam. Ja jums vajadzīga tālāk customize, skatiet sadaļu zemāk par Konfigurāciju. Lai izveidotu komandu, jūs vienkārši pagarināt `AbstractBaseCommand` klasi un implementēt vismaz `__construct` metodi un `execute` metodi. @@ -159,7 +157,7 @@ class ExampleCommand extends AbstractBaseCommand public function __construct(array $config) { parent::__construct('make:example', 'Izveidot piemēru dokumentācijai', $config); - $this->argument('', 'Smieklīgā gif nosaukums'); + $this->argument('', 'Nosaukums smieklīgajam gif'); } /** @@ -173,7 +171,7 @@ class ExampleCommand extends AbstractBaseCommand $io->info('Izveido piemēru...'); - // Dariet kaut ko šeit + // Dari kaut ko šeit $io->ok('Piemērs izveidots!'); } @@ -184,7 +182,7 @@ Skatiet [adhocore/php-cli Dokumentāciju](https://github.com/adhocore/php-cli), ## Konfigurācijas pārvaldība -Tā kā konfigurācija ir pārvietota uz `app/config/config.php` no `v1.2.0`, ir dažas palīpkomandas konfigurācijas pārvaldībai. +Tā kā konfigurācija ir pārvietota uz `app/config/config.php` sākot no `v1.2.0`, ir dažas palīgam komandas konfigurācijas pārvaldībai. ### Migrēt veco konfigurāciju @@ -196,7 +194,7 @@ php runway config:migrate ### Iestatīt konfigurācijas vērtību -Jūs varat iestatīt konfigurācijas vērtību, izmantojot `config:set` komandu. Tas ir noderīgi, ja vēlaties atjaunināt konfigurācijas vērtību, neatsākot failu. +Jūs varat iestatīt konfigurācijas vērtību, izmantojot `config:set` komandu. Tas ir noderīgi, ja vēlaties atjaunināt konfigurācijas vērtību bez faila atvēršanas. ```bash php runway config:set app_root "app/" @@ -212,7 +210,7 @@ php runway config:get app_root ## Visas Runway konfigurācijas -Ja nepieciešams pielāgot konfigurāciju Runway, jūs varat iestatīt šīs vērtības `app/config/config.php`. Zemāk ir dažas papildu konfigurācijas, kuras jūs varat iestatīt: +Ja jums vajadzīga customize Runway konfigurācija, jūs varat iestatīt šīs vērtības `app/config/config.php`. Zemāk ir dažas papildu konfigurācijas, kuras jūs varat iestatīt: ```php [ - '/includes/libs/vendor', // ja jums ir patiesi unikāls ceļš uz jūsu vendor direktoriju vai kaut ko + '/includes/libs/vendor', // ja jums ir patiešām unikāls ceļš uz jūsu vendor direktoriju vai kaut ko ], - // Galīgie ceļi ir atrašanās vietas projektā, kur meklēt komandu failus + // Galīgie ceļi ir vietas projektā, kur meklēt komandu failus 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // Ja vēlaties tikai pievienot pilnu ceļu, dariet to (absolūts vai relatīvs pret projektu sakni) + // Ja vēlaties tikai pievienot pilnu ceļu, dariet to (absolūts vai relatīvs pret projekta sakni) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -256,33 +254,33 @@ return [ ### Piekļuve konfigurācijai -Ja nepieciešams efektīvi piekļūt konfigurācijas vērtībām, jūs varat piekļūt tām caur `__construct` metodi vai `app()` metodi. Ir arī svarīgi atzīmēt, ka, ja jums ir `app/config/services.php` fails, šie servisi būs pieejami jūsu komandai. +Ja jums vajadzīga efektīvi piekļūt konfigurācijas vērtībām, jūs varat piekļūt tām caur `__construct` metodi vai `app()` metodi. Ir arī svarīgi atzīmēt, ka, ja jums ir `app/config/services.php` fails, šie servisi būs pieejami jūsu komandai. ```php public function execute() { $io = $this->app()->io(); - // Piekļuve konfigurācijai + // Piekļūt konfigurācijai $app_root = $this->config['runway']['app_root']; - // Piekļuve servisiem, piemēram, datubāzes savienojumam + // Piekļūt servisiem, piemēram, datubāzes savienojumam $database = $this->config['database'] // ... } ``` -## AI palīglīdzekļu apvalki +## AI Palīgsa Aptinēji -Runway ir daži palīglīdzekļu apvalki, kas padara vieglāku AI ģenerēt komandas. Jūs varat izmantot `addOption` un `addArgument` veidā, kas šķiet līdzīgs Symfony Console. Tas ir noderīgi, ja izmantojat AI rīkus, lai ģenerētu savas komandas. +Runway ir daži palīgsa aptinēji, kas padara vieglāku AI ģenerēt komandas. Jūs varat izmantot `addOption` un `addArgument` veidā, kas jūtas līdzīgs Symfony Console. Tas ir noderīgi, ja jūs izmantojat AI rīkus, lai ģenerētu savas komandas. ```php public function __construct(array $config) { parent::__construct('make:example', 'Izveidot piemēru dokumentācijai', $config); - // Name arguments ir nullable un pēc noklusējuma pilnībā opcionāls - $this->addOption('name', 'Piemēra nosaukums', null); + // The mode argument is nullable and defaults to completely optional + $this->addOption('name', 'The name of the example', null); } ``` \ No newline at end of file diff --git a/content/v3/lv/learn/ai.md b/content/v3/lv/learn/ai.md index a2df6eb1..a0c66e11 100644 --- a/content/v3/lv/learn/ai.md +++ b/content/v3/lv/learn/ai.md @@ -2,14 +2,14 @@ ## Pārskats -Flight padara viegli uzlabot jūsu PHP projektus ar AI vadītiem rīkiem un moderniem izstrādātāju darba plūsmu. Ar iebūvētiem komandām savienojumiem ar LLM (Large Language Model) sniedzējiem un ģenerēšanu projektu specifiskām AI kodēšanas instrukcijām, Flight palīdz jums un jūsu komandai iegūt maksimālu labumu no AI asistentiem, piemēram, GitHub Copilot, Cursor, Windsurf un Antigravity (Gemini). +Flight padara vieglu jūsu PHP projektu uzlabošanu ar AI vadītiem rīkiem un mūsdienīgiem izstrādātāju darba plūsmu. Iebūvētās komandas savienojumiem ar LLM (Large Language Model) sniedzējiem un ģenerēšanai projekta specifiskām AI kodēšanas instrukcijām palīdz Flight jums un jūsu komandai iegūt maksimālu labumu no AI asistentiem, piemēram, GitHub Copilot, Cursor, Windsurf un Antigravity (Gemini). ## Saprašana AI kodēšanas asistenti ir visnoderīgākie, kad tie saprot jūsu projekta kontekstu, konvencijas un mērķus. Flight AI palīgi ļauj jums: -- Savienot jūsu projektu ar populāriem LLM sniedzējiem (OpenAI, Grok, Claude utt.) -- Ģenerēt un atjaunināt projektu specifiskas instrukcijas AI rīkiem, lai visi saņemtu konsekventu, atbilstošu palīdzību -- Turēt jūsu komandu saskaņotu un produktīvu, ar mazāk laika iztērētu konteksta skaidrošanai +- Savienot savu projektu ar populāriem LLM sniedzējiem (OpenAI, Grok, Claude utt.) +- Ģenerēt un atjaunināt projekta specifiskas instrukcijas AI rīkiem, lai visi saņemtu konsekventu, atbilstošu palīdzību +- Uzturēt jūsu komandu saskaņotu un produktīvu, ar mazāk laika iztērēšanu konteksta skaidrošanai Šīs funkcijas ir iebūvētas Flight kodola CLI un oficiālajā [flightphp/skeleton](https://github.com/flightphp/skeleton) sākuma projektā. @@ -17,27 +17,27 @@ AI kodēšanas asistenti ir visnoderīgākie, kad tie saprot jūsu projekta kont ### LLM akreditīvu iestatīšana -`ai:init` komanda ved jūs cauri jūsu projekta savienojumam ar LLM sniedzēju. +`ai:init` komanda vadīs jūs cauri jūsu projekta savienošanai ar LLM sniedzēju. ```bash php runway ai:init ``` -Jums tiks prasīts: -- Izvēlēties jūsu sniedzēju (OpenAI, Grok, Claude utt.) -- Ievadīt jūsu API atslēgu +Jums tiks lūgts: +- Izvēlēties savu sniedzēju (OpenAI, Grok, Claude utt.) +- Ievadīt savu API atslēgu - Iestatīt bāzes URL un modeļa nosaukumu Tas izveido nepieciešamos akreditīvus, lai jūs varētu veikt turpmākus LLM pieprasījumus. **Piemērs:** ``` -Laipni lūgti AI Init! -Kuru LLM API jūs vēlaties izmantot? [1] openai, [2] grok, [3] claude: 1 -Ievadiet bāzes URL LLM API [https://api.openai.com]: -Ievadiet jūsu API atslēgu openai: sk-... -Ievadiet modeļa nosaukumu, kuru vēlaties izmantot (piem. gpt-4, claude-3-opus utt.) [gpt-4o]: -Akreditīvi saglabāti .runway-creds.json +Welcome to AI Init! +Which LLM API do you want to use? [1] openai, [2] grok, [3] claude: 1 +Enter the base URL for the LLM API [https://api.openai.com]: +Enter your API key for openai: sk-... +Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: +Credentials saved to .runway-creds.json ``` ### Projekta specifisku AI instrukciju ģenerēšana @@ -48,36 +48,36 @@ Akreditīvi saglabāti .runway-creds.json php runway ai:generate-instructions ``` -Jūs atbildēsiet uz dažiem jautājumiem par jūsu projektu (apraksts, datubāze, veidnes, drošība, komandas lielums utt.). Flight izmanto jūsu LLM sniedzēju, lai ģenerētu instrukcijas, pēc tam ieraksta tās: -- `.github/copilot-instructions.md` (GitHub Copilot) -- `.cursor/rules/project-overview.mdc` (Cursor) -- `.windsurfrules` (Windsurf) -- `.gemini/GEMINI.md` (Antigravity) +Jūs atbildēsiet uz dažiem jautājumiem par savu projektu (apraksts, datubāze, veidnes, drošība, komandas lielums utt.). Flight izmanto jūsu LLM sniedzēju, lai ģenerētu instrukcijas, tad ieraksta tās: +- `.github/copilot-instructions.md` (for GitHub Copilot) +- `.cursor/rules/project-overview.mdc` (for Cursor) +- `.windsurfrules` (for Windsurf) +- `.gemini/GEMINI.md` (for Antigravity) **Piemērs:** ``` -Lūdzu, aprakstiet, kam ir paredzēts jūsu projekts? Mans lieliskais API -Kuru datubāzi jūs plānojat izmantot? MySQL -Kuru HTML veidņu dzinēju jūs plānojat izmantot (ja kādu)? latte -Vai drošība ir svarīgs elements šim projektam? (y/n) y +Please describe what your project is for? My awesome API +What database are you planning on using? MySQL +What HTML templating engine will you plan on using (if any)? latte +Is security an important element of this project? (y/n) y ... -AI instrukcijas atjauninātas veiksmīgi. +AI instructions updated successfully. ``` Tagad jūsu AI rīki sniegs gudrākus, atbilstošākus ieteikumus, balstītus uz jūsu projekta reālajām vajadzībām. ## Uzlabota izmantošana -- Jūs varat pielāgot jūsu akreditīvu vai instrukciju failu atrašanās vietu, izmantojot komandas opcijas (skat. `--help` katrai komandai). -- AI palīgi ir paredzēti darbam ar jebkuru LLM sniedzēju, kas atbalsta OpenAI saderīgās API. -- Ja vēlaties atjaunināt jūsu instrukcijas, kad jūsu projekts attīstās, vienkārši palaidiet atkārtoti `ai:generate-instructions` un atbildiet uz uzvednēm vēlreiz. +- Jūs varat pielāgot jūsu akreditīvu vai instrukciju failu atrašanās vietu, izmantojot komandas opcijas (skatiet `--help` katrai komandai). +- AI palīgi ir paredzēti darbam ar jebkuru LLM sniedzēju, kas atbalsta OpenAI saderīgas API. +- Ja vēlaties atjaunināt savas instrukcijas, kad jūsu projekts attīstās, vienkārši palaidiet atkārtoti `ai:generate-instructions` un atbildiet uz uzvednēm vēlreiz. ## Skatīt arī - [Flight Skeleton](https://github.com/flightphp/skeleton) – Oficiālais sākuma projekts ar AI integrāciju - [Runway CLI](/awesome-plugins/runway) – Vairāk par CLI rīku, kas nodrošina šīs komandas -## Traucējummeklēšana +## Traucējumu novēršana - Ja redzat "Missing .runway-creds.json", vispirms palaidiet `php runway ai:init`. - Pārliecinieties, ka jūsu API atslēga ir derīga un tai ir piekļuve izvēlētajam modelim. diff --git a/content/v3/pt/about.md b/content/v3/pt/about.md index 32bfd031..9db7d0b6 100644 --- a/content/v3/pt/about.md +++ b/content/v3/pt/about.md @@ -1,12 +1,14 @@ -# Flight PHP Framework +# Framework PHP Flight -Flight é um framework rápido, simples e extensível para PHP — criado para desenvolvedores que querem fazer as coisas rapidamente, sem complicações. Seja você construindo um app web clássico, uma API ultrarrápida ou experimentando com as ferramentas mais recentes impulsionadas por IA, o design de baixa pegada e direto ao ponto do Flight o torna uma escolha perfeita. Flight é projetado para ser enxuto, mas também pode lidar com requisitos de arquitetura empresarial. +Flight é um framework rápido, simples e extensível para PHP — construído para desenvolvedores que querem fazer as coisas rapidamente, sem complicações. Seja você construindo um app web clássico, uma API ultrarrápida ou experimentando com as ferramentas mais recentes alimentadas por IA, o baixo impacto e o design direto do Flight o tornam uma escolha perfeita. Flight é projetado para ser enxuto, mas também pode lidar com requisitos de arquitetura empresarial. -## Por que Escolher Flight? +## Por Que Escolher Flight? -- **Amigável para Iniciantes:** Flight é um ótimo ponto de partida para novos desenvolvedores PHP. Sua estrutura clara e sintaxe simples ajudam você a aprender desenvolvimento web sem se perder em códigos desnecessários. -- **Adorado por Profissionais:** Desenvolvedores experientes amam o Flight pela sua flexibilidade e controle. Você pode escalar de um protótipo pequeno para um app completo sem trocar de framework. -- **Amigável para IA:** A sobrecarga mínima e a arquitetura limpa do Flight o tornam ideal para integrar ferramentas e APIs de IA. Seja construindo chatbots inteligentes, painéis impulsionados por IA ou apenas experimentando, o Flight sai do caminho para que você se concentre no que importa. O [skeleton app](https://github.com/flightphp/skeleton) vem com arquivos de instruções pré-construídos para os principais assistentes de codificação de IA prontos para uso! [Saiba mais sobre o uso de IA com Flight](/learn/ai) +- **Amigável para Iniciantes:** Flight é um ótimo ponto de partida para novos desenvolvedores PHP. Sua estrutura clara e sintaxe simples ajudam você a aprender desenvolvimento web sem se perder em boilerplate. +- **Amado por Profissionais:** Desenvolvedores experientes adoram o Flight por sua flexibilidade e controle. Você pode escalar de um protótipo minúsculo para um app completo sem trocar de framework. +- **Compatível com Versões Anteriores:** Nós valorizamos seu tempo. Flight v3 é uma ampliação do v2, mantendo quase toda a mesma API. Acreditamos em evolução, não em revolução — nada de "quebrar o mundo" toda vez que uma versão principal é lançada. +- **Zero Dependências:** O núcleo do Flight é completamente livre de dependências — sem polyfills, sem pacotes externos, nem mesmo interfaces PSR. Isso significa menos vetores de ataque, um footprint menor e nenhuma mudança quebrada surpreendente de dependências upstream. Plugins opcionais podem incluir dependências, mas o núcleo sempre permanecerá enxuto e seguro. +- **Focado em IA:** O overhead mínimo e a arquitetura limpa do Flight o tornam ideal para integrar ferramentas e APIs de IA. Seja você construindo chatbots inteligentes, painéis impulsionados por IA ou apenas querendo experimentar, Flight sai do caminho para que você possa se concentrar no que importa. O [skeleton app](https://github.com/flightphp/skeleton) vem com arquivos de instruções pré-construídos para os principais assistentes de codificação de IA logo de cara! [Saiba mais sobre o uso de IA com Flight](/learn/ai) ## Visão Geral em Vídeo @@ -16,29 +18,29 @@ Flight é um framework rápido, simples e extensível para PHP — criado para d
          - Simples o suficiente, certo? + Simples o suficiente, não é?
          - Saiba mais sobre Flight na documentação! + Saiba mais sobre o Flight na documentação!
          ## Início Rápido -Para fazer uma instalação básica e rápida, instale com Composer: +Para uma instalação rápida e básica, instale com Composer: ```bash composer require flightphp/core ``` -Ou você pode baixar um zip do repositório [aqui](https://github.com/flightphp/core). Então, você terá um arquivo básico `index.php` como o seguinte: +Ou você pode baixar um zip do repositório [aqui](https://github.com/flightphp/core). Em seguida, você teria um arquivo `index.php` básico como o seguinte: ```php 8 causaria problemas para esses usuários. O framework também suporta PHP >8. +**Nota:** PHP 7.4 é suportado porque, no momento da redação (2024), o PHP 7.4 é a versão padrão para algumas distribuições Linux LTS. Forçar uma mudança para PHP >8 causaria muitos problemas para esses usuários. O framework também suporta PHP >8. # Licença -Flight é liberado sob a [licença MIT](https://github.com/flightphp/core/blob/master/LICENSE). \ No newline at end of file +Flight é lançado sob a licença [MIT](https://github.com/flightphp/core/blob/master/LICENSE). \ No newline at end of file diff --git a/content/v3/pt/awesome-plugins/runway.md b/content/v3/pt/awesome-plugins/runway.md index de0a5b9e..9102ecea 100644 --- a/content/v3/pt/awesome-plugins/runway.md +++ b/content/v3/pt/awesome-plugins/runway.md @@ -1,6 +1,6 @@ # Runway -Runway é uma aplicação CLI que ajuda você a gerenciar suas aplicações Flight. Ela pode gerar controladores, exibir todas as rotas e mais. É baseada na excelente biblioteca [adhocore/php-cli](https://github.com/adhocore/php-cli). +Runway é uma aplicação CLI que ajuda a gerenciar suas aplicações Flight. Ela pode gerar controladores, exibir todas as rotas e mais. É baseada na excelente biblioteca [adhocore/php-cli](https://github.com/adhocore/php-cli). Clique [aqui](https://github.com/flightphp/runway) para visualizar o código. @@ -27,18 +27,18 @@ return [ ]; ``` -> **NOTA** - A partir de **v1.2.0**, `.runway-config.json` está depreciado. Por favor, migre sua configuração para `app/config/config.php`. Você pode fazer isso facilmente com o comando `php runway config:migrate`. +> **NOTA** - A partir da **v1.2.0**, `.runway-config.json` está depreciado. Por favor, migre sua configuração para `app/config/config.php`. Você pode fazer isso facilmente com o comando `php runway config:migrate`. ### Detecção da Raiz do Projeto -Runway é inteligente o suficiente para detectar a raiz do seu projeto, mesmo se você o executar de um subdiretório. Ele procura por indicadores como `composer.json`, `.git` ou `app/config/config.php` para determinar onde está a raiz do projeto. Isso significa que você pode executar comandos do Runway de qualquer lugar no seu projeto! +O Runway é inteligente o suficiente para detectar a raiz do seu projeto, mesmo se você o executar de um subdiretório. Ele procura indicadores como `composer.json`, `.git` ou `app/config/config.php` para determinar onde está a raiz do projeto. Isso significa que você pode executar comandos do Runway de qualquer lugar no seu projeto! ## Uso -Runway tem uma série de comandos que você pode usar para gerenciar sua aplicação Flight. Há duas maneiras fáceis de usar o Runway. +O Runway tem vários comandos que você pode usar para gerenciar sua aplicação Flight. Existem duas maneiras fáceis de usar o Runway. 1. Se você estiver usando o projeto skeleton, você pode executar `php runway [command]` da raiz do seu projeto. -1. Se você estiver usando Runway como um pacote instalado via composer, você pode executar `vendor/bin/runway [command]` da raiz do seu projeto. +1. Se você estiver usando o Runway como um pacote instalado via composer, você pode executar `vendor/bin/runway [command]` da raiz do seu projeto. ### Lista de Comandos @@ -68,13 +68,13 @@ php runway make:controller MyController ### Gerar um Modelo Active Record -Primeiro, certifique-se de que você instalou o plugin [Active Record](/awesome-plugins/active-record). Com base na configuração em `runway.app_root`, o local gerará um registro para você no diretório `app/records/`. +Primeiro, certifique-se de ter instalado o plugin [Active Record](/awesome-plugins/active-record). Com base na configuração em `runway.app_root`, o local gerará um registro para você no diretório `app/records/`. ```bash php runway make:record users ``` -Por exemplo, se você tiver a tabela `users` com o seguinte esquema: `id`, `name`, `email`, `created_at`, `updated_at`, um arquivo similar ao seguinte será criado no arquivo `app/records/UserRecord.php`: +Se, por exemplo, você tiver a tabela `users` com o seguinte esquema: `id`, `name`, `email`, `created_at`, `updated_at`, um arquivo semelhante ao seguinte será criado no arquivo `app/records/UserRecord.php`: ```php 'app/', - // Este é o diretório onde o seu arquivo index raiz está localizado + // Este é o diretório onde o seu arquivo de índice raiz está localizado 'index_root' => 'public/', // Estes são os caminhos para as raízes de outros projetos @@ -233,10 +233,10 @@ return [ // Caminhos base provavelmente não precisam ser configurados, mas está aqui se você quiser 'base_paths' => [ - '/includes/libs/vendor', // se você tiver um caminho realmente único para o diretório vendor ou algo assim + '/includes/libs/vendor', // se você tiver um caminho realmente único para o seu diretório vendor ou algo assim ], - // Caminhos finais são locais dentro de um projeto para procurar pelos arquivos de comando + // Caminhos finais são locais dentro de um projeto para procurar os arquivos de comando 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', @@ -271,9 +271,9 @@ public function execute() } ``` -## Wrappers de Auxílio para IA +## Wrappers de Auxílio de IA -Runway tem alguns wrappers de auxílio que facilitam para a IA gerar comandos. Você pode usar `addOption` e `addArgument` de uma maneira que se sente similar ao Symfony Console. Isso é útil se você estiver usando ferramentas de IA para gerar seus comandos. +O Runway tem alguns wrappers de auxílio que facilitam para a IA gerar comandos. Você pode usar `addOption` e `addArgument` de uma maneira que se sinta semelhante ao Symfony Console. Isso é útil se você estiver usando ferramentas de IA para gerar seus comandos. ```php public function __construct(array $config) diff --git a/content/v3/pt/learn/ai.md b/content/v3/pt/learn/ai.md index 1d8c22c8..07d56d07 100644 --- a/content/v3/pt/learn/ai.md +++ b/content/v3/pt/learn/ai.md @@ -2,13 +2,13 @@ ## Visão Geral -Flight facilita o superpoder de seus projetos PHP com ferramentas alimentadas por IA e fluxos de trabalho modernos para desenvolvedores. Com comandos integrados para conectar a provedores de LLM (Large Language Model) e gerar instruções de codificação específicas do projeto baseadas em IA, Flight ajuda você e sua equipe a tirar o máximo proveito de assistentes de IA como GitHub Copilot, Cursor, Windsurf e Antigravity (Gemini). +Flight facilita o superalimentar seus projetos PHP com ferramentas alimentadas por IA e fluxos de trabalho modernos para desenvolvedores. Com comandos integrados para conectar a provedores de LLM (Large Language Model) e gerar instruções específicas de projeto para codificação com IA, Flight ajuda você e sua equipe a tirar o máximo proveito de assistentes de IA como GitHub Copilot, Cursor, Windsurf e Antigravity (Gemini). ## Entendendo -Assistentes de codificação de IA são mais úteis quando entendem o contexto, as convenções e os objetivos do seu projeto. Os ajudantes de IA do Flight permitem que você: +Assistentes de codificação com IA são mais úteis quando entendem o contexto, as convenções e os objetivos do seu projeto. Os ajudantes de IA do Flight permitem que você: - Conecte seu projeto a provedores populares de LLM (OpenAI, Grok, Claude, etc.) -- Gere e atualize instruções específicas do projeto para ferramentas de IA, para que todos recebam ajuda consistente e relevante +- Gere e atualize instruções específicas de projeto para ferramentas de IA, para que todos recebam ajuda consistente e relevante - Mantenha sua equipe alinhada e produtiva, com menos tempo gasto explicando o contexto Esses recursos estão integrados ao CLI principal do Flight e ao projeto inicial oficial [flightphp/skeleton](https://github.com/flightphp/skeleton). @@ -36,13 +36,13 @@ Bem-vindo ao AI Init! Qual API de LLM você deseja usar? [1] openai, [2] grok, [3] claude: 1 Digite a URL base para a API de LLM [https://api.openai.com]: Digite sua chave de API para openai: sk-... -Digite o nome do modelo que você deseja usar (ex. gpt-4, claude-3-opus, etc) [gpt-4o]: +Digite o nome do modelo que você deseja usar (ex.: gpt-4, claude-3-opus, etc) [gpt-4o]: Credenciais salvas em .runway-creds.json ``` -### Gerando Instruções de IA Específicas do Projeto +### Gerando Instruções Específicas de Projeto para IA -O comando `ai:generate-instructions` ajuda você a criar ou atualizar instruções para assistentes de codificação de IA, adaptadas ao seu projeto. +O comando `ai:generate-instructions` ajuda você a criar ou atualizar instruções para assistentes de codificação com IA, adaptadas ao seu projeto. ```bash php runway ai:generate-instructions @@ -59,7 +59,7 @@ Você responderá a algumas perguntas sobre seu projeto (descrição, banco de d Por favor, descreva para que serve seu projeto? Minha API incrível Qual banco de dados você planeja usar? MySQL Qual engine de templating HTML você planeja usar (se houver)? latte -A segurança é um elemento importante deste projeto? (s/n) s +A segurança é um elemento importante deste projeto? (y/n) y ... Instruções de IA atualizadas com sucesso. ``` @@ -68,14 +68,14 @@ Agora, suas ferramentas de IA darão sugestões mais inteligentes e relevantes c ## Uso Avançado -- Você pode personalizar a localização dos seus arquivos de credenciais ou instruções usando opções de comando (veja `--help` para cada comando). +- Você pode personalizar a localização dos arquivos de credenciais ou instruções usando opções de comando (veja `--help` para cada comando). - Os ajudantes de IA são projetados para funcionar com qualquer provedor de LLM que suporte APIs compatíveis com OpenAI. -- Se você quiser atualizar suas instruções à medida que seu projeto evolui, basta executar novamente `ai:generate-instructions` e responder aos prompts novamente. +- Se você quiser atualizar suas instruções à medida que o projeto evolui, basta executar novamente `ai:generate-instructions` e responder aos prompts novamente. ## Veja Também - [Flight Skeleton](https://github.com/flightphp/skeleton) – O inicial oficial com integração de IA -- [Runway CLI](/awesome-plugins/runway) – Mais sobre a ferramenta CLI que impulsiona esses comandos +- [Runway CLI](/awesome-plugins/runway) – Mais sobre a ferramenta CLI que alimenta esses comandos ## Solução de Problemas diff --git a/content/v3/ru/about.md b/content/v3/ru/about.md index 490cce1c..93732b8a 100644 --- a/content/v3/ru/about.md +++ b/content/v3/ru/about.md @@ -1,14 +1,16 @@ -# Фреймворк PHP Flight +# Flight PHP Framework -Flight — это быстрый, простой и расширяемый фреймворк для PHP, созданный для разработчиков, которые хотят быстро выполнять задачи без лишних хлопот. Независимо от того, создаете ли вы классическое веб-приложение, сверхбыстрый API или экспериментируете с последними инструментами на базе ИИ, низкая нагрузка и прямолинейный дизайн Flight делают его идеальным выбором. Flight предназначен для того, чтобы быть легким, но при этом он может справляться с требованиями корпоративной архитектуры. +Flight — это быстрый, простой и расширяемый фреймворк для PHP, созданный для разработчиков, которые хотят быстро достигать результатов без лишних хлопот. Независимо от того, строите ли вы классическое веб-приложение, сверхбыстрый API или экспериментируете с новейшими инструментами на базе ИИ, низкий объем памяти и прямолинейный дизайн Flight делают его идеальным выбором. Flight предназначен для минимализма, но также может справляться с требованиями корпоративной архитектуры. ## Почему выбрать Flight? -- **Дружественный для начинающих:** Flight — отличная отправная точка для новых разработчиков PHP. Его четкая структура и простой синтаксис помогают освоить веб-разработку, не запутавшись в шаблонном коде. -- **Любимый профессионалами:** Опытные разработчики любят Flight за его гибкость и контроль. Вы можете масштабировать от маленького прототипа до полноценного приложения, не переключаясь на другие фреймворки. -- **Дружественный к ИИ:** Минимальная нагрузка и чистая архитектура Flight идеально подходят для интеграции инструментов и API ИИ. Если вы создаете умные чатботы, дашборды на базе ИИ или просто экспериментируете, Flight не мешает, позволяя сосредоточиться на главном. В [skeleton app](https://github.com/flightphp/skeleton) уже есть предустановленные инструкции для основных ассистентов ИИ прямо из коробки! [Узнайте больше об использовании ИИ с Flight](/learn/ai) +- **Дружественный для начинающих:** Flight — отличная отправная точка для новых разработчиков PHP. Его четкая структура и простой синтаксис помогают изучать веб-разработку, не теряясь в шаблонном коде. +- **Любимый профессионалами:** Опытные разработчики ценят Flight за его гибкость и контроль. Вы можете масштабировать от крошечного прототипа до полнофункционального приложения, не меняя фреймворк. +- **Обратная совместимость:** Мы ценим ваше время. Flight v3 — это дополнение к v2, сохраняющее почти весь тот же API. Мы верим в эволюцию, а не в революцию — больше никаких "разрушений мира" с каждым крупным выпуском. +- **Нулевые зависимости:** Ядро Flight полностью лишено зависимостей — никаких полифиллов, внешних пакетов, даже интерфейсов PSR. Это означает меньше векторов атак, меньший объем и отсутствие неожиданных разрушительных изменений от внешних зависимостей. Опциональные плагины могут включать зависимости, но ядро всегда останется легким и безопасным. +- **Ориентированный на ИИ:** Минимальные накладные расходы и чистая архитектура Flight делают его идеальным для интеграции инструментов и API на базе ИИ. Независимо от того, создаете ли вы умные чат-боты, панели управления на базе ИИ или просто хотите поэкспериментировать, Flight не мешает, позволяя сосредоточиться на главном. [Пример приложения-скелета](https://github.com/flightphp/skeleton) поставляется с предустановленными инструкциями для основных ассистентов по кодированию на базе ИИ прямо из коробки! [Узнайте больше об использовании ИИ с Flight](/learn/ai) -## Обзор в видео +## Обзор видео
          @@ -16,7 +18,7 @@ Flight — это быстрый, простой и расширяемый фр
          - Достаточно просто, верно? + Достаточно просто, правда?
          Узнайте больше о Flight в документации!
          @@ -25,20 +27,20 @@ Flight — это быстрый, простой и расширяемый фр ## Быстрый старт -Для быстрой базовой установки установите его с помощью Composer: +Для быстрой установки без лишнего, установите его с помощью Composer: ```bash composer require flightphp/core ``` -Или вы можете скачать ZIP-архив репозитория [here](https://github.com/flightphp/core). Затем у вас будет базовый файл `index.php`, как в следующем примере: +Или вы можете скачать zip-архив репозитория [здесь](https://github.com/flightphp/core). Затем у вас будет базовый файл `index.php`, подобный следующему: ```php 8 вызвал бы проблемы для пользователей. Фреймворк также поддерживает PHP >8. +**Примечание:** PHP 7.4 поддерживается, потому что на момент написания (2024) PHP 7.4 является версией по умолчанию для некоторых дистрибутивов Linux LTS. Принуждение к переходу на PHP >8 вызвало бы много проблем для этих пользователей. Фреймворк также поддерживает PHP >8. # Лицензия -Flight распространяется под [MIT](https://github.com/flightphp/core/blob/master/LICENSE) лицензией. \ No newline at end of file +Flight выпущен под [MIT](https://github.com/flightphp/core/blob/master/LICENSE) лицензией. \ No newline at end of file diff --git a/content/v3/ru/awesome-plugins/runway.md b/content/v3/ru/awesome-plugins/runway.md index 5919708e..da58446a 100644 --- a/content/v3/ru/awesome-plugins/runway.md +++ b/content/v3/ru/awesome-plugins/runway.md @@ -14,7 +14,7 @@ composer require flightphp/runway ## Базовая конфигурация -В первый раз при запуске Runway попытается найти конфигурацию `runway` в `app/config/config.php` через ключ `'runway'`. +Впервые запустив Runway, оно попытается найти конфигурацию `runway` в `app/config/config.php` через ключ `'runway'`. ```php **ПРИМЕЧАНИЕ** - Начиная с **v1.2.0**, `.runway-config.json` устарел. Пожалуйста, мигрируйте вашу конфигурацию в `app/config/config.php`. Вы можете сделать это легко с помощью команды `php runway config:migrate`. - - ### Обнаружение корня проекта -Runway достаточно умён, чтобы обнаружить корень вашего проекта, даже если вы запускаете его из поддиректории. Он ищет индикаторы, такие как `composer.json`, `.git` или `app/config/config.php`, чтобы определить, где находится корень проекта. Это значит, что вы можете запускать команды Runway откуда угодно в вашем проекте! +Runway достаточно умён, чтобы обнаружить корень вашего проекта, даже если вы запускаете его из поддиректории. Оно ищет индикаторы, такие как `composer.json`, `.git` или `app/config/config.php`, чтобы определить, где находится корень проекта. Это означает, что вы можете запускать команды Runway откуда угодно в вашем проекте! ## Использование @@ -62,7 +60,7 @@ php runway routes --help ### Генерация контроллера -На основе конфигурации в `runway.app_root` будет сгенерирован контроллер для вас в директории `app/controllers/`. +На основе конфигурации в `runway.app_root`, местоположение сгенерирует для вас контроллер в директории `app/controllers/`. ```bash php runway make:controller MyController @@ -70,13 +68,13 @@ php runway make:controller MyController ### Генерация модели Active Record -Сначала убедитесь, что вы установили плагин [Active Record](/awesome-plugins/active-record). На основе конфигурации в `runway.app_root` будет сгенерирована запись для вас в директории `app/records/`. +Сначала убедитесь, что вы установили плагин [Active Record](/awesome-plugins/active-record). На основе конфигурации в `runway.app_root`, местоположение сгенерирует для вас запись в директории `app/records/`. ```bash php runway make:record users ``` -Если, например, у вас есть таблица `users` со следующей схемой: `id`, `name`, `email`, `created_at`, `updated_at`, будет создан файл, похожий на следующий, в файле `app/records/UserRecord.php`: +Если, например, у вас есть таблица `users` со следующей схемой: `id`, `name`, `email`, `created_at`, `updated_at`, файл, похожий на следующий, будет создан в файле `app/records/UserRecord.php`: ```php $config Конфигурация из app/config/config.php + * @param array $config Config from app/config/config.php */ public function __construct(array $config) { - parent::__construct('make:example', 'Создать пример для документации', $config); - $this->argument('', 'Имя забавного GIF'); + parent::__construct('make:example', 'Create an example for the documentation', $config); + $this->argument('', 'The name of the funny gif'); } /** - * Выполняет функцию + * Executes the function * * @return void */ @@ -171,11 +169,11 @@ class ExampleCommand extends AbstractBaseCommand { $io = $this->app()->io(); - $io->info('Создание примера...'); + $io->info('Creating example...'); - // Сделайте что-то здесь + // Do something here - $io->ok('Пример создан!'); + $io->ok('Example created!'); } } ``` @@ -196,7 +194,7 @@ php runway config:migrate ### Установка значения конфигурации -Вы можете установить значение конфигурации с помощью команды `config:set`. Это полезно, если вы хотите обновить значение конфигурации без открытия файла. +Вы можете установить значение конфигурации с помощью команды `config:set`. Это полезно, если вы хотите обновить значение конфигурации, не открывая файл. ```bash php runway config:set app_root "app/" @@ -218,33 +216,33 @@ php runway config:get app_root [ - // Здесь находится директория вашего приложения + // This is where your application directory is located 'app_root' => 'app/', - // Это директория, где находится ваш корневой индексный файл + // This is the directory where your root index file is located 'index_root' => 'public/', - // Это пути к корням других проектов + // These are the paths to the roots of other projects 'root_paths' => [ '/home/user/different-project', '/var/www/another-project' ], - // Базовые пути, скорее всего, не нужно настраивать, но они здесь, если вы хотите + // Base paths most likely don't need to be configured, but it's here if you want it 'base_paths' => [ - '/includes/libs/vendor', // если у вас действительно уникальный путь для директории vendor или чего-то подобного + '/includes/libs/vendor', // if you have a really unique path for your vendor directory or something ], - // Финальные пути — это места внутри проекта для поиска файлов команд + // Final paths are locations within a project to search for the command files 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // Если вы хотите просто добавить полный путь, пожалуйста (абсолютный или относительный к корню проекта) + // If you want to just add the full path, go right ahead (absolute or relative to project root) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -256,33 +254,33 @@ return [ ### Доступ к конфигурации -Если вам нужно эффективно получить доступ к значениям конфигурации, вы можете обращаться к ним через метод `__construct` или метод `app()`. Также важно отметить, что если у вас есть файл `app/config/services.php`, эти сервисы также будут доступны для вашей команды. +Если вам нужно эффективно получить доступ к значениям конфигурации, вы можете получить к ним доступ через метод `__construct` или метод `app()`. Также важно отметить, что если у вас есть файл `app/config/services.php`, эти сервисы также будут доступны для вашей команды. ```php public function execute() { $io = $this->app()->io(); - // Доступ к конфигурации + // Access configuration $app_root = $this->config['runway']['app_root']; - // Доступ к сервисам, например, соединению с базой данных + // Access services like maybe a database connection $database = $this->config['database'] // ... } ``` -## Обертки помощников ИИ +## Обёртки помощника ИИ -Runway имеет некоторые обертки помощников, которые облегчают генерацию команд ИИ. Вы можете использовать `addOption` и `addArgument` таким образом, который похож на Symfony Console. Это полезно, если вы используете инструменты ИИ для генерации ваших команд. +Runway имеет некоторые обёртки помощников, которые облегчают генерацию команд ИИ. Вы можете использовать `addOption` и `addArgument` таким образом, который ощущается похожим на Symfony Console. Это полезно, если вы используете инструменты ИИ для генерации ваших команд. ```php public function __construct(array $config) { - parent::__construct('make:example', 'Создать пример для документации', $config); + parent::__construct('make:example', 'Create an example for the documentation', $config); - // Аргумент mode является nullable и по умолчанию полностью необязательным - $this->addOption('name', 'Имя примера', null); + // The mode argument is nullable and defaults to completely optional + $this->addOption('name', 'The name of the example', null); } ``` \ No newline at end of file diff --git a/content/v3/ru/learn/ai.md b/content/v3/ru/learn/ai.md index 5284c983..b984abdf 100644 --- a/content/v3/ru/learn/ai.md +++ b/content/v3/ru/learn/ai.md @@ -2,14 +2,14 @@ ## Обзор -Flight упрощает суперзарядку ваших PHP-проектов с помощью инструментов на базе ИИ и современных рабочих процессов разработчика. С встроенными командами для подключения к провайдерам LLM (Large Language Model) и генерации специфических для проекта инструкций по кодированию с ИИ, Flight помогает вам и вашей команде извлечь максимум из ИИ-помощников, таких как GitHub Copilot, Cursor, Windsurf и Antigravity (Gemini). +Flight упрощает суперзарядку ваших PHP-проектов с помощью инструментов на базе ИИ и современных рабочих процессов для разработчиков. С встроенными командами для подключения к поставщикам LLM (Large Language Model) и генерации инструкций по кодированию ИИ, специфичных для проекта, Flight помогает вам и вашей команде максимально использовать ИИ-ассистентов, таких как GitHub Copilot, Cursor, Windsurf и Antigravity (Gemini). ## Понимание -ИИ-помощники по кодированию наиболее полезны, когда они понимают контекст, конвенции и цели вашего проекта. ИИ-помощники Flight позволяют вам: -- Подключить ваш проект к популярным провайдерам LLM (OpenAI, Grok, Claude и т.д.) -- Генерировать и обновлять специфические для проекта инструкции для ИИ-инструментов, чтобы все получали последовательную, релевантную помощь -- Сохранять вашу команду в согласованности и продуктивности, тратя меньше времени на объяснение контекста +ИИ-ассистенты для кодирования наиболее полезны, когда они понимают контекст, конвенции и цели вашего проекта. ИИ-помощники Flight позволяют вам: +- Подключить ваш проект к популярным поставщикам LLM (OpenAI, Grok, Claude и т.д.) +- Генерировать и обновлять инструкции, специфичные для проекта, для ИИ-инструментов, чтобы все получали последовательную, релевантную помощь +- Держать вашу команду в согласованности и продуктивности, тратя меньше времени на объяснение контекста Эти функции встроены в основной CLI Flight и официальный стартовый проект [flightphp/skeleton](https://github.com/flightphp/skeleton). @@ -17,14 +17,14 @@ Flight упрощает суперзарядку ваших PHP-проектов ### Настройка учетных данных LLM -Команда `ai:init` проведет вас через процесс подключения вашего проекта к провайдеру LLM. +Команда `ai:init` проведет вас через процесс подключения вашего проекта к поставщику LLM. ```bash php runway ai:init ``` Вам будет предложено: -- Выбрать вашего провайдера (OpenAI, Grok, Claude и т.д.) +- Выбрать вашего поставщика (OpenAI, Grok, Claude и т.д.) - Ввести ваш API-ключ - Установить базовый URL и имя модели @@ -40,15 +40,15 @@ Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: Credentials saved to .runway-creds.json ``` -### Генерация специфических для проекта инструкций ИИ +### Генерация инструкций ИИ, специфичных для проекта -Команда `ai:generate-instructions` помогает создать или обновить инструкции для ИИ-помощников по кодированию, адаптированные к вашему проекту. +Команда `ai:generate-instructions` помогает создать или обновить инструкции для ИИ-ассистентов по кодированию, адаптированные к вашему проекту. ```bash php runway ai:generate-instructions ``` -Вы ответите на несколько вопросов о вашем проекте (описание, база данных, шаблонизация, безопасность, размер команды и т.д.). Flight использует вашего провайдера LLM для генерации инструкций, затем записывает их в: +Вы ответите на несколько вопросов о вашем проекте (описание, база данных, шаблонизация, безопасность, размер команды и т.д.). Flight использует вашего поставщика LLM для генерации инструкций, затем записывает их в: - `.github/copilot-instructions.md` (для GitHub Copilot) - `.cursor/rules/project-overview.mdc` (для Cursor) - `.windsurfrules` (для Windsurf) @@ -69,19 +69,19 @@ AI instructions updated successfully. ## Расширенное использование - Вы можете настроить расположение файлов учетных данных или инструкций с помощью опций команд (см. `--help` для каждой команды). -- ИИ-помощники предназначены для работы с любым провайдером LLM, поддерживающим API, совместимые с OpenAI. -- Если вы хотите обновить инструкции по мере эволюции вашего проекта, просто перезапустите `ai:generate-instructions` и ответьте на подсказки снова. +- ИИ-помощники предназначены для работы с любым поставщиком LLM, поддерживающим API, совместимые с OpenAI. +- Если вы хотите обновить инструкции по мере эволюции проекта, просто перезапустите `ai:generate-instructions` и снова ответьте на подсказки. ## См. также - [Flight Skeleton](https://github.com/flightphp/skeleton) – Официальный стартер с интеграцией ИИ -- [Runway CLI](/awesome-plugins/runway) – Подробнее о CLI-инструменте, питающем эти команды +- [Runway CLI](/awesome-plugins/runway) – Подробнее о CLI-инструменте, обеспечивающем эти команды ## Устранение неисправностей - Если вы видите "Missing .runway-creds.json", сначала запустите `php runway ai:init`. - Убедитесь, что ваш API-ключ действителен и имеет доступ к выбранной модели. -- Если инструкции не обновляются, проверьте разрешения на файлы в директории вашего проекта. +- Если инструкции не обновляются, проверьте разрешения файлов в директории вашего проекта. ## Журнал изменений diff --git a/content/v3/uk/about.md b/content/v3/uk/about.md index d9271bdd..8dd2a182 100644 --- a/content/v3/uk/about.md +++ b/content/v3/uk/about.md @@ -1,14 +1,16 @@ -# Фреймворк Flight PHP +# Flight PHP Framework -Flight — це швидкий, простий, розширюваний фреймворк для PHP, створений для розробників, які хочуть швидко виконувати завдання, без зайвого клопоту. Незалежно від того, чи створюєте ви класичний веб-додаток, швидкісний API чи експериментуєте з останніми інструментами на основі ШІ, низький відбиток і простий дизайн Flight роблять його ідеальним вибором. Flight призначений бути легким, але також може задовольняти вимоги корпоративної архітектури. +Flight — це швидкий, простий, розширюваний фреймворк для PHP, створений для розробників, які хочуть швидко виконувати завдання без зайвого клопоту. Чи будуєте ви класичний веб-додаток, блискавично швидкий API чи експериментуєте з найновішими інструментами на основі ШІ, низьке навантаження Flight та простий дизайн роблять його ідеальним вибором. Flight призначений бути легким, але також може відповідати вимогам корпоративної архітектури. ## Чому обрати Flight? -- **Дружечний для початківців:** Flight — чудова стартова точка для нових розробників PHP. Його чітка структура і проста синтаксис допомагають вивчати веб-розробку, не гублячись у зайвому коді. -- **Улюблений професіоналами:** Досвідчені розробники люблять Flight за його гнучкість і контроль. Ви можете масштабувати від маленького прототипу до повноцінного додатку, не змінюючи фреймворків. -- **Дружечний до ШІ:** Мінімальний наклад і чиста архітектура Flight роблять його ідеальним для інтеграції інструментів і API ШІ. Чи то ви створюєте розумні чатботи, панелі керування на основі ШІ, чи просто експериментуєте, Flight не заважає, щоб ви могли зосередитися на головному. [skeleton app](https://github.com/flightphp/skeleton) містить попередньо налаштовані файли інструкцій для основних помічників кодування на основі ШІ прямо з коробки! [Дізнатися більше про використання ШІ з Flight](/learn/ai) +- **Дружній до початківців:** Flight — чудова відправна точка для нових розробників PHP. Його чітка структура та простий синтаксис допомагають вивчати веб-розробку без заплутування в шаблонному коді. +- **Улюблений професіоналами:** Досвідчені розробники люблять Flight за його гнучкість та контроль. Ви можете масштабувати від маленького прототипу до повноцінного додатка без зміни фреймворків. +- **Зворотна сумісність:** Ми цінуємо ваш час. Flight v3 — це доповнення до v2, зберігаючи майже весь той самий API. Ми віримо в еволюцію, а не революцію — більше ніяких "руйнувань світу" при виході кожної великої версії. +- **Без залежностей:** Ядро Flight повністю позбавлене залежностей — без поліфілів, зовнішніх пакетів, навіть інтерфейсів PSR. Це означає менше векторів атак, менший обсяг та відсутність несподіваних руйнівних змін від залежностей. Опціональні плагіни можуть містити залежності, але ядро завжди залишатиметься легким і безпечним. +- **Орієнтований на ШІ:** Мінімальне навантаження Flight та чиста архітектура роблять його ідеальним для інтеграції інструментів та API на основі ШІ. Чи будуєте ви розумних чат-ботів, панелі керування на основі ШІ чи просто хочете експериментувати, Flight не заважає, дозволяючи зосередитися на важливому. [Скелет додатка](https://github.com/flightphp/skeleton) постачається з попередньо налаштованими файлами інструкцій для основних AI-асистентів кодування прямо з коробки! [Дізнайтеся більше про використання ШІ з Flight](/learn/ai) -## Огляд у відео +## Огляд на відео
          @@ -18,27 +20,27 @@ Flight — це швидкий, простий, розширюваний фре
          Досить просто, правда?
          - Дізнатися більше про Flight у документації! + Дізнайтеся більше про Flight у документації!
          ## Швидкий старт -Щоб швидко встановити базову версію, встановіть за допомогою Composer: +Для швидкої базової установки встановіть його за допомогою Composer: ```bash composer require flightphp/core ``` -Або ви можете завантажити zip-архів репозиторію [here](https://github.com/flightphp/core). Тоді у вас буде базовий файл `index.php`, як ось: +Або ви можете завантажити zip-архів репозиторію [тут](https://github.com/flightphp/core). Тоді у вас буде базовий файл `index.php`, подібний до такого: ```php 8 спричинив би багато проблем для цих користувачів. Фреймворк також підтримує PHP >8. +**Примітка:** PHP 7.4 підтримується, оскільки на момент написання (2024) PHP 7.4 є версією за замовчуванням для деяких LTS дистрибутивів Linux. Примусовий перехід на PHP >8 викликав би багато проблем для цих користувачів. Фреймворк також підтримує PHP >8. # Ліцензія -Flight поширюється під [MIT](https://github.com/flightphp/core/blob/master/LICENSE) ліцензією. \ No newline at end of file +Flight розповсюджується за [MIT](https://github.com/flightphp/core/blob/master/LICENSE) ліцензією. \ No newline at end of file diff --git a/content/v3/uk/awesome-plugins/runway.md b/content/v3/uk/awesome-plugins/runway.md index e971ca2c..9b49751c 100644 --- a/content/v3/uk/awesome-plugins/runway.md +++ b/content/v3/uk/awesome-plugins/runway.md @@ -1,6 +1,6 @@ -# Runway +# Паска -Runway — це додаток командного рядка (CLI), який допомагає керувати вашими додатками Flight. Він може генерувати контролери, відображати всі маршрути та багато іншого. Він базується на чудовій бібліотеці [adhocore/php-cli](https://github.com/adhocore/php-cli). +Паска — це CLI-додаток, який допомагає керувати вашими додатками Flight. Він може генерувати контролери, відображати всі маршрути та багато іншого. Він базується на чудовій бібліотеці [adhocore/php-cli](https://github.com/adhocore/php-cli). Натисніть [тут](https://github.com/flightphp/runway), щоб переглянути код. @@ -14,7 +14,7 @@ composer require flightphp/runway ## Базова Конфігурація -Під час першого запуску Runway він спробує знайти конфігурацію `runway` у `app/config/config.php` через ключ `'runway'`. +Вперше, коли ви запустите Паска, він спробує знайти конфігурацію `runway` у `app/config/config.php` через ключ `'runway'`. ```php **ПРИМІТКА** - Починаючи з **v1.2.0**, `.runway-config.json` є застарілим. Будь ласка, мігруйте вашу конфігурацію до `app/config/config.php`. Ви можете зробити це легко за допомогою команди `php runway config:migrate`. - - ### Виявлення Кореня Проекту -Runway достатньо розумний, щоб виявити корінь вашого проекту, навіть якщо ви запускаєте його з підкаталогу. Він шукає індикатори, такі як `composer.json`, `.git` або `app/config/config.php`, щоб визначити, де знаходиться корінь проекту. Це означає, що ви можете запускати команди Runway з будь-якого місця у вашому проекті! +Паска достатньо розумний, щоб виявити корінь вашого проекту, навіть якщо ви запускаєте його з підкаталогу. Він шукає індикатори, такі як `composer.json`, `.git` або `app/config/config.php`, щоб визначити, де знаходиться корінь проекту. Це означає, що ви можете запускати команди Паска з будь-якого місця у вашому проекті! ## Використання -Runway має низку команд, які ви можете використовувати для керування вашим додатком Flight. Є два простих способи використовувати Runway. +Паска має низку команд, які ви можете використовувати для керування вашим додатком Flight. Є два простих способи використовувати Паска. -1. Якщо ви використовуєте скелетний проект, ви можете запустити `php runway [command]` з кореня вашого проекту. -1. Якщо ви використовуєте Runway як пакет, встановлений через composer, ви можете запустити `vendor/bin/runway [command]` з кореня вашого проекту. +1. Якщо ви використовуєте скелетний проект, ви можете запускати `php runway [command]` з кореня вашого проекту. +1. Якщо ви використовуєте Паска як пакет, встановлений через composer, ви можете запускати `vendor/bin/runway [command]` з кореня вашого проекту. ### Список Команд @@ -62,7 +60,7 @@ php runway routes --help ### Генерація Контролера -На основі конфігурації в `runway.app_root`, локація згенерує контролер для вас у директорії `app/controllers/`. +На основі конфігурації в `runway.app_root`, локація згенерує контролер для вас у каталозі `app/controllers/`. ```bash php runway make:controller MyController @@ -70,13 +68,13 @@ php runway make:controller MyController ### Генерація Моделі Active Record -Спочатку переконайтеся, що ви встановили плагін [Active Record](/awesome-plugins/active-record). На основі конфігурації в `runway.app_root`, локація згенерує запис для вас у директорії `app/records/`. +Спочатку переконайтеся, що ви встановили плагін [Active Record](/awesome-plugins/active-record). На основі конфігурації в `runway.app_root`, локація згенерує запис для вас у каталозі `app/records/`. ```bash php runway make:record users ``` -Наприклад, якщо у вас є таблиця `users` з такою схемою: `id`, `name`, `email`, `created_at`, `updated_at`, файл, подібний до наступного, буде створено у файлі `app/records/UserRecord.php`: +Наприклад, якщо у вас є таблиця `users` з такою схемою: `id`, `name`, `email`, `created_at`, `updated_at`, файл, подібний до наступного, буде створено в файлі `app/records/UserRecord.php`: ```php $config Config from app/config/config.php + * @param array $config Конфігурація з app/config/config.php */ public function __construct(array $config) { - parent::__construct('make:example', 'Create an example for the documentation', $config); - $this->argument('', 'The name of the funny gif'); + parent::__construct('make:example', 'Створити приклад для документації', $config); + $this->argument('', 'Назва смішного GIF'); } /** - * Executes the function + * Виконує функцію * * @return void */ @@ -171,20 +169,20 @@ class ExampleCommand extends AbstractBaseCommand { $io = $this->app()->io(); - $io->info('Creating example...'); + $io->info('Створення прикладу...'); - // Do something here + // Зробіть щось тут - $io->ok('Example created!'); + $io->ok('Приклад створено!'); } } ``` -Дивіться [adhocore/php-cli Documentation](https://github.com/adhocore/php-cli) для отримання додаткової інформації про те, як створювати власні власні команди для вашого додатка Flight! +Дивіться [Документацію adhocore/php-cli](https://github.com/adhocore/php-cli) для отримання додаткової інформації про те, як створювати власні власні команди для вашого додатка Flight! ## Керування Конфігурацією -Оскільки конфігурація переміщена до `app/config/config.php` починаючи з `v1.2.0`, є кілька допоміжних команд для керування конфігурацією. +Оскільки конфігурація перемістилася до `app/config/config.php` починаючи з `v1.2.0`, є кілька допоміжних команд для керування конфігурацією. ### Міграція Старої Конфігурації @@ -210,41 +208,41 @@ php runway config:set app_root "app/" php runway config:get app_root ``` -## Усі Конфігурації Runway +## Усі Конфігурації Паска -Якщо вам потрібно кастомізувати конфігурацію для Runway, ви можете встановити ці значення у `app/config/config.php`. Нижче наведено деякі додаткові конфігурації, які ви можете встановити: +Якщо вам потрібно кастомізувати конфігурацію для Паска, ви можете встановити ці значення в `app/config/config.php`. Нижче наведено деякі додаткові конфігурації, які ви можете встановити: ```php [ - // This is where your application directory is located + // Тут розташований каталог вашого додатка 'app_root' => 'app/', - // This is the directory where your root index file is located + // Це каталог, де розташований ваш кореневий індексний файл 'index_root' => 'public/', - // These are the paths to the roots of other projects + // Це шляхи до коренів інших проектів 'root_paths' => [ '/home/user/different-project', '/var/www/another-project' ], - // Base paths most likely don't need to be configured, but it's here if you want it + // Базові шляхи, ймовірно, не потрібно налаштовувати, але вони тут, якщо ви хочете 'base_paths' => [ - '/includes/libs/vendor', // if you have a really unique path for your vendor directory or something + '/includes/libs/vendor', // якщо у вас є дійсно унікальний шлях для каталогу vendor або щось подібне ], - // Final paths are locations within a project to search for the command files + // Фінальні шляхи — це локації всередині проекту для пошуку файлів команд 'final_paths' => [ 'src/diff-path/commands', 'app/module/admin/commands', ], - // If you want to just add the full path, go right ahead (absolute or relative to project root) + // Якщо ви хочете просто додати повний шлях, робіть це (абсолютний або відносний до кореня проекту) 'paths' => [ '/home/user/different-project/src/diff-path/commands', '/var/www/another-project/app/module/admin/commands', @@ -263,10 +261,10 @@ public function execute() { $io = $this->app()->io(); - // Access configuration + // Доступ до конфігурації $app_root = $this->config['runway']['app_root']; - // Access services like maybe a database connection + // Доступ до сервісів, наприклад, підключення до бази даних $database = $this->config['database'] // ... @@ -275,14 +273,14 @@ public function execute() ## Обгортки Допоміжника ШІ -Runway має деякі обгортки помічників, які полегшують для ШІ генерацію команд. Ви можете використовувати `addOption` та `addArgument` у спосіб, подібний до Symfony Console. Це корисно, якщо ви використовуєте інструменти ШІ для генерації ваших команд. +Паска має деякі обгортки помічників, які полегшують для ШІ генерацію команд. Ви можете використовувати `addOption` та `addArgument` у спосіб, подібний до Symfony Console. Це корисно, якщо ви використовуєте інструменти ШІ для генерації ваших команд. ```php public function __construct(array $config) { - parent::__construct('make:example', 'Create an example for the documentation', $config); + parent::__construct('make:example', 'Створити приклад для документації', $config); - // The mode argument is nullable and defaults to completely optional - $this->addOption('name', 'The name of the example', null); + // Аргумент mode є nullable і за замовчуванням повністю необов'язковим + $this->addOption('name', 'Назва прикладу', null); } ``` \ No newline at end of file diff --git a/content/v3/uk/learn/ai.md b/content/v3/uk/learn/ai.md index 34dd1a98..d9e1bfa8 100644 --- a/content/v3/uk/learn/ai.md +++ b/content/v3/uk/learn/ai.md @@ -1,14 +1,14 @@ -# AI та досвід розробника з Flight +# ШІ та досвід розробника з Flight ## Огляд -Flight полегшує суперзарядку ваших PHP-проектів за допомогою інструментів на основі штучного інтелекту та сучасних робочих процесів розробника. З вбудованими командами для підключення до постачальників LLM (Великі мовні моделі) та генерації інструкцій для кодування на основі AI, специфічних для проекту, Flight допомагає вам і вашій команді отримати максимум від AI-помічників, таких як GitHub Copilot, Cursor, Windsurf та Antigravity (Gemini). +Flight полегшує наділення ваших PHP-проектів інструментами на основі ШІ та сучасними робочими процесами розробників. З вбудованими командами для підключення до постачальників LLM (Large Language Model) та генерації інструкцій для кодування на основі ШІ, специфічних для проекту, Flight допомагає вам та вашій команді максимально використовувати ШІ-помічників, таких як GitHub Copilot, Cursor, Windsurf та Antigravity (Gemini). ## Розуміння -AI-помічники для кодування найбільш корисні, коли вони розуміють контекст вашого проекту, конвенції та цілі. AI-допоміжники Flight дозволяють вам: +ШІ-помічники для кодування найбільш корисні, коли вони розуміють контекст, конвенції та цілі вашого проекту. ШІ-допоміжники Flight дозволяють вам: - Підключити ваш проект до популярних постачальників LLM (OpenAI, Grok, Claude тощо) -- Генерувати та оновлювати інструкції, специфічні для проекту, для AI-інструментів, щоб кожен отримував послідовну, релевантну допомогу +- Генерувати та оновлювати інструкції, специфічні для проекту, для інструментів ШІ, щоб кожен отримував послідовну, релевантну допомогу - Зберігати вашу команду узгодженою та продуктивною, витрачаючи менше часу на пояснення контексту Ці функції вбудовані в основний CLI Flight та офіційний стартовий проект [flightphp/skeleton](https://github.com/flightphp/skeleton). @@ -24,7 +24,7 @@ php runway ai:init ``` Вам буде запропоновано: -- Вибрати вашого постачальника (OpenAI, Grok, Claude тощо) +- Вибрати постачальника (OpenAI, Grok, Claude тощо) - Ввести ваш API-ключ - Встановити базовий URL та назву моделі @@ -32,23 +32,23 @@ php runway ai:init **Приклад:** ``` -Ласкаво просимо до AI Init! -Який LLM API ви хочете використовувати? [1] openai, [2] grok, [3] claude: 1 -Введіть базовий URL для LLM API [https://api.openai.com]: -Введіть ваш API-ключ для openai: sk-... -Введіть назву моделі, яку ви хочете використовувати (наприклад, gpt-4, claude-3-opus тощо) [gpt-4o]: -Облікові дані збережено в .runway-creds.json +Welcome to AI Init! +Which LLM API do you want to use? [1] openai, [2] grok, [3] claude: 1 +Enter the base URL for the LLM API [https://api.openai.com]: +Enter your API key for openai: sk-... +Enter the model name you want to use (e.g. gpt-4, claude-3-opus, etc) [gpt-4o]: +Credentials saved to .runway-creds.json ``` -### Генерація інструкцій AI, специфічних для проекту +### Генерація інструкцій ШІ, специфічних для проекту -Команда `ai:generate-instructions` допомагає створити або оновити інструкції для AI-помічників кодування, адаптовані до вашого проекту. +Команда `ai:generate-instructions` допомагає створити або оновити інструкції для ШІ-помічників кодування, адаптовані до вашого проекту. ```bash php runway ai:generate-instructions ``` -Ви відповість на кілька питань про ваш проект (опис, база даних, шаблонізація, безпека, розмір команди тощо). Flight використовує вашого постачальника LLM для генерації інструкцій, а потім записує їх до: +Ви відповість на кілька питань про ваш проект (опис, база даних, шаблонізація, безпека, розмір команди тощо). Flight використовує ваш постачальник LLM для генерації інструкцій, а потім записує їх до: - `.github/copilot-instructions.md` (для GitHub Copilot) - `.cursor/rules/project-overview.mdc` (для Cursor) - `.windsurfrules` (для Windsurf) @@ -56,33 +56,33 @@ php runway ai:generate-instructions **Приклад:** ``` -Будь ласка, опишіть, для чого ваш проект? Мій чудовий API -Яку базу даних ви плануєте використовувати? MySQL -Який HTML-шаблонізатор ви плануєте використовувати (якщо є)? latte -Чи є безпека важливою частиною цього проекту? (y/n) y +Please describe what your project is for? My awesome API +What database are you planning on using? MySQL +What HTML templating engine will you plan on using (if any)? latte +Is security an important element of this project? (y/n) y ... -Інструкції AI успішно оновлено. +AI instructions updated successfully. ``` -Тепер ваші AI-інструменти надаватимуть розумніші, більш релевантні пропозиції на основі реальних потреб вашого проекту. +Тепер ваші інструменти ШІ надаватимуть розумніші, більш релевантні пропозиції на основі реальних потреб вашого проекту. ## Розширене використання - Ви можете налаштувати розташування файлів з обліковими даними або інструкціями за допомогою опцій команд (див. `--help` для кожної команди). -- AI-допоміжники розроблені для роботи з будь-яким постачальником LLM, який підтримує API, сумісні з OpenAI. -- Якщо ви хочете оновити інструкції з еволюцією вашого проекту, просто повторно запустіть `ai:generate-instructions` та відповідайте на запити знову. +- ШІ-допоміжники розроблені для роботи з будь-яким постачальником LLM, який підтримує API, сумісні з OpenAI. +- Якщо ви хочете оновити інструкції з еволюцією проекту, просто повторно запустіть `ai:generate-instructions` та відповістьте на запити знову. ## Див. також -- [Flight Skeleton](https://github.com/flightphp/skeleton) – Офіційний стартер з інтеграцією AI -- [Runway CLI](/awesome-plugins/runway) – Більше про CLI-інструмент, який живить ці команди +- [Flight Skeleton](https://github.com/flightphp/skeleton) – Офіційний стартер з інтеграцією ШІ +- [Runway CLI](/awesome-plugins/runway) – Більше про інструмент CLI, що живить ці команди ## Вирішення проблем - Якщо ви бачите "Missing .runway-creds.json", спочатку запустіть `php runway ai:init`. -- Переконайтеся, що ваш API-ключ дійсний і має доступ до вибраної моделі. -- Якщо інструкції не оновлюються, перевірте дозволи на файли в каталозі вашого проекту. +- Переконайтеся, що ваш API-ключ дійсний та має доступ до вибраної моделі. +- Якщо інструкції не оновлюються, перевірте дозволи файлів у каталозі проекту. ## Журнал змін -- v3.16.0 – Додано команди CLI `ai:init` та `ai:generate-instructions` для інтеграції AI. \ No newline at end of file +- v3.16.0 – Додано команди CLI `ai:init` та `ai:generate-instructions` для інтеграції ШІ. \ No newline at end of file diff --git a/content/v3/zh/about.md b/content/v3/zh/about.md index 947a0e2b..af7527a7 100644 --- a/content/v3/zh/about.md +++ b/content/v3/zh/about.md @@ -1,12 +1,14 @@ # Flight PHP 框架 -Flight 是一个快速、简单、可扩展的 PHP 框架——专为那些希望快速完成任务且不希望大费周章的开发人员而构建。不管您是在构建经典的网络应用、极速的 API,还是在试验最新的 AI 驱动工具,Flight 的低占用和直观设计使其成为完美选择。Flight 旨在保持精简,但也能满足企业架构需求。 +Flight 是一个快速、简单、可扩展的 PHP 框架——专为那些希望快速完成任务、零麻烦的开发者而构建。无论您是在构建经典 Web 应用、闪电般的 API,还是实验最新的 AI 驱动工具,Flight 的低资源占用和直观设计使其成为完美选择。Flight 旨在保持精简,但也能处理企业级架构需求。 ## 为什么选择 Flight? -- **适合初学者:** Flight 是新 PHP 开发人员的一个伟大起点。其清晰的结构和简单语法能帮助您学习网络开发,而不会迷失在样板代码中。 -- **专业人士喜爱:** 经验丰富的开发人员喜爱 Flight 的灵活性和控制性。您可以从小型原型扩展到功能齐全的应用,而无需切换框架。 -- **AI 友好:** Flight 的最小开销和干净架构使其非常适合集成 AI 工具和 API。不管您是在构建智能聊天机器人、AI 驱动的仪表板,还是只是想试验,Flight 会让您专注于重要事项。该 [skeleton app](https://github.com/flightphp/skeleton) 附带了主要 AI 编码助手的预构建说明文件![了解更多关于使用 AI 与 Flight](/learn/ai) +- **适合初学者:** Flight 是新 PHP 开发者的绝佳起点。其清晰的结构和简单的语法帮助您学习 Web 开发,而不会迷失在样板代码中。 +- **专业开发者喜爱:** 经验丰富的开发者喜爱 Flight 的灵活性和控制力。您可以从小型原型扩展到功能齐全的应用,而无需切换框架。 +- **向后兼容:** 我们重视您的时间。Flight v3 是 v2 的增强版本,保留了几乎所有相同的 API。我们相信进化而非革命——不再每次主要版本发布时“打破世界”。 +- **零依赖:** Flight 的核心完全无依赖——没有 polyfill,没有外部包,甚至没有 PSR 接口。这意味着更少的攻击向量、更小的资源占用,以及上游依赖带来的意外破坏性变更。可选插件可能包含依赖,但核心始终保持精简和安全。 +- **AI 导向:** Flight 的最小开销和干净架构使其非常适合集成 AI 工具和 API。无论您是在构建智能聊天机器人、AI 驱动的仪表板,还是只是想实验,Flight 不会妨碍您,让您专注于重要事项。[骨架应用](https://github.com/flightphp/skeleton) 开箱即用,带有主要 AI 编码助手的预构建指令文件![了解更多关于使用 AI 与 Flight](/learn/ai) ## 视频概述 @@ -16,16 +18,16 @@ Flight 是一个快速、简单、可扩展的 PHP 框架——专为那些希
          - 够简单,对吧? + 足够简单,对吧?
          了解更多 关于 Flight 的文档!
          -## 快速入门 +## 快速开始 -要进行快速的基本安装,请使用 Composer 安装: +要进行快速的裸机安装,请使用 Composer 安装: ```bash composer require flightphp/core @@ -36,9 +38,9 @@ composer require flightphp/core ```php 8 会给那些用户带来很多麻烦。该框架也支持 PHP >8。 +**注意:** 支持 PHP 7.4 是因为在撰写本文时(2024 年),PHP 7.4 是某些 LTS Linux 发行版的默认版本。强制升级到 PHP >8 会为那些用户带来很多麻烦。该框架也支持 PHP >8。 -# 许可 +# 许可证 -Flight 发布 under the [MIT](https://github.com/flightphp/core/blob/master/LICENSE) 许可。 \ No newline at end of file +Flight 根据 [MIT](https://github.com/flightphp/core/blob/master/LICENSE) 许可证发布。 \ No newline at end of file diff --git a/content/v3/zh/awesome-plugins/runway.md b/content/v3/zh/awesome-plugins/runway.md index f8ccdeef..ea83bb10 100644 --- a/content/v3/zh/awesome-plugins/runway.md +++ b/content/v3/zh/awesome-plugins/runway.md @@ -1,6 +1,6 @@ # Runway -Runway 是一个 CLI 应用程序,帮助您管理您的 Flight 应用程序。它可以生成控制器、显示所有路由等。它基于优秀的 [adhocore/php-cli](https://github.com/adhocore/php-cli) 库。 +Runway 是一个 CLI 应用程序,帮助您管理 Flight 应用程序。它可以生成控制器、显示所有路由等。它基于优秀的 [adhocore/php-cli](https://github.com/adhocore/php-cli) 库。 点击 [这里](https://github.com/flightphp/runway) 查看代码。 @@ -14,7 +14,7 @@ composer require flightphp/runway ## 基本配置 -首次运行 Runway 时,它将尝试在 `app/config/config.php` 中通过 `'runway'` 键查找 `runway` 配置。 +首次运行 Runway 时,它会尝试在 `app/config/config.php` 中通过 `'runway'` 键查找 `runway` 配置。 ```php Date: Tue, 20 Jan 2026 21:50:46 +0900 Subject: [PATCH 36/36] added EasyQueryBuilder and translated --- .../v3/de/awesome-plugins/awesome_plugins.md | 1 + content/v3/de/awesome-plugins/easy_query.md | 569 ++++++++++++++++++ .../v3/en/awesome-plugins/awesome_plugins.md | 1 + content/v3/en/awesome-plugins/easy_query.md | 569 ++++++++++++++++++ .../v3/es/awesome-plugins/awesome_plugins.md | 1 + content/v3/es/awesome-plugins/easy_query.md | 569 ++++++++++++++++++ .../v3/fr/awesome-plugins/awesome_plugins.md | 1 + content/v3/fr/awesome-plugins/easy_query.md | 569 ++++++++++++++++++ .../v3/id/awesome-plugins/awesome_plugins.md | 1 + content/v3/id/awesome-plugins/easy_query.md | 569 ++++++++++++++++++ .../v3/ja/awesome-plugins/awesome_plugins.md | 1 + content/v3/ja/awesome-plugins/easy_query.md | 569 ++++++++++++++++++ .../v3/ko/awesome-plugins/awesome_plugins.md | 1 + content/v3/ko/awesome-plugins/easy_query.md | 569 ++++++++++++++++++ .../v3/lv/awesome-plugins/awesome_plugins.md | 1 + content/v3/lv/awesome-plugins/easy_query.md | 569 ++++++++++++++++++ .../v3/pt/awesome-plugins/awesome_plugins.md | 1 + content/v3/pt/awesome-plugins/easy_query.md | 569 ++++++++++++++++++ .../v3/ru/awesome-plugins/awesome_plugins.md | 3 +- content/v3/ru/awesome-plugins/easy_query.md | 569 ++++++++++++++++++ .../v3/uk/awesome-plugins/awesome_plugins.md | 1 + content/v3/uk/awesome-plugins/easy_query.md | 569 ++++++++++++++++++ .../v3/zh/awesome-plugins/awesome_plugins.md | 1 + content/v3/zh/awesome-plugins/easy_query.md | 569 ++++++++++++++++++ 24 files changed, 6840 insertions(+), 2 deletions(-) create mode 100644 content/v3/de/awesome-plugins/easy_query.md create mode 100644 content/v3/en/awesome-plugins/easy_query.md create mode 100644 content/v3/es/awesome-plugins/easy_query.md create mode 100644 content/v3/fr/awesome-plugins/easy_query.md create mode 100644 content/v3/id/awesome-plugins/easy_query.md create mode 100644 content/v3/ja/awesome-plugins/easy_query.md create mode 100644 content/v3/ko/awesome-plugins/easy_query.md create mode 100644 content/v3/lv/awesome-plugins/easy_query.md create mode 100644 content/v3/pt/awesome-plugins/easy_query.md create mode 100644 content/v3/ru/awesome-plugins/easy_query.md create mode 100644 content/v3/uk/awesome-plugins/easy_query.md create mode 100644 content/v3/zh/awesome-plugins/easy_query.md diff --git a/content/v3/de/awesome-plugins/awesome_plugins.md b/content/v3/de/awesome-plugins/awesome_plugins.md index 2ade0256..fd8d3a02 100644 --- a/content/v3/de/awesome-plugins/awesome_plugins.md +++ b/content/v3/de/awesome-plugins/awesome_plugins.md @@ -65,6 +65,7 @@ Datenbanken sind der Kern der meisten Anwendungen. So speichern und rufen Sie Da - deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Offizieller Flight PDO-Wrapper, der zum Kern gehört (veraltet ab v3.18.0). Verwenden Sie stattdessen SimplePdo. - official [flightphp/active-record](/awesome-plugins/active-record) - Offizielles Flight ActiveRecord ORM/Mapper. Tolle kleine Bibliothek, um Daten einfach in Ihrer Datenbank abzurufen und zu speichern. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin, um alle Datenbankänderungen für Ihr Projekt zu verfolgen. +- [knifelemon/easy-query](/awesome-plugins/easy-query) - Leichter, fluent SQL Query Builder, der SQL und Parameter für Prepared Statements generiert. Funktioniert hervorragend mit [SimplePdo](/learn/simple-pdo). ## Encryption diff --git a/content/v3/de/awesome-plugins/easy_query.md b/content/v3/de/awesome-plugins/easy_query.md new file mode 100644 index 00000000..1bdbb88c --- /dev/null +++ b/content/v3/de/awesome-plugins/easy_query.md @@ -0,0 +1,569 @@ +# EasyQuery + +[knifelemon/easy-query](https://github.com/knifelemon/EasyQueryBuilder) ist ein leichtgewichtiger, fluenter SQL-Query-Builder, der SQL und Parameter für Prepared Statements generiert. Funktioniert mit [SimplePdo](/learn/simple-pdo). + +## Funktionen + +- 🔗 **Fluent API** - Verkettete Methoden für lesbare Query-Konstruktion +- 🛡️ **SQL-Injection-Schutz** - Automatische Parameter-Bindung mit Prepared Statements +- 🔧 **Raw SQL Support** - SQL-Ausdrücke direkt mit `raw()` einfügen +- 📝 **Mehrere Query-Typen** - SELECT, INSERT, UPDATE, DELETE, COUNT +- 🔀 **JOIN Support** - INNER, LEFT, RIGHT Joins mit Aliasen +- 🎯 **Erweiterte Bedingungen** - LIKE, IN, NOT IN, BETWEEN, Vergleichsoperatoren +- 🌐 **Datenbank-unabhängig** - Gibt SQL + Params zurück, nutzbar mit jeder DB-Verbindung +- 🪶 **Leichtgewichtig** - Minimaler Footprint ohne Abhängigkeiten + +## Installation + +```bash +composer require knifelemon/easy-query +``` + +## Schnellstart + +```php +use KnifeLemon\EasyQuery\Builder; + +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit(10) + ->build(); + +// Mit Flight's SimplePdo verwenden +$users = Flight::db()->fetchAll($q['sql'], $q['params']); +``` + +## build() verstehen + +Die `build()`-Methode gibt ein Array mit `sql` und `params` zurück. Diese Trennung schützt Ihre Datenbank durch Prepared Statements. + +```php +$q = Builder::table('users') + ->where(['email' => 'user@example.com']) + ->build(); + +// Rückgabe: +// [ +// 'sql' => 'SELECT * FROM users WHERE email = ?', +// 'params' => ['user@example.com'] +// ] +``` + +--- + +## Query-Typen + +### SELECT + +```php +// Alle Spalten auswählen +$q = Builder::table('users')->build(); +// SELECT * FROM users + +// Bestimmte Spalten auswählen +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->build(); +// SELECT id, name, email FROM users + +// Mit Tabellen-Alias +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name']) + ->build(); +// SELECT u.id, u.name FROM users AS u +``` + +### INSERT + +```php +$q = Builder::table('users') + ->insert([ + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'status' => 'active' + ]) + ->build(); +// INSERT INTO users SET name = ?, email = ?, status = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +$userId = Flight::db()->lastInsertId(); +``` + +### UPDATE + +```php +$q = Builder::table('users') + ->update(['status' => 'inactive', 'updated_at' => date('Y-m-d H:i:s')]) + ->where(['id' => 123]) + ->build(); +// UPDATE users SET status = ?, updated_at = ? WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### DELETE + +```php +$q = Builder::table('users') + ->delete() + ->where(['id' => 123]) + ->build(); +// DELETE FROM users WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### COUNT + +```php +$q = Builder::table('users') + ->count() + ->where(['status' => 'active']) + ->build(); +// SELECT COUNT(*) AS cnt FROM users WHERE status = ? + +$count = Flight::db()->fetchField($q['sql'], $q['params']); +``` + +--- + +## WHERE-Bedingungen + +### Einfache Gleichheit + +```php +$q = Builder::table('users') + ->where(['id' => 123, 'status' => 'active']) + ->build(); +// WHERE id = ? AND status = ? +``` + +### Vergleichsoperatoren + +```php +$q = Builder::table('users') + ->where([ + 'age' => ['>=', 18], + 'score' => ['<', 100], + 'name' => ['!=', 'admin'] + ]) + ->build(); +// WHERE age >= ? AND score < ? AND name != ? +``` + +### LIKE + +```php +$q = Builder::table('users') + ->where(['name' => ['LIKE', '%john%']]) + ->build(); +// WHERE name LIKE ? +``` + +### IN / NOT IN + +```php +// IN +$q = Builder::table('users') + ->where(['id' => ['IN', [1, 2, 3, 4, 5]]]) + ->build(); +// WHERE id IN (?, ?, ?, ?, ?) + +// NOT IN +$q = Builder::table('users') + ->where(['status' => ['NOT IN', ['banned', 'deleted']]]) + ->build(); +// WHERE status NOT IN (?, ?) +``` + +### BETWEEN + +```php +$q = Builder::table('products') + ->where(['price' => ['BETWEEN', [100, 500]]]) + ->build(); +// WHERE price BETWEEN ? AND ? +``` + +### OR-Bedingungen + +Verwenden Sie `orWhere()` um OR-gruppierte Bedingungen hinzuzufügen: + +```php +$q = Builder::table('users') + ->where(['status' => 'active']) + ->orWhere([ + 'role' => 'admin', + 'permissions' => ['LIKE', '%manage%'] + ]) + ->build(); +// WHERE status = ? AND (role = ? OR permissions LIKE ?) +``` + +--- + +## JOIN + +### INNER JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name', 'p.title']) + ->innerJoin('posts', 'u.id = p.user_id', 'p') + ->build(); +// SELECT u.id, u.name, p.title FROM users AS u INNER JOIN posts AS p ON u.id = p.user_id +``` + +### LEFT JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.name', 'o.total']) + ->leftJoin('orders', 'u.id = o.user_id', 'o') + ->build(); +// ... LEFT JOIN orders AS o ON u.id = o.user_id +``` + +### Mehrere JOINs + +```php +$q = Builder::table('orders') + ->alias('o') + ->select(['o.id', 'u.name AS customer', 'p.title AS product']) + ->innerJoin('users', 'o.user_id = u.id', 'u') + ->leftJoin('order_items', 'o.id = oi.order_id', 'oi') + ->leftJoin('products', 'oi.product_id = p.id', 'p') + ->where(['o.status' => 'completed']) + ->build(); +``` + +--- + +## Sortierung, Gruppierung und Limits + +### ORDER BY + +```php +$q = Builder::table('users') + ->orderBy('created_at DESC') + ->build(); +// ORDER BY created_at DESC +``` + +### GROUP BY + +```php +$q = Builder::table('orders') + ->select(['user_id', 'COUNT(*) as order_count']) + ->groupBy('user_id') + ->build(); +// SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id +``` + +### LIMIT und OFFSET + +```php +$q = Builder::table('users') + ->limit(10) + ->build(); +// LIMIT 10 + +$q = Builder::table('users') + ->limit(10, 20) // limit, offset + ->build(); +// LIMIT 10 OFFSET 20 +``` + +--- + +## Raw SQL-Ausdrücke + +Verwenden Sie `raw()` wenn Sie SQL-Funktionen oder Ausdrücke benötigen, die nicht als gebundene Parameter behandelt werden sollen. + +### Einfaches Raw + +```php +$q = Builder::table('users') + ->update([ + 'login_count' => Builder::raw('login_count + 1'), + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => 123]) + ->build(); +// SET login_count = login_count + 1, updated_at = NOW() +``` + +### Raw mit gebundenen Parametern + +```php +$q = Builder::table('orders') + ->update([ + 'total' => Builder::raw('COALESCE(subtotal, ?) + ?', [0, 10]) + ]) + ->where(['id' => 1]) + ->build(); +// SET total = COALESCE(subtotal, ?) + ? +// params: [0, 10, 1] +``` + +### Raw in WHERE (Subquery) + +```php +$q = Builder::table('products') + ->where([ + 'price' => ['>', Builder::raw('(SELECT AVG(price) FROM products)')] + ]) + ->build(); +// WHERE price > (SELECT AVG(price) FROM products) +``` + +### Sichere Identifier für Benutzereingaben + +Wenn Spaltennamen aus Benutzereingaben stammen, verwenden Sie `safeIdentifier()` um SQL-Injection zu verhindern: + +```php +$sortColumn = $_GET['sort']; // z.B. 'created_at' +$safeColumn = Builder::safeIdentifier($sortColumn); + +$q = Builder::table('users') + ->orderBy($safeColumn . ' DESC') + ->build(); + +// Wenn Benutzer versucht: "name; DROP TABLE users--" +// Wirft InvalidArgumentException +``` + +### rawSafe für benutzerdefinierte Spaltennamen + +```php +$userColumn = $_GET['aggregate_column']; + +$q = Builder::table('orders') + ->select([ + Builder::rawSafe('SUM({col})', ['col' => $userColumn])->value . ' AS total' + ]) + ->build(); +// Validiert Spaltennamen, wirft Ausnahme bei Ungültigkeit +``` + +> **Warnung:** Verketten Sie niemals Benutzereingaben direkt in `raw()`. Verwenden Sie immer gebundene Parameter oder `safeIdentifier()`. + +--- + +## Query-Builder-Wiederverwendung + +### Clear-Methoden + +Löschen Sie bestimmte Teile um den Builder wiederzuverwenden: + +```php +$query = Builder::table('users') + ->select(['id', 'name']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Erste Query +$q1 = $query->limit(10)->build(); + +// Löschen und wiederverwenden +$query->clearWhere()->clearLimit(); + +// Zweite Query mit anderen Bedingungen +$q2 = $query + ->where(['status' => 'pending']) + ->limit(5) + ->build(); +``` + +### Verfügbare Clear-Methoden + +| Methode | Beschreibung | +|---------|--------------| +| `clearWhere()` | WHERE-Bedingungen und Parameter löschen | +| `clearSelect()` | SELECT-Spalten auf Standard '*' zurücksetzen | +| `clearJoin()` | Alle JOIN-Klauseln löschen | +| `clearGroupBy()` | GROUP BY-Klausel löschen | +| `clearOrderBy()` | ORDER BY-Klausel löschen | +| `clearLimit()` | LIMIT und OFFSET löschen | +| `clearAll()` | Builder auf Anfangszustand zurücksetzen | + +### Paginierungs-Beispiel + +```php +$baseQuery = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Gesamtanzahl abrufen +$countQuery = clone $baseQuery; +$countResult = $countQuery->clearSelect()->count()->build(); +$total = Flight::db()->fetchField($countResult['sql'], $countResult['params']); + +// Paginierte Ergebnisse abrufen +$page = 1; +$perPage = 20; +$listResult = $baseQuery->limit($perPage, ($page - 1) * $perPage)->build(); +$users = Flight::db()->fetchAll($listResult['sql'], $listResult['params']); +``` + +--- + +## Dynamischer Query-Aufbau + +```php +$query = Builder::table('products')->alias('p'); + +if (!empty($categoryId)) { + $query->where(['p.category_id' => $categoryId]); +} + +if (!empty($minPrice)) { + $query->where(['p.price' => ['>=', $minPrice]]); +} + +if (!empty($maxPrice)) { + $query->where(['p.price' => ['<=', $maxPrice]]); +} + +if (!empty($searchTerm)) { + $query->where(['p.name' => ['LIKE', "%{$searchTerm}%"]]); +} + +$result = $query->orderBy('p.created_at DESC')->limit(20)->build(); +$products = Flight::db()->fetchAll($result['sql'], $result['params']); +``` + +--- + +## Vollständiges FlightPHP-Beispiel + +```php +use KnifeLemon\EasyQuery\Builder; + +// Benutzerliste mit Paginierung +Flight::route('GET /users', function() { + $page = (int) (Flight::request()->query['page'] ?? 1); + $perPage = 20; + + $q = Builder::table('users') + ->select(['id', 'name', 'email', 'created_at']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit($perPage, ($page - 1) * $perPage) + ->build(); + + $users = Flight::db()->fetchAll($q['sql'], $q['params']); + Flight::json(['users' => $users, 'page' => $page]); +}); + +// Benutzer erstellen +Flight::route('POST /users', function() { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->insert([ + 'name' => $data->name, + 'email' => $data->email, + 'created_at' => Builder::raw('NOW()') + ]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['id' => Flight::db()->lastInsertId()]); +}); + +// Benutzer aktualisieren +Flight::route('PUT /users/@id', function($id) { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->update([ + 'name' => $data->name, + 'email' => $data->email, + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); + +// Benutzer löschen +Flight::route('DELETE /users/@id', function($id) { + $q = Builder::table('users') + ->delete() + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); +``` + +--- + +## API-Referenz + +### Statische Methoden + +| Methode | Beschreibung | +|---------|--------------| +| `Builder::table(string $table)` | Neue Builder-Instanz für die Tabelle erstellen | +| `Builder::raw(string $sql, array $bindings = [])` | Raw SQL-Ausdruck erstellen | +| `Builder::rawSafe(string $expr, array $identifiers, array $bindings = [])` | Raw-Ausdruck mit sicherer Identifier-Substitution | +| `Builder::safeIdentifier(string $identifier)` | Sicheren Spalten-/Tabellennamen validieren und zurückgeben | + +### Instanz-Methoden + +| Methode | Beschreibung | +|---------|--------------| +| `alias(string $alias)` | Tabellen-Alias setzen | +| `select(string\|array $columns)` | Zu selektierende Spalten setzen (Standard: '*') | +| `where(array $conditions)` | WHERE-Bedingungen hinzufügen (AND) | +| `orWhere(array $conditions)` | OR WHERE-Bedingungen hinzufügen | +| `join(string $table, string $condition, string $alias, string $type)` | JOIN-Klausel hinzufügen | +| `innerJoin(string $table, string $condition, string $alias)` | INNER JOIN hinzufügen | +| `leftJoin(string $table, string $condition, string $alias)` | LEFT JOIN hinzufügen | +| `groupBy(string $groupBy)` | GROUP BY-Klausel hinzufügen | +| `orderBy(string $orderBy)` | ORDER BY-Klausel hinzufügen | +| `limit(int $limit, int $offset = 0)` | LIMIT und OFFSET hinzufügen | +| `count(string $column = '*')` | Query auf COUNT setzen | +| `insert(array $data)` | Query auf INSERT setzen | +| `update(array $data)` | Query auf UPDATE setzen | +| `delete()` | Query auf DELETE setzen | +| `build()` | `['sql' => ..., 'params' => ...]` bauen und zurückgeben | +| `get()` | Alias für `build()` | + +--- + +## Tracy-Debugger-Integration + +EasyQuery integriert sich automatisch mit Tracy Debugger, wenn installiert. Keine Einrichtung erforderlich! + +```bash +composer require tracy/tracy +``` + +```php +use Tracy\Debugger; + +Debugger::enable(); + +// Alle Queries werden automatisch im Tracy-Panel protokolliert +$q = Builder::table('users')->where(['status' => 'active'])->build(); +``` + +Das Tracy-Panel zeigt: +- Gesamtanzahl Queries und Aufschlüsselung nach Typ +- Generiertes SQL (Syntax-Highlighting) +- Parameter-Array +- Query-Details (Tabelle, where, joins, usw.) + +Vollständige Dokumentation im [GitHub Repository](https://github.com/knifelemon/EasyQueryBuilder). diff --git a/content/v3/en/awesome-plugins/awesome_plugins.md b/content/v3/en/awesome-plugins/awesome_plugins.md index 63a24edc..332329bd 100644 --- a/content/v3/en/awesome-plugins/awesome_plugins.md +++ b/content/v3/en/awesome-plugins/awesome_plugins.md @@ -65,6 +65,7 @@ Databases are the core to most applications. This is how you store and retrieve - deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Official Flight PDO Wrapper that's part of the core (deprecated as of v3.18.0). Use SimplePdo instead. - official [flightphp/active-record](/awesome-plugins/active-record) - Official Flight ActiveRecord ORM/Mapper. Great little library for easily retrieving and storing data in your database. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin to keep track of all database changes for your project. +- [knifelemon/easy-query](/awesome-plugins/easy-query) - Lightweight, fluent SQL query builder that generates SQL and parameters for prepared statements. Works great with [SimplePdo](/learn/simple-pdo). ## Encryption diff --git a/content/v3/en/awesome-plugins/easy_query.md b/content/v3/en/awesome-plugins/easy_query.md new file mode 100644 index 00000000..0f4eb4d5 --- /dev/null +++ b/content/v3/en/awesome-plugins/easy_query.md @@ -0,0 +1,569 @@ +# EasyQuery + +[knifelemon/easy-query](https://github.com/knifelemon/EasyQueryBuilder) is a lightweight, fluent SQL query builder that generates SQL and parameters for prepared statements. Works with [SimplePdo](/learn/simple-pdo). + +## Features + +- 🔗 **Fluent API** - Chain methods for readable query construction +- 🛡️ **SQL Injection Protection** - Automatic parameter binding with prepared statements +- 🔧 **Raw SQL Support** - Insert raw SQL expressions with `raw()` +- 📝 **Multiple Query Types** - SELECT, INSERT, UPDATE, DELETE, COUNT +- 🔀 **JOIN Support** - INNER, LEFT, RIGHT joins with aliases +- 🎯 **Advanced Conditions** - LIKE, IN, NOT IN, BETWEEN, comparison operators +- 🌐 **Database Agnostic** - Returns SQL + params, use with any DB connection +- 🪶 **Lightweight** - Minimal footprint with zero dependencies + +## Installation + +```bash +composer require knifelemon/easy-query +``` + +## Quick Start + +```php +use KnifeLemon\EasyQuery\Builder; + +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit(10) + ->build(); + +// Use with Flight's SimplePdo +$users = Flight::db()->fetchAll($q['sql'], $q['params']); +``` + +## Understanding build() + +The `build()` method returns an array with `sql` and `params`. This separation keeps your database safe by using prepared statements. + +```php +$q = Builder::table('users') + ->where(['email' => 'user@example.com']) + ->build(); + +// Returns: +// [ +// 'sql' => 'SELECT * FROM users WHERE email = ?', +// 'params' => ['user@example.com'] +// ] +``` + +--- + +## Query Types + +### SELECT + +```php +// Select all columns +$q = Builder::table('users')->build(); +// SELECT * FROM users + +// Select specific columns +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->build(); +// SELECT id, name, email FROM users + +// With table alias +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name']) + ->build(); +// SELECT u.id, u.name FROM users AS u +``` + +### INSERT + +```php +$q = Builder::table('users') + ->insert([ + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'status' => 'active' + ]) + ->build(); +// INSERT INTO users SET name = ?, email = ?, status = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +$userId = Flight::db()->lastInsertId(); +``` + +### UPDATE + +```php +$q = Builder::table('users') + ->update(['status' => 'inactive', 'updated_at' => date('Y-m-d H:i:s')]) + ->where(['id' => 123]) + ->build(); +// UPDATE users SET status = ?, updated_at = ? WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### DELETE + +```php +$q = Builder::table('users') + ->delete() + ->where(['id' => 123]) + ->build(); +// DELETE FROM users WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### COUNT + +```php +$q = Builder::table('users') + ->count() + ->where(['status' => 'active']) + ->build(); +// SELECT COUNT(*) AS cnt FROM users WHERE status = ? + +$count = Flight::db()->fetchField($q['sql'], $q['params']); +``` + +--- + +## WHERE Conditions + +### Simple Equality + +```php +$q = Builder::table('users') + ->where(['id' => 123, 'status' => 'active']) + ->build(); +// WHERE id = ? AND status = ? +``` + +### Comparison Operators + +```php +$q = Builder::table('users') + ->where([ + 'age' => ['>=', 18], + 'score' => ['<', 100], + 'name' => ['!=', 'admin'] + ]) + ->build(); +// WHERE age >= ? AND score < ? AND name != ? +``` + +### LIKE + +```php +$q = Builder::table('users') + ->where(['name' => ['LIKE', '%john%']]) + ->build(); +// WHERE name LIKE ? +``` + +### IN / NOT IN + +```php +// IN +$q = Builder::table('users') + ->where(['id' => ['IN', [1, 2, 3, 4, 5]]]) + ->build(); +// WHERE id IN (?, ?, ?, ?, ?) + +// NOT IN +$q = Builder::table('users') + ->where(['status' => ['NOT IN', ['banned', 'deleted']]]) + ->build(); +// WHERE status NOT IN (?, ?) +``` + +### BETWEEN + +```php +$q = Builder::table('products') + ->where(['price' => ['BETWEEN', [100, 500]]]) + ->build(); +// WHERE price BETWEEN ? AND ? +``` + +### OR Conditions + +Use `orWhere()` to add OR grouped conditions: + +```php +$q = Builder::table('users') + ->where(['status' => 'active']) + ->orWhere([ + 'role' => 'admin', + 'permissions' => ['LIKE', '%manage%'] + ]) + ->build(); +// WHERE status = ? AND (role = ? OR permissions LIKE ?) +``` + +--- + +## JOIN + +### INNER JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name', 'p.title']) + ->innerJoin('posts', 'u.id = p.user_id', 'p') + ->build(); +// SELECT u.id, u.name, p.title FROM users AS u INNER JOIN posts AS p ON u.id = p.user_id +``` + +### LEFT JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.name', 'o.total']) + ->leftJoin('orders', 'u.id = o.user_id', 'o') + ->build(); +// ... LEFT JOIN orders AS o ON u.id = o.user_id +``` + +### Multiple JOINs + +```php +$q = Builder::table('orders') + ->alias('o') + ->select(['o.id', 'u.name AS customer', 'p.title AS product']) + ->innerJoin('users', 'o.user_id = u.id', 'u') + ->leftJoin('order_items', 'o.id = oi.order_id', 'oi') + ->leftJoin('products', 'oi.product_id = p.id', 'p') + ->where(['o.status' => 'completed']) + ->build(); +``` + +--- + +## Ordering, Grouping, and Limits + +### ORDER BY + +```php +$q = Builder::table('users') + ->orderBy('created_at DESC') + ->build(); +// ORDER BY created_at DESC +``` + +### GROUP BY + +```php +$q = Builder::table('orders') + ->select(['user_id', 'COUNT(*) as order_count']) + ->groupBy('user_id') + ->build(); +// SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id +``` + +### LIMIT and OFFSET + +```php +$q = Builder::table('users') + ->limit(10) + ->build(); +// LIMIT 10 + +$q = Builder::table('users') + ->limit(10, 20) // limit, offset + ->build(); +// LIMIT 10 OFFSET 20 +``` + +--- + +## Raw SQL Expressions + +Use `raw()` when you need SQL functions or expressions that shouldn't be treated as bound parameters. + +### Basic Raw + +```php +$q = Builder::table('users') + ->update([ + 'login_count' => Builder::raw('login_count + 1'), + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => 123]) + ->build(); +// SET login_count = login_count + 1, updated_at = NOW() +``` + +### Raw with Bound Parameters + +```php +$q = Builder::table('orders') + ->update([ + 'total' => Builder::raw('COALESCE(subtotal, ?) + ?', [0, 10]) + ]) + ->where(['id' => 1]) + ->build(); +// SET total = COALESCE(subtotal, ?) + ? +// params: [0, 10, 1] +``` + +### Raw in WHERE (Subquery) + +```php +$q = Builder::table('products') + ->where([ + 'price' => ['>', Builder::raw('(SELECT AVG(price) FROM products)')] + ]) + ->build(); +// WHERE price > (SELECT AVG(price) FROM products) +``` + +### Safe Identifiers for User Input + +When column names come from user input, use `safeIdentifier()` to prevent SQL injection: + +```php +$sortColumn = $_GET['sort']; // e.g., 'created_at' +$safeColumn = Builder::safeIdentifier($sortColumn); + +$q = Builder::table('users') + ->orderBy($safeColumn . ' DESC') + ->build(); + +// If user tries: "name; DROP TABLE users--" +// Throws InvalidArgumentException +``` + +### rawSafe for User-Provided Column Names + +```php +$userColumn = $_GET['aggregate_column']; + +$q = Builder::table('orders') + ->select([ + Builder::rawSafe('SUM({col})', ['col' => $userColumn])->value . ' AS total' + ]) + ->build(); +// Validates column name, throws exception if invalid +``` + +> **Warning:** Never concatenate user input directly into `raw()`. Always use bound parameters or `safeIdentifier()`. + +--- + +## Query Builder Reuse + +### Clear Methods + +Clear specific parts to reuse the builder: + +```php +$query = Builder::table('users') + ->select(['id', 'name']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// First query +$q1 = $query->limit(10)->build(); + +// Clear and reuse +$query->clearWhere()->clearLimit(); + +// Second query with different conditions +$q2 = $query + ->where(['status' => 'pending']) + ->limit(5) + ->build(); +``` + +### Available Clear Methods + +| Method | Description | +|--------|-------------| +| `clearWhere()` | Clear WHERE conditions and parameters | +| `clearSelect()` | Reset SELECT columns to default '*' | +| `clearJoin()` | Clear all JOIN clauses | +| `clearGroupBy()` | Clear GROUP BY clause | +| `clearOrderBy()` | Clear ORDER BY clause | +| `clearLimit()` | Clear LIMIT and OFFSET | +| `clearAll()` | Reset builder to initial state | + +### Pagination Example + +```php +$baseQuery = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Get total count +$countQuery = clone $baseQuery; +$countResult = $countQuery->clearSelect()->count()->build(); +$total = Flight::db()->fetchField($countResult['sql'], $countResult['params']); + +// Get paginated results +$page = 1; +$perPage = 20; +$listResult = $baseQuery->limit($perPage, ($page - 1) * $perPage)->build(); +$users = Flight::db()->fetchAll($listResult['sql'], $listResult['params']); +``` + +--- + +## Dynamic Query Building + +```php +$query = Builder::table('products')->alias('p'); + +if (!empty($categoryId)) { + $query->where(['p.category_id' => $categoryId]); +} + +if (!empty($minPrice)) { + $query->where(['p.price' => ['>=', $minPrice]]); +} + +if (!empty($maxPrice)) { + $query->where(['p.price' => ['<=', $maxPrice]]); +} + +if (!empty($searchTerm)) { + $query->where(['p.name' => ['LIKE', "%{$searchTerm}%"]]); +} + +$result = $query->orderBy('p.created_at DESC')->limit(20)->build(); +$products = Flight::db()->fetchAll($result['sql'], $result['params']); +``` + +--- + +## Full FlightPHP Example + +```php +use KnifeLemon\EasyQuery\Builder; + +// List users with pagination +Flight::route('GET /users', function() { + $page = (int) (Flight::request()->query['page'] ?? 1); + $perPage = 20; + + $q = Builder::table('users') + ->select(['id', 'name', 'email', 'created_at']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit($perPage, ($page - 1) * $perPage) + ->build(); + + $users = Flight::db()->fetchAll($q['sql'], $q['params']); + Flight::json(['users' => $users, 'page' => $page]); +}); + +// Create user +Flight::route('POST /users', function() { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->insert([ + 'name' => $data->name, + 'email' => $data->email, + 'created_at' => Builder::raw('NOW()') + ]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['id' => Flight::db()->lastInsertId()]); +}); + +// Update user +Flight::route('PUT /users/@id', function($id) { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->update([ + 'name' => $data->name, + 'email' => $data->email, + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); + +// Delete user +Flight::route('DELETE /users/@id', function($id) { + $q = Builder::table('users') + ->delete() + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); +``` + +--- + +## API Reference + +### Static Methods + +| Method | Description | +|--------|-------------| +| `Builder::table(string $table)` | Create a new builder instance for the table | +| `Builder::raw(string $sql, array $bindings = [])` | Create a raw SQL expression | +| `Builder::rawSafe(string $expr, array $identifiers, array $bindings = [])` | Raw expression with safe identifier substitution | +| `Builder::safeIdentifier(string $identifier)` | Validate and return a safe column/table name | + +### Instance Methods + +| Method | Description | +|--------|-------------| +| `alias(string $alias)` | Set table alias | +| `select(string\|array $columns)` | Set columns to select (default: '*') | +| `where(array $conditions)` | Add WHERE conditions (AND) | +| `orWhere(array $conditions)` | Add OR WHERE conditions | +| `join(string $table, string $condition, string $alias, string $type)` | Add JOIN clause | +| `innerJoin(string $table, string $condition, string $alias)` | Add INNER JOIN | +| `leftJoin(string $table, string $condition, string $alias)` | Add LEFT JOIN | +| `groupBy(string $groupBy)` | Add GROUP BY clause | +| `orderBy(string $orderBy)` | Add ORDER BY clause | +| `limit(int $limit, int $offset = 0)` | Add LIMIT and OFFSET | +| `count(string $column = '*')` | Set query to COUNT | +| `insert(array $data)` | Set query to INSERT | +| `update(array $data)` | Set query to UPDATE | +| `delete()` | Set query to DELETE | +| `build()` | Build and return `['sql' => ..., 'params' => ...]` | +| `get()` | Alias for `build()` | + +--- + +## Tracy Debugger Integration + +EasyQuery automatically integrates with Tracy Debugger if installed. No setup required! + +```bash +composer require tracy/tracy +``` + +```php +use Tracy\Debugger; + +Debugger::enable(); + +// All queries are automatically logged to Tracy panel +$q = Builder::table('users')->where(['status' => 'active'])->build(); +``` + +The Tracy panel shows: +- Total queries and breakdown by type +- Generated SQL (syntax highlighted) +- Parameters array +- Query details (table, where, joins, etc.) + +For full documentation, visit the [GitHub repository](https://github.com/knifelemon/EasyQueryBuilder). diff --git a/content/v3/es/awesome-plugins/awesome_plugins.md b/content/v3/es/awesome-plugins/awesome_plugins.md index c9791739..94955f70 100644 --- a/content/v3/es/awesome-plugins/awesome_plugins.md +++ b/content/v3/es/awesome-plugins/awesome_plugins.md @@ -65,6 +65,7 @@ Las bases de datos son el núcleo de la mayoría de las aplicaciones. Así es co - deprecado [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper oficial de PDO de Flight que forma parte del núcleo (deprecado a partir de v3.18.0). Usa SimplePdo en su lugar. - oficial [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper oficial de ActiveRecord de Flight. Gran biblioteca pequeña para recuperar y almacenar datos fácilmente en tu base de datos. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin para rastrear todos los cambios de base de datos para tu proyecto. +- [knifelemon/easy-query](/awesome-plugins/easy-query) - Constructor de consultas SQL ligero y fluido que genera SQL y parámetros para sentencias preparadas. Funciona muy bien con [SimplePdo](/learn/simple-pdo). ## Encriptación diff --git a/content/v3/es/awesome-plugins/easy_query.md b/content/v3/es/awesome-plugins/easy_query.md new file mode 100644 index 00000000..886cbb41 --- /dev/null +++ b/content/v3/es/awesome-plugins/easy_query.md @@ -0,0 +1,569 @@ +# EasyQuery + +[knifelemon/easy-query](https://github.com/knifelemon/EasyQueryBuilder) es un constructor de consultas SQL ligero y fluido que genera SQL y parámetros para sentencias preparadas. Funciona con [SimplePdo](/learn/simple-pdo). + +## Características + +- 🔗 **API Fluida** - Métodos encadenados para construcción de consultas legibles +- 🛡️ **Protección contra Inyección SQL** - Vinculación automática de parámetros con sentencias preparadas +- 🔧 **Soporte Raw SQL** - Insertar expresiones SQL directamente con `raw()` +- 📝 **Múltiples Tipos de Consulta** - SELECT, INSERT, UPDATE, DELETE, COUNT +- 🔀 **Soporte JOIN** - INNER, LEFT, RIGHT joins con alias +- 🎯 **Condiciones Avanzadas** - LIKE, IN, NOT IN, BETWEEN, operadores de comparación +- 🌐 **Agnóstico de Base de Datos** - Devuelve SQL + params, úsalo con cualquier conexión DB +- 🪶 **Ligero** - Huella mínima sin dependencias + +## Instalación + +```bash +composer require knifelemon/easy-query +``` + +## Inicio Rápido + +```php +use KnifeLemon\EasyQuery\Builder; + +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit(10) + ->build(); + +// Usar con SimplePdo de Flight +$users = Flight::db()->fetchAll($q['sql'], $q['params']); +``` + +## Entendiendo build() + +El método `build()` devuelve un array con `sql` y `params`. Esta separación mantiene tu base de datos segura usando sentencias preparadas. + +```php +$q = Builder::table('users') + ->where(['email' => 'user@example.com']) + ->build(); + +// Devuelve: +// [ +// 'sql' => 'SELECT * FROM users WHERE email = ?', +// 'params' => ['user@example.com'] +// ] +``` + +--- + +## Tipos de Consulta + +### SELECT + +```php +// Seleccionar todas las columnas +$q = Builder::table('users')->build(); +// SELECT * FROM users + +// Seleccionar columnas específicas +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->build(); +// SELECT id, name, email FROM users + +// Con alias de tabla +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name']) + ->build(); +// SELECT u.id, u.name FROM users AS u +``` + +### INSERT + +```php +$q = Builder::table('users') + ->insert([ + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'status' => 'active' + ]) + ->build(); +// INSERT INTO users SET name = ?, email = ?, status = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +$userId = Flight::db()->lastInsertId(); +``` + +### UPDATE + +```php +$q = Builder::table('users') + ->update(['status' => 'inactive', 'updated_at' => date('Y-m-d H:i:s')]) + ->where(['id' => 123]) + ->build(); +// UPDATE users SET status = ?, updated_at = ? WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### DELETE + +```php +$q = Builder::table('users') + ->delete() + ->where(['id' => 123]) + ->build(); +// DELETE FROM users WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### COUNT + +```php +$q = Builder::table('users') + ->count() + ->where(['status' => 'active']) + ->build(); +// SELECT COUNT(*) AS cnt FROM users WHERE status = ? + +$count = Flight::db()->fetchField($q['sql'], $q['params']); +``` + +--- + +## Condiciones WHERE + +### Igualdad Simple + +```php +$q = Builder::table('users') + ->where(['id' => 123, 'status' => 'active']) + ->build(); +// WHERE id = ? AND status = ? +``` + +### Operadores de Comparación + +```php +$q = Builder::table('users') + ->where([ + 'age' => ['>=', 18], + 'score' => ['<', 100], + 'name' => ['!=', 'admin'] + ]) + ->build(); +// WHERE age >= ? AND score < ? AND name != ? +``` + +### LIKE + +```php +$q = Builder::table('users') + ->where(['name' => ['LIKE', '%john%']]) + ->build(); +// WHERE name LIKE ? +``` + +### IN / NOT IN + +```php +// IN +$q = Builder::table('users') + ->where(['id' => ['IN', [1, 2, 3, 4, 5]]]) + ->build(); +// WHERE id IN (?, ?, ?, ?, ?) + +// NOT IN +$q = Builder::table('users') + ->where(['status' => ['NOT IN', ['banned', 'deleted']]]) + ->build(); +// WHERE status NOT IN (?, ?) +``` + +### BETWEEN + +```php +$q = Builder::table('products') + ->where(['price' => ['BETWEEN', [100, 500]]]) + ->build(); +// WHERE price BETWEEN ? AND ? +``` + +### Condiciones OR + +Usa `orWhere()` para añadir condiciones agrupadas con OR: + +```php +$q = Builder::table('users') + ->where(['status' => 'active']) + ->orWhere([ + 'role' => 'admin', + 'permissions' => ['LIKE', '%manage%'] + ]) + ->build(); +// WHERE status = ? AND (role = ? OR permissions LIKE ?) +``` + +--- + +## JOIN + +### INNER JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name', 'p.title']) + ->innerJoin('posts', 'u.id = p.user_id', 'p') + ->build(); +// SELECT u.id, u.name, p.title FROM users AS u INNER JOIN posts AS p ON u.id = p.user_id +``` + +### LEFT JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.name', 'o.total']) + ->leftJoin('orders', 'u.id = o.user_id', 'o') + ->build(); +// ... LEFT JOIN orders AS o ON u.id = o.user_id +``` + +### Múltiples JOINs + +```php +$q = Builder::table('orders') + ->alias('o') + ->select(['o.id', 'u.name AS customer', 'p.title AS product']) + ->innerJoin('users', 'o.user_id = u.id', 'u') + ->leftJoin('order_items', 'o.id = oi.order_id', 'oi') + ->leftJoin('products', 'oi.product_id = p.id', 'p') + ->where(['o.status' => 'completed']) + ->build(); +``` + +--- + +## Ordenamiento, Agrupación y Límites + +### ORDER BY + +```php +$q = Builder::table('users') + ->orderBy('created_at DESC') + ->build(); +// ORDER BY created_at DESC +``` + +### GROUP BY + +```php +$q = Builder::table('orders') + ->select(['user_id', 'COUNT(*) as order_count']) + ->groupBy('user_id') + ->build(); +// SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id +``` + +### LIMIT y OFFSET + +```php +$q = Builder::table('users') + ->limit(10) + ->build(); +// LIMIT 10 + +$q = Builder::table('users') + ->limit(10, 20) // limit, offset + ->build(); +// LIMIT 10 OFFSET 20 +``` + +--- + +## Expresiones Raw SQL + +Usa `raw()` cuando necesites funciones SQL o expresiones que no deben tratarse como parámetros vinculados. + +### Raw Básico + +```php +$q = Builder::table('users') + ->update([ + 'login_count' => Builder::raw('login_count + 1'), + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => 123]) + ->build(); +// SET login_count = login_count + 1, updated_at = NOW() +``` + +### Raw con Parámetros Vinculados + +```php +$q = Builder::table('orders') + ->update([ + 'total' => Builder::raw('COALESCE(subtotal, ?) + ?', [0, 10]) + ]) + ->where(['id' => 1]) + ->build(); +// SET total = COALESCE(subtotal, ?) + ? +// params: [0, 10, 1] +``` + +### Raw en WHERE (Subconsulta) + +```php +$q = Builder::table('products') + ->where([ + 'price' => ['>', Builder::raw('(SELECT AVG(price) FROM products)')] + ]) + ->build(); +// WHERE price > (SELECT AVG(price) FROM products) +``` + +### Identificadores Seguros para Entrada de Usuario + +Cuando los nombres de columna vienen de entrada de usuario, usa `safeIdentifier()` para prevenir inyección SQL: + +```php +$sortColumn = $_GET['sort']; // ej: 'created_at' +$safeColumn = Builder::safeIdentifier($sortColumn); + +$q = Builder::table('users') + ->orderBy($safeColumn . ' DESC') + ->build(); + +// Si el usuario intenta: "name; DROP TABLE users--" +// Lanza InvalidArgumentException +``` + +### rawSafe para Nombres de Columna del Usuario + +```php +$userColumn = $_GET['aggregate_column']; + +$q = Builder::table('orders') + ->select([ + Builder::rawSafe('SUM({col})', ['col' => $userColumn])->value . ' AS total' + ]) + ->build(); +// Valida el nombre de columna, lanza excepción si es inválido +``` + +> **Advertencia:** Nunca concatenes entrada de usuario directamente en `raw()`. Siempre usa parámetros vinculados o `safeIdentifier()`. + +--- + +## Reutilización del Query Builder + +### Métodos Clear + +Limpia partes específicas para reutilizar el builder: + +```php +$query = Builder::table('users') + ->select(['id', 'name']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Primera consulta +$q1 = $query->limit(10)->build(); + +// Limpiar y reutilizar +$query->clearWhere()->clearLimit(); + +// Segunda consulta con diferentes condiciones +$q2 = $query + ->where(['status' => 'pending']) + ->limit(5) + ->build(); +``` + +### Métodos Clear Disponibles + +| Método | Descripción | +|--------|-------------| +| `clearWhere()` | Limpiar condiciones WHERE y parámetros | +| `clearSelect()` | Resetear columnas SELECT al predeterminado '*' | +| `clearJoin()` | Limpiar todas las cláusulas JOIN | +| `clearGroupBy()` | Limpiar cláusula GROUP BY | +| `clearOrderBy()` | Limpiar cláusula ORDER BY | +| `clearLimit()` | Limpiar LIMIT y OFFSET | +| `clearAll()` | Resetear builder al estado inicial | + +### Ejemplo de Paginación + +```php +$baseQuery = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Obtener conteo total +$countQuery = clone $baseQuery; +$countResult = $countQuery->clearSelect()->count()->build(); +$total = Flight::db()->fetchField($countResult['sql'], $countResult['params']); + +// Obtener resultados paginados +$page = 1; +$perPage = 20; +$listResult = $baseQuery->limit($perPage, ($page - 1) * $perPage)->build(); +$users = Flight::db()->fetchAll($listResult['sql'], $listResult['params']); +``` + +--- + +## Construcción Dinámica de Consultas + +```php +$query = Builder::table('products')->alias('p'); + +if (!empty($categoryId)) { + $query->where(['p.category_id' => $categoryId]); +} + +if (!empty($minPrice)) { + $query->where(['p.price' => ['>=', $minPrice]]); +} + +if (!empty($maxPrice)) { + $query->where(['p.price' => ['<=', $maxPrice]]); +} + +if (!empty($searchTerm)) { + $query->where(['p.name' => ['LIKE', "%{$searchTerm}%"]]); +} + +$result = $query->orderBy('p.created_at DESC')->limit(20)->build(); +$products = Flight::db()->fetchAll($result['sql'], $result['params']); +``` + +--- + +## Ejemplo Completo FlightPHP + +```php +use KnifeLemon\EasyQuery\Builder; + +// Listar usuarios con paginación +Flight::route('GET /users', function() { + $page = (int) (Flight::request()->query['page'] ?? 1); + $perPage = 20; + + $q = Builder::table('users') + ->select(['id', 'name', 'email', 'created_at']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit($perPage, ($page - 1) * $perPage) + ->build(); + + $users = Flight::db()->fetchAll($q['sql'], $q['params']); + Flight::json(['users' => $users, 'page' => $page]); +}); + +// Crear usuario +Flight::route('POST /users', function() { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->insert([ + 'name' => $data->name, + 'email' => $data->email, + 'created_at' => Builder::raw('NOW()') + ]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['id' => Flight::db()->lastInsertId()]); +}); + +// Actualizar usuario +Flight::route('PUT /users/@id', function($id) { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->update([ + 'name' => $data->name, + 'email' => $data->email, + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); + +// Eliminar usuario +Flight::route('DELETE /users/@id', function($id) { + $q = Builder::table('users') + ->delete() + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); +``` + +--- + +## Referencia API + +### Métodos Estáticos + +| Método | Descripción | +|--------|-------------| +| `Builder::table(string $table)` | Crear nueva instancia del builder para la tabla | +| `Builder::raw(string $sql, array $bindings = [])` | Crear expresión SQL raw | +| `Builder::rawSafe(string $expr, array $identifiers, array $bindings = [])` | Expresión raw con sustitución segura de identificadores | +| `Builder::safeIdentifier(string $identifier)` | Validar y devolver nombre seguro de columna/tabla | + +### Métodos de Instancia + +| Método | Descripción | +|--------|-------------| +| `alias(string $alias)` | Establecer alias de tabla | +| `select(string\|array $columns)` | Establecer columnas a seleccionar (predeterminado: '*') | +| `where(array $conditions)` | Añadir condiciones WHERE (AND) | +| `orWhere(array $conditions)` | Añadir condiciones OR WHERE | +| `join(string $table, string $condition, string $alias, string $type)` | Añadir cláusula JOIN | +| `innerJoin(string $table, string $condition, string $alias)` | Añadir INNER JOIN | +| `leftJoin(string $table, string $condition, string $alias)` | Añadir LEFT JOIN | +| `groupBy(string $groupBy)` | Añadir cláusula GROUP BY | +| `orderBy(string $orderBy)` | Añadir cláusula ORDER BY | +| `limit(int $limit, int $offset = 0)` | Añadir LIMIT y OFFSET | +| `count(string $column = '*')` | Establecer consulta a COUNT | +| `insert(array $data)` | Establecer consulta a INSERT | +| `update(array $data)` | Establecer consulta a UPDATE | +| `delete()` | Establecer consulta a DELETE | +| `build()` | Construir y devolver `['sql' => ..., 'params' => ...]` | +| `get()` | Alias de `build()` | + +--- + +## Integración con Tracy Debugger + +EasyQuery se integra automáticamente con Tracy Debugger si está instalado. ¡Sin configuración necesaria! + +```bash +composer require tracy/tracy +``` + +```php +use Tracy\Debugger; + +Debugger::enable(); + +// Todas las consultas se registran automáticamente en el panel Tracy +$q = Builder::table('users')->where(['status' => 'active'])->build(); +``` + +El panel Tracy muestra: +- Total de consultas y desglose por tipo +- SQL generado (resaltado de sintaxis) +- Array de parámetros +- Detalles de consulta (tabla, where, joins, etc.) + +Para documentación completa, visita el [repositorio GitHub](https://github.com/knifelemon/EasyQueryBuilder). diff --git a/content/v3/fr/awesome-plugins/awesome_plugins.md b/content/v3/fr/awesome-plugins/awesome_plugins.md index 514955e2..e88c9da7 100644 --- a/content/v3/fr/awesome-plugins/awesome_plugins.md +++ b/content/v3/fr/awesome-plugins/awesome_plugins.md @@ -65,6 +65,7 @@ Les bases de données sont au cœur de la plupart des applications. C'est ainsi - déprécié [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper officiel Flight PDO qui fait partie du core (déprécié depuis la v3.18.0). Utilisez SimplePdo à la place. - officiel [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper officiel Flight ActiveRecord. Excellente petite bibliothèque pour récupérer et stocker facilement des données dans votre base de données. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin pour suivre toutes les modifications de base de données pour votre projet. +- [knifelemon/easy-query](/awesome-plugins/easy-query) - Constructeur de requêtes SQL léger et fluent qui génère du SQL et des paramètres pour les instructions préparées. Fonctionne très bien avec [SimplePdo](/learn/simple-pdo). ## Chiffrement diff --git a/content/v3/fr/awesome-plugins/easy_query.md b/content/v3/fr/awesome-plugins/easy_query.md new file mode 100644 index 00000000..b3ee2576 --- /dev/null +++ b/content/v3/fr/awesome-plugins/easy_query.md @@ -0,0 +1,569 @@ +# EasyQuery + +[knifelemon/easy-query](https://github.com/knifelemon/EasyQueryBuilder) est un constructeur de requêtes SQL léger et fluide qui génère du SQL et des paramètres pour les requêtes préparées. Fonctionne avec [SimplePdo](/learn/simple-pdo). + +## Fonctionnalités + +- 🔗 **API Fluide** - Méthodes chaînées pour une construction de requêtes lisible +- 🛡️ **Protection contre l'Injection SQL** - Liaison automatique des paramètres avec les requêtes préparées +- 🔧 **Support Raw SQL** - Insérer des expressions SQL directement avec `raw()` +- 📝 **Types de Requêtes Multiples** - SELECT, INSERT, UPDATE, DELETE, COUNT +- 🔀 **Support JOIN** - INNER, LEFT, RIGHT joins avec alias +- 🎯 **Conditions Avancées** - LIKE, IN, NOT IN, BETWEEN, opérateurs de comparaison +- 🌐 **Agnostique de Base de Données** - Retourne SQL + params, utilisable avec n'importe quelle connexion DB +- 🪶 **Léger** - Empreinte minimale sans dépendances + +## Installation + +```bash +composer require knifelemon/easy-query +``` + +## Démarrage Rapide + +```php +use KnifeLemon\EasyQuery\Builder; + +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit(10) + ->build(); + +// Utiliser avec SimplePdo de Flight +$users = Flight::db()->fetchAll($q['sql'], $q['params']); +``` + +## Comprendre build() + +La méthode `build()` retourne un tableau avec `sql` et `params`. Cette séparation protège votre base de données en utilisant des requêtes préparées. + +```php +$q = Builder::table('users') + ->where(['email' => 'user@example.com']) + ->build(); + +// Retourne: +// [ +// 'sql' => 'SELECT * FROM users WHERE email = ?', +// 'params' => ['user@example.com'] +// ] +``` + +--- + +## Types de Requêtes + +### SELECT + +```php +// Sélectionner toutes les colonnes +$q = Builder::table('users')->build(); +// SELECT * FROM users + +// Sélectionner des colonnes spécifiques +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->build(); +// SELECT id, name, email FROM users + +// Avec alias de table +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name']) + ->build(); +// SELECT u.id, u.name FROM users AS u +``` + +### INSERT + +```php +$q = Builder::table('users') + ->insert([ + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'status' => 'active' + ]) + ->build(); +// INSERT INTO users SET name = ?, email = ?, status = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +$userId = Flight::db()->lastInsertId(); +``` + +### UPDATE + +```php +$q = Builder::table('users') + ->update(['status' => 'inactive', 'updated_at' => date('Y-m-d H:i:s')]) + ->where(['id' => 123]) + ->build(); +// UPDATE users SET status = ?, updated_at = ? WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### DELETE + +```php +$q = Builder::table('users') + ->delete() + ->where(['id' => 123]) + ->build(); +// DELETE FROM users WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### COUNT + +```php +$q = Builder::table('users') + ->count() + ->where(['status' => 'active']) + ->build(); +// SELECT COUNT(*) AS cnt FROM users WHERE status = ? + +$count = Flight::db()->fetchField($q['sql'], $q['params']); +``` + +--- + +## Conditions WHERE + +### Égalité Simple + +```php +$q = Builder::table('users') + ->where(['id' => 123, 'status' => 'active']) + ->build(); +// WHERE id = ? AND status = ? +``` + +### Opérateurs de Comparaison + +```php +$q = Builder::table('users') + ->where([ + 'age' => ['>=', 18], + 'score' => ['<', 100], + 'name' => ['!=', 'admin'] + ]) + ->build(); +// WHERE age >= ? AND score < ? AND name != ? +``` + +### LIKE + +```php +$q = Builder::table('users') + ->where(['name' => ['LIKE', '%john%']]) + ->build(); +// WHERE name LIKE ? +``` + +### IN / NOT IN + +```php +// IN +$q = Builder::table('users') + ->where(['id' => ['IN', [1, 2, 3, 4, 5]]]) + ->build(); +// WHERE id IN (?, ?, ?, ?, ?) + +// NOT IN +$q = Builder::table('users') + ->where(['status' => ['NOT IN', ['banned', 'deleted']]]) + ->build(); +// WHERE status NOT IN (?, ?) +``` + +### BETWEEN + +```php +$q = Builder::table('products') + ->where(['price' => ['BETWEEN', [100, 500]]]) + ->build(); +// WHERE price BETWEEN ? AND ? +``` + +### Conditions OR + +Utilisez `orWhere()` pour ajouter des conditions groupées avec OR: + +```php +$q = Builder::table('users') + ->where(['status' => 'active']) + ->orWhere([ + 'role' => 'admin', + 'permissions' => ['LIKE', '%manage%'] + ]) + ->build(); +// WHERE status = ? AND (role = ? OR permissions LIKE ?) +``` + +--- + +## JOIN + +### INNER JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name', 'p.title']) + ->innerJoin('posts', 'u.id = p.user_id', 'p') + ->build(); +// SELECT u.id, u.name, p.title FROM users AS u INNER JOIN posts AS p ON u.id = p.user_id +``` + +### LEFT JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.name', 'o.total']) + ->leftJoin('orders', 'u.id = o.user_id', 'o') + ->build(); +// ... LEFT JOIN orders AS o ON u.id = o.user_id +``` + +### JOINs Multiples + +```php +$q = Builder::table('orders') + ->alias('o') + ->select(['o.id', 'u.name AS customer', 'p.title AS product']) + ->innerJoin('users', 'o.user_id = u.id', 'u') + ->leftJoin('order_items', 'o.id = oi.order_id', 'oi') + ->leftJoin('products', 'oi.product_id = p.id', 'p') + ->where(['o.status' => 'completed']) + ->build(); +``` + +--- + +## Tri, Groupement et Limites + +### ORDER BY + +```php +$q = Builder::table('users') + ->orderBy('created_at DESC') + ->build(); +// ORDER BY created_at DESC +``` + +### GROUP BY + +```php +$q = Builder::table('orders') + ->select(['user_id', 'COUNT(*) as order_count']) + ->groupBy('user_id') + ->build(); +// SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id +``` + +### LIMIT et OFFSET + +```php +$q = Builder::table('users') + ->limit(10) + ->build(); +// LIMIT 10 + +$q = Builder::table('users') + ->limit(10, 20) // limit, offset + ->build(); +// LIMIT 10 OFFSET 20 +``` + +--- + +## Expressions Raw SQL + +Utilisez `raw()` quand vous avez besoin de fonctions SQL ou d'expressions qui ne doivent pas être traitées comme des paramètres liés. + +### Raw Basique + +```php +$q = Builder::table('users') + ->update([ + 'login_count' => Builder::raw('login_count + 1'), + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => 123]) + ->build(); +// SET login_count = login_count + 1, updated_at = NOW() +``` + +### Raw avec Paramètres Liés + +```php +$q = Builder::table('orders') + ->update([ + 'total' => Builder::raw('COALESCE(subtotal, ?) + ?', [0, 10]) + ]) + ->where(['id' => 1]) + ->build(); +// SET total = COALESCE(subtotal, ?) + ? +// params: [0, 10, 1] +``` + +### Raw dans WHERE (Sous-requête) + +```php +$q = Builder::table('products') + ->where([ + 'price' => ['>', Builder::raw('(SELECT AVG(price) FROM products)')] + ]) + ->build(); +// WHERE price > (SELECT AVG(price) FROM products) +``` + +### Identifiants Sécurisés pour les Entrées Utilisateur + +Quand les noms de colonnes viennent d'entrées utilisateur, utilisez `safeIdentifier()` pour prévenir l'injection SQL: + +```php +$sortColumn = $_GET['sort']; // ex: 'created_at' +$safeColumn = Builder::safeIdentifier($sortColumn); + +$q = Builder::table('users') + ->orderBy($safeColumn . ' DESC') + ->build(); + +// Si l'utilisateur essaie: "name; DROP TABLE users--" +// Lance InvalidArgumentException +``` + +### rawSafe pour les Noms de Colonnes Utilisateur + +```php +$userColumn = $_GET['aggregate_column']; + +$q = Builder::table('orders') + ->select([ + Builder::rawSafe('SUM({col})', ['col' => $userColumn])->value . ' AS total' + ]) + ->build(); +// Valide le nom de colonne, lance une exception si invalide +``` + +> **Avertissement:** Ne concaténez jamais directement les entrées utilisateur dans `raw()`. Utilisez toujours des paramètres liés ou `safeIdentifier()`. + +--- + +## Réutilisation du Query Builder + +### Méthodes Clear + +Effacez des parties spécifiques pour réutiliser le builder: + +```php +$query = Builder::table('users') + ->select(['id', 'name']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Première requête +$q1 = $query->limit(10)->build(); + +// Effacer et réutiliser +$query->clearWhere()->clearLimit(); + +// Deuxième requête avec des conditions différentes +$q2 = $query + ->where(['status' => 'pending']) + ->limit(5) + ->build(); +``` + +### Méthodes Clear Disponibles + +| Méthode | Description | +|---------|-------------| +| `clearWhere()` | Effacer les conditions WHERE et les paramètres | +| `clearSelect()` | Réinitialiser les colonnes SELECT à '*' par défaut | +| `clearJoin()` | Effacer toutes les clauses JOIN | +| `clearGroupBy()` | Effacer la clause GROUP BY | +| `clearOrderBy()` | Effacer la clause ORDER BY | +| `clearLimit()` | Effacer LIMIT et OFFSET | +| `clearAll()` | Réinitialiser le builder à l'état initial | + +### Exemple de Pagination + +```php +$baseQuery = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Obtenir le nombre total +$countQuery = clone $baseQuery; +$countResult = $countQuery->clearSelect()->count()->build(); +$total = Flight::db()->fetchField($countResult['sql'], $countResult['params']); + +// Obtenir les résultats paginés +$page = 1; +$perPage = 20; +$listResult = $baseQuery->limit($perPage, ($page - 1) * $perPage)->build(); +$users = Flight::db()->fetchAll($listResult['sql'], $listResult['params']); +``` + +--- + +## Construction Dynamique de Requêtes + +```php +$query = Builder::table('products')->alias('p'); + +if (!empty($categoryId)) { + $query->where(['p.category_id' => $categoryId]); +} + +if (!empty($minPrice)) { + $query->where(['p.price' => ['>=', $minPrice]]); +} + +if (!empty($maxPrice)) { + $query->where(['p.price' => ['<=', $maxPrice]]); +} + +if (!empty($searchTerm)) { + $query->where(['p.name' => ['LIKE', "%{$searchTerm}%"]]); +} + +$result = $query->orderBy('p.created_at DESC')->limit(20)->build(); +$products = Flight::db()->fetchAll($result['sql'], $result['params']); +``` + +--- + +## Exemple Complet FlightPHP + +```php +use KnifeLemon\EasyQuery\Builder; + +// Lister les utilisateurs avec pagination +Flight::route('GET /users', function() { + $page = (int) (Flight::request()->query['page'] ?? 1); + $perPage = 20; + + $q = Builder::table('users') + ->select(['id', 'name', 'email', 'created_at']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit($perPage, ($page - 1) * $perPage) + ->build(); + + $users = Flight::db()->fetchAll($q['sql'], $q['params']); + Flight::json(['users' => $users, 'page' => $page]); +}); + +// Créer un utilisateur +Flight::route('POST /users', function() { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->insert([ + 'name' => $data->name, + 'email' => $data->email, + 'created_at' => Builder::raw('NOW()') + ]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['id' => Flight::db()->lastInsertId()]); +}); + +// Mettre à jour un utilisateur +Flight::route('PUT /users/@id', function($id) { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->update([ + 'name' => $data->name, + 'email' => $data->email, + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); + +// Supprimer un utilisateur +Flight::route('DELETE /users/@id', function($id) { + $q = Builder::table('users') + ->delete() + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); +``` + +--- + +## Référence API + +### Méthodes Statiques + +| Méthode | Description | +|---------|-------------| +| `Builder::table(string $table)` | Créer une nouvelle instance du builder pour la table | +| `Builder::raw(string $sql, array $bindings = [])` | Créer une expression SQL brute | +| `Builder::rawSafe(string $expr, array $identifiers, array $bindings = [])` | Expression raw avec substitution sécurisée des identifiants | +| `Builder::safeIdentifier(string $identifier)` | Valider et retourner un nom de colonne/table sécurisé | + +### Méthodes d'Instance + +| Méthode | Description | +|---------|-------------| +| `alias(string $alias)` | Définir l'alias de table | +| `select(string\|array $columns)` | Définir les colonnes à sélectionner (défaut: '*') | +| `where(array $conditions)` | Ajouter des conditions WHERE (AND) | +| `orWhere(array $conditions)` | Ajouter des conditions OR WHERE | +| `join(string $table, string $condition, string $alias, string $type)` | Ajouter une clause JOIN | +| `innerJoin(string $table, string $condition, string $alias)` | Ajouter INNER JOIN | +| `leftJoin(string $table, string $condition, string $alias)` | Ajouter LEFT JOIN | +| `groupBy(string $groupBy)` | Ajouter la clause GROUP BY | +| `orderBy(string $orderBy)` | Ajouter la clause ORDER BY | +| `limit(int $limit, int $offset = 0)` | Ajouter LIMIT et OFFSET | +| `count(string $column = '*')` | Définir la requête en COUNT | +| `insert(array $data)` | Définir la requête en INSERT | +| `update(array $data)` | Définir la requête en UPDATE | +| `delete()` | Définir la requête en DELETE | +| `build()` | Construire et retourner `['sql' => ..., 'params' => ...]` | +| `get()` | Alias de `build()` | + +--- + +## Intégration Tracy Debugger + +EasyQuery s'intègre automatiquement avec Tracy Debugger s'il est installé. Aucune configuration nécessaire! + +```bash +composer require tracy/tracy +``` + +```php +use Tracy\Debugger; + +Debugger::enable(); + +// Toutes les requêtes sont automatiquement enregistrées dans le panneau Tracy +$q = Builder::table('users')->where(['status' => 'active'])->build(); +``` + +Le panneau Tracy affiche: +- Total des requêtes et répartition par type +- SQL généré (coloration syntaxique) +- Tableau des paramètres +- Détails de requête (table, where, joins, etc.) + +Pour la documentation complète, visitez le [dépôt GitHub](https://github.com/knifelemon/EasyQueryBuilder). diff --git a/content/v3/id/awesome-plugins/awesome_plugins.md b/content/v3/id/awesome-plugins/awesome_plugins.md index 3bf10cb1..0d67947f 100644 --- a/content/v3/id/awesome-plugins/awesome_plugins.md +++ b/content/v3/id/awesome-plugins/awesome_plugins.md @@ -65,6 +65,7 @@ Database adalah inti dari sebagian besar aplikasi. Ini adalah cara Anda menyimpa - deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO Flight resmi yang merupakan bagian dari inti (deprecated sejak v3.18.0). Gunakan SimplePdo sebagai gantinya. - resmi [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord Flight resmi. Pustaka kecil yang hebat untuk dengan mudah mengambil dan menyimpan data di database Anda. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin untuk melacak semua perubahan database untuk proyek Anda. +- [knifelemon/easy-query](/awesome-plugins/easy-query) - Pembuat kueri SQL yang ringan dan fluent yang menghasilkan SQL dan parameter untuk prepared statement. Bekerja dengan baik dengan [SimplePdo](/learn/simple-pdo). ## Enkripsi diff --git a/content/v3/id/awesome-plugins/easy_query.md b/content/v3/id/awesome-plugins/easy_query.md new file mode 100644 index 00000000..3887470d --- /dev/null +++ b/content/v3/id/awesome-plugins/easy_query.md @@ -0,0 +1,569 @@ +# EasyQuery + +[knifelemon/easy-query](https://github.com/knifelemon/EasyQueryBuilder) adalah pembuat kueri SQL yang ringan dan fluent yang menghasilkan SQL dan parameter untuk prepared statement. Bekerja dengan [SimplePdo](/learn/simple-pdo). + +## Fitur + +- 🔗 **API Fluent** - Metode berantai untuk konstruksi kueri yang mudah dibaca +- 🛡️ **Perlindungan SQL Injection** - Pengikatan parameter otomatis dengan prepared statement +- 🔧 **Dukungan Raw SQL** - Sisipkan ekspresi SQL langsung dengan `raw()` +- 📝 **Berbagai Tipe Kueri** - SELECT, INSERT, UPDATE, DELETE, COUNT +- 🔀 **Dukungan JOIN** - INNER, LEFT, RIGHT join dengan alias +- 🎯 **Kondisi Lanjutan** - LIKE, IN, NOT IN, BETWEEN, operator perbandingan +- 🌐 **Database Agnostic** - Mengembalikan SQL + params, gunakan dengan koneksi DB apapun +- 🪶 **Ringan** - Footprint minimal tanpa dependensi + +## Instalasi + +```bash +composer require knifelemon/easy-query +``` + +## Mulai Cepat + +```php +use KnifeLemon\EasyQuery\Builder; + +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit(10) + ->build(); + +// Gunakan dengan SimplePdo Flight +$users = Flight::db()->fetchAll($q['sql'], $q['params']); +``` + +## Memahami build() + +Metode `build()` mengembalikan array dengan `sql` dan `params`. Pemisahan ini menjaga database Anda aman dengan menggunakan prepared statement. + +```php +$q = Builder::table('users') + ->where(['email' => 'user@example.com']) + ->build(); + +// Mengembalikan: +// [ +// 'sql' => 'SELECT * FROM users WHERE email = ?', +// 'params' => ['user@example.com'] +// ] +``` + +--- + +## Tipe Kueri + +### SELECT + +```php +// Pilih semua kolom +$q = Builder::table('users')->build(); +// SELECT * FROM users + +// Pilih kolom tertentu +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->build(); +// SELECT id, name, email FROM users + +// Dengan alias tabel +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name']) + ->build(); +// SELECT u.id, u.name FROM users AS u +``` + +### INSERT + +```php +$q = Builder::table('users') + ->insert([ + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'status' => 'active' + ]) + ->build(); +// INSERT INTO users SET name = ?, email = ?, status = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +$userId = Flight::db()->lastInsertId(); +``` + +### UPDATE + +```php +$q = Builder::table('users') + ->update(['status' => 'inactive', 'updated_at' => date('Y-m-d H:i:s')]) + ->where(['id' => 123]) + ->build(); +// UPDATE users SET status = ?, updated_at = ? WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### DELETE + +```php +$q = Builder::table('users') + ->delete() + ->where(['id' => 123]) + ->build(); +// DELETE FROM users WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### COUNT + +```php +$q = Builder::table('users') + ->count() + ->where(['status' => 'active']) + ->build(); +// SELECT COUNT(*) AS cnt FROM users WHERE status = ? + +$count = Flight::db()->fetchField($q['sql'], $q['params']); +``` + +--- + +## Kondisi WHERE + +### Kesetaraan Sederhana + +```php +$q = Builder::table('users') + ->where(['id' => 123, 'status' => 'active']) + ->build(); +// WHERE id = ? AND status = ? +``` + +### Operator Perbandingan + +```php +$q = Builder::table('users') + ->where([ + 'age' => ['>=', 18], + 'score' => ['<', 100], + 'name' => ['!=', 'admin'] + ]) + ->build(); +// WHERE age >= ? AND score < ? AND name != ? +``` + +### LIKE + +```php +$q = Builder::table('users') + ->where(['name' => ['LIKE', '%john%']]) + ->build(); +// WHERE name LIKE ? +``` + +### IN / NOT IN + +```php +// IN +$q = Builder::table('users') + ->where(['id' => ['IN', [1, 2, 3, 4, 5]]]) + ->build(); +// WHERE id IN (?, ?, ?, ?, ?) + +// NOT IN +$q = Builder::table('users') + ->where(['status' => ['NOT IN', ['banned', 'deleted']]]) + ->build(); +// WHERE status NOT IN (?, ?) +``` + +### BETWEEN + +```php +$q = Builder::table('products') + ->where(['price' => ['BETWEEN', [100, 500]]]) + ->build(); +// WHERE price BETWEEN ? AND ? +``` + +### Kondisi OR + +Gunakan `orWhere()` untuk menambahkan kondisi yang dikelompokkan dengan OR: + +```php +$q = Builder::table('users') + ->where(['status' => 'active']) + ->orWhere([ + 'role' => 'admin', + 'permissions' => ['LIKE', '%manage%'] + ]) + ->build(); +// WHERE status = ? AND (role = ? OR permissions LIKE ?) +``` + +--- + +## JOIN + +### INNER JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name', 'p.title']) + ->innerJoin('posts', 'u.id = p.user_id', 'p') + ->build(); +// SELECT u.id, u.name, p.title FROM users AS u INNER JOIN posts AS p ON u.id = p.user_id +``` + +### LEFT JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.name', 'o.total']) + ->leftJoin('orders', 'u.id = o.user_id', 'o') + ->build(); +// ... LEFT JOIN orders AS o ON u.id = o.user_id +``` + +### Multiple JOIN + +```php +$q = Builder::table('orders') + ->alias('o') + ->select(['o.id', 'u.name AS customer', 'p.title AS product']) + ->innerJoin('users', 'o.user_id = u.id', 'u') + ->leftJoin('order_items', 'o.id = oi.order_id', 'oi') + ->leftJoin('products', 'oi.product_id = p.id', 'p') + ->where(['o.status' => 'completed']) + ->build(); +``` + +--- + +## Pengurutan, Pengelompokan, dan Limit + +### ORDER BY + +```php +$q = Builder::table('users') + ->orderBy('created_at DESC') + ->build(); +// ORDER BY created_at DESC +``` + +### GROUP BY + +```php +$q = Builder::table('orders') + ->select(['user_id', 'COUNT(*) as order_count']) + ->groupBy('user_id') + ->build(); +// SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id +``` + +### LIMIT dan OFFSET + +```php +$q = Builder::table('users') + ->limit(10) + ->build(); +// LIMIT 10 + +$q = Builder::table('users') + ->limit(10, 20) // limit, offset + ->build(); +// LIMIT 10 OFFSET 20 +``` + +--- + +## Ekspresi Raw SQL + +Gunakan `raw()` ketika Anda membutuhkan fungsi SQL atau ekspresi yang tidak boleh diperlakukan sebagai parameter terikat. + +### Raw Dasar + +```php +$q = Builder::table('users') + ->update([ + 'login_count' => Builder::raw('login_count + 1'), + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => 123]) + ->build(); +// SET login_count = login_count + 1, updated_at = NOW() +``` + +### Raw dengan Parameter Terikat + +```php +$q = Builder::table('orders') + ->update([ + 'total' => Builder::raw('COALESCE(subtotal, ?) + ?', [0, 10]) + ]) + ->where(['id' => 1]) + ->build(); +// SET total = COALESCE(subtotal, ?) + ? +// params: [0, 10, 1] +``` + +### Raw di WHERE (Subquery) + +```php +$q = Builder::table('products') + ->where([ + 'price' => ['>', Builder::raw('(SELECT AVG(price) FROM products)')] + ]) + ->build(); +// WHERE price > (SELECT AVG(price) FROM products) +``` + +### Identifier Aman untuk Input Pengguna + +Ketika nama kolom berasal dari input pengguna, gunakan `safeIdentifier()` untuk mencegah SQL injection: + +```php +$sortColumn = $_GET['sort']; // contoh: 'created_at' +$safeColumn = Builder::safeIdentifier($sortColumn); + +$q = Builder::table('users') + ->orderBy($safeColumn . ' DESC') + ->build(); + +// Jika pengguna mencoba: "name; DROP TABLE users--" +// Melempar InvalidArgumentException +``` + +### rawSafe untuk Nama Kolom dari Pengguna + +```php +$userColumn = $_GET['aggregate_column']; + +$q = Builder::table('orders') + ->select([ + Builder::rawSafe('SUM({col})', ['col' => $userColumn])->value . ' AS total' + ]) + ->build(); +// Memvalidasi nama kolom, melempar exception jika tidak valid +``` + +> **Peringatan:** Jangan pernah menggabungkan input pengguna langsung ke `raw()`. Selalu gunakan parameter terikat atau `safeIdentifier()`. + +--- + +## Penggunaan Ulang Query Builder + +### Metode Clear + +Hapus bagian tertentu untuk menggunakan ulang builder: + +```php +$query = Builder::table('users') + ->select(['id', 'name']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Kueri pertama +$q1 = $query->limit(10)->build(); + +// Hapus dan gunakan ulang +$query->clearWhere()->clearLimit(); + +// Kueri kedua dengan kondisi berbeda +$q2 = $query + ->where(['status' => 'pending']) + ->limit(5) + ->build(); +``` + +### Metode Clear yang Tersedia + +| Metode | Deskripsi | +|--------|-----------| +| `clearWhere()` | Hapus kondisi WHERE dan parameter | +| `clearSelect()` | Reset kolom SELECT ke default '*' | +| `clearJoin()` | Hapus semua klausa JOIN | +| `clearGroupBy()` | Hapus klausa GROUP BY | +| `clearOrderBy()` | Hapus klausa ORDER BY | +| `clearLimit()` | Hapus LIMIT dan OFFSET | +| `clearAll()` | Reset builder ke keadaan awal | + +### Contoh Paginasi + +```php +$baseQuery = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Dapatkan jumlah total +$countQuery = clone $baseQuery; +$countResult = $countQuery->clearSelect()->count()->build(); +$total = Flight::db()->fetchField($countResult['sql'], $countResult['params']); + +// Dapatkan hasil terpaginasi +$page = 1; +$perPage = 20; +$listResult = $baseQuery->limit($perPage, ($page - 1) * $perPage)->build(); +$users = Flight::db()->fetchAll($listResult['sql'], $listResult['params']); +``` + +--- + +## Pembangunan Kueri Dinamis + +```php +$query = Builder::table('products')->alias('p'); + +if (!empty($categoryId)) { + $query->where(['p.category_id' => $categoryId]); +} + +if (!empty($minPrice)) { + $query->where(['p.price' => ['>=', $minPrice]]); +} + +if (!empty($maxPrice)) { + $query->where(['p.price' => ['<=', $maxPrice]]); +} + +if (!empty($searchTerm)) { + $query->where(['p.name' => ['LIKE', "%{$searchTerm}%"]]); +} + +$result = $query->orderBy('p.created_at DESC')->limit(20)->build(); +$products = Flight::db()->fetchAll($result['sql'], $result['params']); +``` + +--- + +## Contoh FlightPHP Lengkap + +```php +use KnifeLemon\EasyQuery\Builder; + +// Daftar pengguna dengan paginasi +Flight::route('GET /users', function() { + $page = (int) (Flight::request()->query['page'] ?? 1); + $perPage = 20; + + $q = Builder::table('users') + ->select(['id', 'name', 'email', 'created_at']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit($perPage, ($page - 1) * $perPage) + ->build(); + + $users = Flight::db()->fetchAll($q['sql'], $q['params']); + Flight::json(['users' => $users, 'page' => $page]); +}); + +// Buat pengguna +Flight::route('POST /users', function() { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->insert([ + 'name' => $data->name, + 'email' => $data->email, + 'created_at' => Builder::raw('NOW()') + ]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['id' => Flight::db()->lastInsertId()]); +}); + +// Perbarui pengguna +Flight::route('PUT /users/@id', function($id) { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->update([ + 'name' => $data->name, + 'email' => $data->email, + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); + +// Hapus pengguna +Flight::route('DELETE /users/@id', function($id) { + $q = Builder::table('users') + ->delete() + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); +``` + +--- + +## Referensi API + +### Metode Statis + +| Metode | Deskripsi | +|--------|-----------| +| `Builder::table(string $table)` | Buat instance builder baru untuk tabel | +| `Builder::raw(string $sql, array $bindings = [])` | Buat ekspresi SQL mentah | +| `Builder::rawSafe(string $expr, array $identifiers, array $bindings = [])` | Ekspresi raw dengan substitusi identifier yang aman | +| `Builder::safeIdentifier(string $identifier)` | Validasi dan kembalikan nama kolom/tabel yang aman | + +### Metode Instance + +| Metode | Deskripsi | +|--------|-----------| +| `alias(string $alias)` | Set alias tabel | +| `select(string\|array $columns)` | Set kolom yang akan dipilih (default: '*') | +| `where(array $conditions)` | Tambah kondisi WHERE (AND) | +| `orWhere(array $conditions)` | Tambah kondisi OR WHERE | +| `join(string $table, string $condition, string $alias, string $type)` | Tambah klausa JOIN | +| `innerJoin(string $table, string $condition, string $alias)` | Tambah INNER JOIN | +| `leftJoin(string $table, string $condition, string $alias)` | Tambah LEFT JOIN | +| `groupBy(string $groupBy)` | Tambah klausa GROUP BY | +| `orderBy(string $orderBy)` | Tambah klausa ORDER BY | +| `limit(int $limit, int $offset = 0)` | Tambah LIMIT dan OFFSET | +| `count(string $column = '*')` | Set kueri ke COUNT | +| `insert(array $data)` | Set kueri ke INSERT | +| `update(array $data)` | Set kueri ke UPDATE | +| `delete()` | Set kueri ke DELETE | +| `build()` | Bangun dan kembalikan `['sql' => ..., 'params' => ...]` | +| `get()` | Alias untuk `build()` | + +--- + +## Integrasi Tracy Debugger + +EasyQuery secara otomatis terintegrasi dengan Tracy Debugger jika terinstal. Tidak perlu pengaturan! + +```bash +composer require tracy/tracy +``` + +```php +use Tracy\Debugger; + +Debugger::enable(); + +// Semua kueri secara otomatis dicatat ke panel Tracy +$q = Builder::table('users')->where(['status' => 'active'])->build(); +``` + +Panel Tracy menampilkan: +- Total kueri dan rincian berdasarkan tipe +- SQL yang dihasilkan (syntax highlighting) +- Array parameter +- Detail kueri (tabel, where, join, dll.) + +Untuk dokumentasi lengkap, kunjungi [repositori GitHub](https://github.com/knifelemon/EasyQueryBuilder). diff --git a/content/v3/ja/awesome-plugins/awesome_plugins.md b/content/v3/ja/awesome-plugins/awesome_plugins.md index 236c402c..fc7fbb80 100644 --- a/content/v3/ja/awesome-plugins/awesome_plugins.md +++ b/content/v3/ja/awesome-plugins/awesome_plugins.md @@ -65,6 +65,7 @@ CLI アプリケーションは、アプリケーションとやり取りする - deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) - コアの一部である公式の Flight PDO ラッパー(v3.18.0 以降非推奨)。SimplePdo を使用してください。 - official [flightphp/active-record](/awesome-plugins/active-record) - 公式の Flight ActiveRecord ORM/マッパーです。データベースからデータを簡単に取得および保存するための優れた小さなライブラリです。 - [byjg/php-migration](/awesome-plugins/migrations) - プロジェクトのすべてのデータベース変更を追跡するためのプラグインです。 +- [knifelemon/easy-query](/awesome-plugins/easy-query) - プリペアドステートメント用のSQLとパラメータを生成する軽量でフルエントなSQLクエリビルダー。[SimplePdo](/learn/simple-pdo)との併用に最適です。 ## 暗号化 diff --git a/content/v3/ja/awesome-plugins/easy_query.md b/content/v3/ja/awesome-plugins/easy_query.md new file mode 100644 index 00000000..092b6405 --- /dev/null +++ b/content/v3/ja/awesome-plugins/easy_query.md @@ -0,0 +1,569 @@ +# EasyQuery + +[knifelemon/easy-query](https://github.com/knifelemon/EasyQueryBuilder)は、SQLとパラメータを生成する軽量なFluent SQLクエリビルダーです。[SimplePdo](/learn/simple-pdo)と連携できます。 + +## 特徴 + +- 🔗 **Fluent API** - メソッドチェーンで可読性の高いクエリ構築 +- 🛡️ **SQLインジェクション防止** - プリペアドステートメントによる自動パラメータバインディング +- 🔧 **Raw SQLサポート** - `raw()`でSQL式を直接挿入 +- 📝 **複数のクエリタイプ** - SELECT, INSERT, UPDATE, DELETE, COUNT +- 🔀 **JOINサポート** - INNER, LEFT, RIGHTジョインとエイリアス +- 🎯 **高度な条件** - LIKE, IN, NOT IN, BETWEEN, 比較演算子 +- 🌐 **データベース非依存** - SQL + paramsを返し、どのDB接続でも使用可能 +- 🪶 **軽量** - 依存関係なしで最小限のフットプリント + +## インストール + +```bash +composer require knifelemon/easy-query +``` + +## クイックスタート + +```php +use KnifeLemon\EasyQuery\Builder; + +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit(10) + ->build(); + +// FlightのSimplePdoで使用 +$users = Flight::db()->fetchAll($q['sql'], $q['params']); +``` + +## build()の理解 + +`build()`メソッドは`sql`と`params`を含む配列を返します。この分離により、プリペアドステートメントを使用してデータベースを安全に保護します。 + +```php +$q = Builder::table('users') + ->where(['email' => 'user@example.com']) + ->build(); + +// 戻り値: +// [ +// 'sql' => 'SELECT * FROM users WHERE email = ?', +// 'params' => ['user@example.com'] +// ] +``` + +--- + +## クエリタイプ + +### SELECT + +```php +// すべてのカラムを選択 +$q = Builder::table('users')->build(); +// SELECT * FROM users + +// 特定のカラムを選択 +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->build(); +// SELECT id, name, email FROM users + +// テーブルエイリアスを使用 +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name']) + ->build(); +// SELECT u.id, u.name FROM users AS u +``` + +### INSERT + +```php +$q = Builder::table('users') + ->insert([ + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'status' => 'active' + ]) + ->build(); +// INSERT INTO users SET name = ?, email = ?, status = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +$userId = Flight::db()->lastInsertId(); +``` + +### UPDATE + +```php +$q = Builder::table('users') + ->update(['status' => 'inactive', 'updated_at' => date('Y-m-d H:i:s')]) + ->where(['id' => 123]) + ->build(); +// UPDATE users SET status = ?, updated_at = ? WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### DELETE + +```php +$q = Builder::table('users') + ->delete() + ->where(['id' => 123]) + ->build(); +// DELETE FROM users WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### COUNT + +```php +$q = Builder::table('users') + ->count() + ->where(['status' => 'active']) + ->build(); +// SELECT COUNT(*) AS cnt FROM users WHERE status = ? + +$count = Flight::db()->fetchField($q['sql'], $q['params']); +``` + +--- + +## WHERE条件 + +### 単純な等価比較 + +```php +$q = Builder::table('users') + ->where(['id' => 123, 'status' => 'active']) + ->build(); +// WHERE id = ? AND status = ? +``` + +### 比較演算子 + +```php +$q = Builder::table('users') + ->where([ + 'age' => ['>=', 18], + 'score' => ['<', 100], + 'name' => ['!=', 'admin'] + ]) + ->build(); +// WHERE age >= ? AND score < ? AND name != ? +``` + +### LIKE + +```php +$q = Builder::table('users') + ->where(['name' => ['LIKE', '%john%']]) + ->build(); +// WHERE name LIKE ? +``` + +### IN / NOT IN + +```php +// IN +$q = Builder::table('users') + ->where(['id' => ['IN', [1, 2, 3, 4, 5]]]) + ->build(); +// WHERE id IN (?, ?, ?, ?, ?) + +// NOT IN +$q = Builder::table('users') + ->where(['status' => ['NOT IN', ['banned', 'deleted']]]) + ->build(); +// WHERE status NOT IN (?, ?) +``` + +### BETWEEN + +```php +$q = Builder::table('products') + ->where(['price' => ['BETWEEN', [100, 500]]]) + ->build(); +// WHERE price BETWEEN ? AND ? +``` + +### OR条件 + +`orWhere()`を使用してORでグループ化された条件を追加します: + +```php +$q = Builder::table('users') + ->where(['status' => 'active']) + ->orWhere([ + 'role' => 'admin', + 'permissions' => ['LIKE', '%manage%'] + ]) + ->build(); +// WHERE status = ? AND (role = ? OR permissions LIKE ?) +``` + +--- + +## JOIN + +### INNER JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name', 'p.title']) + ->innerJoin('posts', 'u.id = p.user_id', 'p') + ->build(); +// SELECT u.id, u.name, p.title FROM users AS u INNER JOIN posts AS p ON u.id = p.user_id +``` + +### LEFT JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.name', 'o.total']) + ->leftJoin('orders', 'u.id = o.user_id', 'o') + ->build(); +// ... LEFT JOIN orders AS o ON u.id = o.user_id +``` + +### 複数JOIN + +```php +$q = Builder::table('orders') + ->alias('o') + ->select(['o.id', 'u.name AS customer', 'p.title AS product']) + ->innerJoin('users', 'o.user_id = u.id', 'u') + ->leftJoin('order_items', 'o.id = oi.order_id', 'oi') + ->leftJoin('products', 'oi.product_id = p.id', 'p') + ->where(['o.status' => 'completed']) + ->build(); +``` + +--- + +## ソート、グループ化、制限 + +### ORDER BY + +```php +$q = Builder::table('users') + ->orderBy('created_at DESC') + ->build(); +// ORDER BY created_at DESC +``` + +### GROUP BY + +```php +$q = Builder::table('orders') + ->select(['user_id', 'COUNT(*) as order_count']) + ->groupBy('user_id') + ->build(); +// SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id +``` + +### LIMITとOFFSET + +```php +$q = Builder::table('users') + ->limit(10) + ->build(); +// LIMIT 10 + +$q = Builder::table('users') + ->limit(10, 20) // limit, offset + ->build(); +// LIMIT 10 OFFSET 20 +``` + +--- + +## Raw SQL式 + +バウンドパラメータとして処理すべきでないSQL関数や式が必要な場合は`raw()`を使用します。 + +### 基本的なRaw + +```php +$q = Builder::table('users') + ->update([ + 'login_count' => Builder::raw('login_count + 1'), + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => 123]) + ->build(); +// SET login_count = login_count + 1, updated_at = NOW() +``` + +### バウンドパラメータ付きRaw + +```php +$q = Builder::table('orders') + ->update([ + 'total' => Builder::raw('COALESCE(subtotal, ?) + ?', [0, 10]) + ]) + ->where(['id' => 1]) + ->build(); +// SET total = COALESCE(subtotal, ?) + ? +// params: [0, 10, 1] +``` + +### WHEREでのRaw(サブクエリ) + +```php +$q = Builder::table('products') + ->where([ + 'price' => ['>', Builder::raw('(SELECT AVG(price) FROM products)')] + ]) + ->build(); +// WHERE price > (SELECT AVG(price) FROM products) +``` + +### ユーザー入力の安全な識別子 + +カラム名がユーザー入力から来る場合、`safeIdentifier()`を使用してSQLインジェクションを防止します: + +```php +$sortColumn = $_GET['sort']; // 例: 'created_at' +$safeColumn = Builder::safeIdentifier($sortColumn); + +$q = Builder::table('users') + ->orderBy($safeColumn . ' DESC') + ->build(); + +// ユーザーが"name; DROP TABLE users--"を試みた場合 +// InvalidArgumentExceptionがスローされます +``` + +### ユーザー提供のカラム名用rawSafe + +```php +$userColumn = $_GET['aggregate_column']; + +$q = Builder::table('orders') + ->select([ + Builder::rawSafe('SUM({col})', ['col' => $userColumn])->value . ' AS total' + ]) + ->build(); +// カラム名を検証し、無効な場合は例外をスロー +``` + +> **警告:** ユーザー入力を`raw()`に直接連結しないでください。常にバウンドパラメータまたは`safeIdentifier()`を使用してください。 + +--- + +## クエリビルダーの再利用 + +### Clearメソッド + +ビルダーを再利用するために特定の部分をクリアします: + +```php +$query = Builder::table('users') + ->select(['id', 'name']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// 最初のクエリ +$q1 = $query->limit(10)->build(); + +// クリアして再利用 +$query->clearWhere()->clearLimit(); + +// 異なる条件で2番目のクエリ +$q2 = $query + ->where(['status' => 'pending']) + ->limit(5) + ->build(); +``` + +### 利用可能なClearメソッド + +| メソッド | 説明 | +|----------|------| +| `clearWhere()` | WHERE条件とパラメータをクリア | +| `clearSelect()` | SELECTカラムをデフォルト'*'にリセット | +| `clearJoin()` | すべてのJOIN句をクリア | +| `clearGroupBy()` | GROUP BY句をクリア | +| `clearOrderBy()` | ORDER BY句をクリア | +| `clearLimit()` | LIMITとOFFSETをクリア | +| `clearAll()` | ビルダーを初期状態にリセット | + +### ページネーション例 + +```php +$baseQuery = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// 総数を取得 +$countQuery = clone $baseQuery; +$countResult = $countQuery->clearSelect()->count()->build(); +$total = Flight::db()->fetchField($countResult['sql'], $countResult['params']); + +// ページネーションされた結果を取得 +$page = 1; +$perPage = 20; +$listResult = $baseQuery->limit($perPage, ($page - 1) * $perPage)->build(); +$users = Flight::db()->fetchAll($listResult['sql'], $listResult['params']); +``` + +--- + +## 動的クエリビルディング + +```php +$query = Builder::table('products')->alias('p'); + +if (!empty($categoryId)) { + $query->where(['p.category_id' => $categoryId]); +} + +if (!empty($minPrice)) { + $query->where(['p.price' => ['>=', $minPrice]]); +} + +if (!empty($maxPrice)) { + $query->where(['p.price' => ['<=', $maxPrice]]); +} + +if (!empty($searchTerm)) { + $query->where(['p.name' => ['LIKE', "%{$searchTerm}%"]]); +} + +$result = $query->orderBy('p.created_at DESC')->limit(20)->build(); +$products = Flight::db()->fetchAll($result['sql'], $result['params']); +``` + +--- + +## FlightPHP完全例 + +```php +use KnifeLemon\EasyQuery\Builder; + +// ページネーションでユーザー一覧取得 +Flight::route('GET /users', function() { + $page = (int) (Flight::request()->query['page'] ?? 1); + $perPage = 20; + + $q = Builder::table('users') + ->select(['id', 'name', 'email', 'created_at']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit($perPage, ($page - 1) * $perPage) + ->build(); + + $users = Flight::db()->fetchAll($q['sql'], $q['params']); + Flight::json(['users' => $users, 'page' => $page]); +}); + +// ユーザー作成 +Flight::route('POST /users', function() { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->insert([ + 'name' => $data->name, + 'email' => $data->email, + 'created_at' => Builder::raw('NOW()') + ]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['id' => Flight::db()->lastInsertId()]); +}); + +// ユーザー更新 +Flight::route('PUT /users/@id', function($id) { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->update([ + 'name' => $data->name, + 'email' => $data->email, + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); + +// ユーザー削除 +Flight::route('DELETE /users/@id', function($id) { + $q = Builder::table('users') + ->delete() + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); +``` + +--- + +## APIリファレンス + +### 静的メソッド + +| メソッド | 説明 | +|----------|------| +| `Builder::table(string $table)` | テーブル用の新しいビルダーインスタンスを作成 | +| `Builder::raw(string $sql, array $bindings = [])` | Raw SQL式を作成 | +| `Builder::rawSafe(string $expr, array $identifiers, array $bindings = [])` | 安全な識別子置換付きRaw式 | +| `Builder::safeIdentifier(string $identifier)` | 安全なカラム/テーブル名を検証して返す | + +### インスタンスメソッド + +| メソッド | 説明 | +|----------|------| +| `alias(string $alias)` | テーブルエイリアスを設定 | +| `select(string\|array $columns)` | 選択するカラムを設定(デフォルト: '*') | +| `where(array $conditions)` | WHERE条件を追加(AND) | +| `orWhere(array $conditions)` | OR WHERE条件を追加 | +| `join(string $table, string $condition, string $alias, string $type)` | JOIN句を追加 | +| `innerJoin(string $table, string $condition, string $alias)` | INNER JOINを追加 | +| `leftJoin(string $table, string $condition, string $alias)` | LEFT JOINを追加 | +| `groupBy(string $groupBy)` | GROUP BY句を追加 | +| `orderBy(string $orderBy)` | ORDER BY句を追加 | +| `limit(int $limit, int $offset = 0)` | LIMITとOFFSETを追加 | +| `count(string $column = '*')` | COUNTクエリに設定 | +| `insert(array $data)` | INSERTクエリに設定 | +| `update(array $data)` | UPDATEクエリに設定 | +| `delete()` | DELETEクエリに設定 | +| `build()` | `['sql' => ..., 'params' => ...]`をビルドして返す | +| `get()` | `build()`のエイリアス | + +--- + +## Tracyデバッガー統合 + +EasyQueryはTracy Debuggerがインストールされていれば自動的に統合されます。設定は不要です! + +```bash +composer require tracy/tracy +``` + +```php +use Tracy\Debugger; + +Debugger::enable(); + +// すべてのクエリが自動的にTracyパネルに記録されます +$q = Builder::table('users')->where(['status' => 'active'])->build(); +``` + +Tracyパネルで表示されるもの: +- 総クエリ数とタイプ別内訳 +- 生成されたSQL(構文ハイライト) +- パラメータ配列 +- クエリ詳細(テーブル、where、joinなど) + +完全なドキュメントは[GitHubリポジトリ](https://github.com/knifelemon/EasyQueryBuilder)をご覧ください。 diff --git a/content/v3/ko/awesome-plugins/awesome_plugins.md b/content/v3/ko/awesome-plugins/awesome_plugins.md index 474ddff6..9c31d2e5 100644 --- a/content/v3/ko/awesome-plugins/awesome_plugins.md +++ b/content/v3/ko/awesome-plugins/awesome_plugins.md @@ -65,6 +65,7 @@ CLI 애플리케이션은 애플리케이션과 상호 작용하는 훌륭한 - deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 코어의 일부인 공식 Flight PDO 래퍼 (v3.18.0부터 deprecated). 대신 SimplePdo를 사용하세요. - official [flightphp/active-record](/awesome-plugins/active-record) - 공식 Flight ActiveRecord ORM/Mapper. 데이터베이스에서 데이터를 쉽게 검색하고 저장하는 훌륭한 작은 라이브러리입니다. - [byjg/php-migration](/awesome-plugins/migrations) - 프로젝트의 모든 데이터베이스 변경 사항을 추적하는 플러그인. +- [knifelemon/easy-query](/awesome-plugins/easy-query) - prepared statement를 위한 SQL과 파라미터를 생성하는 경량 fluent SQL 쿼리 빌더. [SimplePdo](/learn/simple-pdo)와 함께 사용하면 좋습니다. ## 암호화 diff --git a/content/v3/ko/awesome-plugins/easy_query.md b/content/v3/ko/awesome-plugins/easy_query.md new file mode 100644 index 00000000..4c6663f3 --- /dev/null +++ b/content/v3/ko/awesome-plugins/easy_query.md @@ -0,0 +1,569 @@ +# EasyQuery + +[knifelemon/easy-query](https://github.com/knifelemon/EasyQueryBuilder)는 SQL과 파라미터를 생성하는 경량의 Fluent SQL 쿼리 빌더입니다. [SimplePdo](/learn/simple-pdo)와 함께 사용할 수 있습니다. + +## 특징 + +- 🔗 **Fluent API** - 메서드 체이닝으로 가독성 높은 쿼리 작성 +- 🛡️ **SQL 인젝션 방지** - Prepared Statement를 통한 자동 파라미터 바인딩 +- 🔧 **Raw SQL 지원** - `raw()`로 SQL 표현식 직접 삽입 +- 📝 **다양한 쿼리 타입** - SELECT, INSERT, UPDATE, DELETE, COUNT +- 🔀 **JOIN 지원** - INNER, LEFT, RIGHT 조인과 별칭 +- 🎯 **고급 조건** - LIKE, IN, NOT IN, BETWEEN, 비교 연산자 +- 🌐 **데이터베이스 독립적** - SQL + params 반환, 어떤 DB 연결에서도 사용 가능 +- 🪶 **경량** - 의존성 없이 최소한의 용량 + +## 설치 + +```bash +composer require knifelemon/easy-query +``` + +## 빠른 시작 + +```php +use KnifeLemon\EasyQuery\Builder; + +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit(10) + ->build(); + +// Flight의 SimplePdo와 함께 사용 +$users = Flight::db()->fetchAll($q['sql'], $q['params']); +``` + +## build() 이해하기 + +`build()` 메서드는 `sql`과 `params`를 포함한 배열을 반환합니다. 이 분리는 prepared statement를 사용하여 데이터베이스를 안전하게 보호합니다. + +```php +$q = Builder::table('users') + ->where(['email' => 'user@example.com']) + ->build(); + +// 반환값: +// [ +// 'sql' => 'SELECT * FROM users WHERE email = ?', +// 'params' => ['user@example.com'] +// ] +``` + +--- + +## 쿼리 타입 + +### SELECT + +```php +// 모든 컬럼 선택 +$q = Builder::table('users')->build(); +// SELECT * FROM users + +// 특정 컬럼 선택 +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->build(); +// SELECT id, name, email FROM users + +// 테이블 별칭 사용 +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name']) + ->build(); +// SELECT u.id, u.name FROM users AS u +``` + +### INSERT + +```php +$q = Builder::table('users') + ->insert([ + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'status' => 'active' + ]) + ->build(); +// INSERT INTO users SET name = ?, email = ?, status = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +$userId = Flight::db()->lastInsertId(); +``` + +### UPDATE + +```php +$q = Builder::table('users') + ->update(['status' => 'inactive', 'updated_at' => date('Y-m-d H:i:s')]) + ->where(['id' => 123]) + ->build(); +// UPDATE users SET status = ?, updated_at = ? WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### DELETE + +```php +$q = Builder::table('users') + ->delete() + ->where(['id' => 123]) + ->build(); +// DELETE FROM users WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### COUNT + +```php +$q = Builder::table('users') + ->count() + ->where(['status' => 'active']) + ->build(); +// SELECT COUNT(*) AS cnt FROM users WHERE status = ? + +$count = Flight::db()->fetchField($q['sql'], $q['params']); +``` + +--- + +## WHERE 조건 + +### 단순 동등 비교 + +```php +$q = Builder::table('users') + ->where(['id' => 123, 'status' => 'active']) + ->build(); +// WHERE id = ? AND status = ? +``` + +### 비교 연산자 + +```php +$q = Builder::table('users') + ->where([ + 'age' => ['>=', 18], + 'score' => ['<', 100], + 'name' => ['!=', 'admin'] + ]) + ->build(); +// WHERE age >= ? AND score < ? AND name != ? +``` + +### LIKE + +```php +$q = Builder::table('users') + ->where(['name' => ['LIKE', '%john%']]) + ->build(); +// WHERE name LIKE ? +``` + +### IN / NOT IN + +```php +// IN +$q = Builder::table('users') + ->where(['id' => ['IN', [1, 2, 3, 4, 5]]]) + ->build(); +// WHERE id IN (?, ?, ?, ?, ?) + +// NOT IN +$q = Builder::table('users') + ->where(['status' => ['NOT IN', ['banned', 'deleted']]]) + ->build(); +// WHERE status NOT IN (?, ?) +``` + +### BETWEEN + +```php +$q = Builder::table('products') + ->where(['price' => ['BETWEEN', [100, 500]]]) + ->build(); +// WHERE price BETWEEN ? AND ? +``` + +### OR 조건 + +`orWhere()`를 사용하여 OR로 그룹화된 조건을 추가합니다: + +```php +$q = Builder::table('users') + ->where(['status' => 'active']) + ->orWhere([ + 'role' => 'admin', + 'permissions' => ['LIKE', '%manage%'] + ]) + ->build(); +// WHERE status = ? AND (role = ? OR permissions LIKE ?) +``` + +--- + +## JOIN + +### INNER JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name', 'p.title']) + ->innerJoin('posts', 'u.id = p.user_id', 'p') + ->build(); +// SELECT u.id, u.name, p.title FROM users AS u INNER JOIN posts AS p ON u.id = p.user_id +``` + +### LEFT JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.name', 'o.total']) + ->leftJoin('orders', 'u.id = o.user_id', 'o') + ->build(); +// ... LEFT JOIN orders AS o ON u.id = o.user_id +``` + +### 다중 JOIN + +```php +$q = Builder::table('orders') + ->alias('o') + ->select(['o.id', 'u.name AS customer', 'p.title AS product']) + ->innerJoin('users', 'o.user_id = u.id', 'u') + ->leftJoin('order_items', 'o.id = oi.order_id', 'oi') + ->leftJoin('products', 'oi.product_id = p.id', 'p') + ->where(['o.status' => 'completed']) + ->build(); +``` + +--- + +## 정렬, 그룹화, 제한 + +### ORDER BY + +```php +$q = Builder::table('users') + ->orderBy('created_at DESC') + ->build(); +// ORDER BY created_at DESC +``` + +### GROUP BY + +```php +$q = Builder::table('orders') + ->select(['user_id', 'COUNT(*) as order_count']) + ->groupBy('user_id') + ->build(); +// SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id +``` + +### LIMIT과 OFFSET + +```php +$q = Builder::table('users') + ->limit(10) + ->build(); +// LIMIT 10 + +$q = Builder::table('users') + ->limit(10, 20) // limit, offset + ->build(); +// LIMIT 10 OFFSET 20 +``` + +--- + +## Raw SQL 표현식 + +SQL 함수나 바운드 파라미터로 처리하면 안 되는 표현식이 필요할 때 `raw()`를 사용합니다. + +### 기본 Raw + +```php +$q = Builder::table('users') + ->update([ + 'login_count' => Builder::raw('login_count + 1'), + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => 123]) + ->build(); +// SET login_count = login_count + 1, updated_at = NOW() +``` + +### 바운드 파라미터가 있는 Raw + +```php +$q = Builder::table('orders') + ->update([ + 'total' => Builder::raw('COALESCE(subtotal, ?) + ?', [0, 10]) + ]) + ->where(['id' => 1]) + ->build(); +// SET total = COALESCE(subtotal, ?) + ? +// params: [0, 10, 1] +``` + +### WHERE에서 Raw (서브쿼리) + +```php +$q = Builder::table('products') + ->where([ + 'price' => ['>', Builder::raw('(SELECT AVG(price) FROM products)')] + ]) + ->build(); +// WHERE price > (SELECT AVG(price) FROM products) +``` + +### 사용자 입력에 대한 안전한 식별자 + +컬럼 이름이 사용자 입력에서 올 때, `safeIdentifier()`를 사용하여 SQL 인젝션을 방지합니다: + +```php +$sortColumn = $_GET['sort']; // 예: 'created_at' +$safeColumn = Builder::safeIdentifier($sortColumn); + +$q = Builder::table('users') + ->orderBy($safeColumn . ' DESC') + ->build(); + +// 사용자가 "name; DROP TABLE users--"를 시도하면 +// InvalidArgumentException 발생 +``` + +### 사용자 제공 컬럼 이름에 대한 rawSafe + +```php +$userColumn = $_GET['aggregate_column']; + +$q = Builder::table('orders') + ->select([ + Builder::rawSafe('SUM({col})', ['col' => $userColumn])->value . ' AS total' + ]) + ->build(); +// 컬럼 이름 유효성 검사, 유효하지 않으면 예외 발생 +``` + +> **경고:** 사용자 입력을 절대 `raw()`에 직접 연결하지 마세요. 항상 바운드 파라미터나 `safeIdentifier()`를 사용하세요. + +--- + +## 쿼리 빌더 재사용 + +### Clear 메서드 + +빌더를 재사용하기 위해 특정 부분을 초기화합니다: + +```php +$query = Builder::table('users') + ->select(['id', 'name']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// 첫 번째 쿼리 +$q1 = $query->limit(10)->build(); + +// 초기화하고 재사용 +$query->clearWhere()->clearLimit(); + +// 다른 조건으로 두 번째 쿼리 +$q2 = $query + ->where(['status' => 'pending']) + ->limit(5) + ->build(); +``` + +### 사용 가능한 Clear 메서드 + +| 메서드 | 설명 | +|--------|------| +| `clearWhere()` | WHERE 조건과 파라미터 초기화 | +| `clearSelect()` | SELECT 컬럼을 기본값 '*'로 초기화 | +| `clearJoin()` | 모든 JOIN 절 초기화 | +| `clearGroupBy()` | GROUP BY 절 초기화 | +| `clearOrderBy()` | ORDER BY 절 초기화 | +| `clearLimit()` | LIMIT과 OFFSET 초기화 | +| `clearAll()` | 빌더를 초기 상태로 리셋 | + +### 페이지네이션 예제 + +```php +$baseQuery = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// 총 개수 가져오기 +$countQuery = clone $baseQuery; +$countResult = $countQuery->clearSelect()->count()->build(); +$total = Flight::db()->fetchField($countResult['sql'], $countResult['params']); + +// 페이지네이션된 결과 가져오기 +$page = 1; +$perPage = 20; +$listResult = $baseQuery->limit($perPage, ($page - 1) * $perPage)->build(); +$users = Flight::db()->fetchAll($listResult['sql'], $listResult['params']); +``` + +--- + +## 동적 쿼리 빌딩 + +```php +$query = Builder::table('products')->alias('p'); + +if (!empty($categoryId)) { + $query->where(['p.category_id' => $categoryId]); +} + +if (!empty($minPrice)) { + $query->where(['p.price' => ['>=', $minPrice]]); +} + +if (!empty($maxPrice)) { + $query->where(['p.price' => ['<=', $maxPrice]]); +} + +if (!empty($searchTerm)) { + $query->where(['p.name' => ['LIKE', "%{$searchTerm}%"]]); +} + +$result = $query->orderBy('p.created_at DESC')->limit(20)->build(); +$products = Flight::db()->fetchAll($result['sql'], $result['params']); +``` + +--- + +## FlightPHP 전체 예제 + +```php +use KnifeLemon\EasyQuery\Builder; + +// 페이지네이션으로 사용자 목록 조회 +Flight::route('GET /users', function() { + $page = (int) (Flight::request()->query['page'] ?? 1); + $perPage = 20; + + $q = Builder::table('users') + ->select(['id', 'name', 'email', 'created_at']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit($perPage, ($page - 1) * $perPage) + ->build(); + + $users = Flight::db()->fetchAll($q['sql'], $q['params']); + Flight::json(['users' => $users, 'page' => $page]); +}); + +// 사용자 생성 +Flight::route('POST /users', function() { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->insert([ + 'name' => $data->name, + 'email' => $data->email, + 'created_at' => Builder::raw('NOW()') + ]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['id' => Flight::db()->lastInsertId()]); +}); + +// 사용자 업데이트 +Flight::route('PUT /users/@id', function($id) { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->update([ + 'name' => $data->name, + 'email' => $data->email, + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); + +// 사용자 삭제 +Flight::route('DELETE /users/@id', function($id) { + $q = Builder::table('users') + ->delete() + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); +``` + +--- + +## API 레퍼런스 + +### 정적 메서드 + +| 메서드 | 설명 | +|--------|------| +| `Builder::table(string $table)` | 테이블에 대한 새 빌더 인스턴스 생성 | +| `Builder::raw(string $sql, array $bindings = [])` | Raw SQL 표현식 생성 | +| `Builder::rawSafe(string $expr, array $identifiers, array $bindings = [])` | 안전한 식별자 치환이 있는 Raw 표현식 | +| `Builder::safeIdentifier(string $identifier)` | 안전한 컬럼/테이블 이름 검증 및 반환 | + +### 인스턴스 메서드 + +| 메서드 | 설명 | +|--------|------| +| `alias(string $alias)` | 테이블 별칭 설정 | +| `select(string\|array $columns)` | 선택할 컬럼 설정 (기본값: '*') | +| `where(array $conditions)` | WHERE 조건 추가 (AND) | +| `orWhere(array $conditions)` | OR WHERE 조건 추가 | +| `join(string $table, string $condition, string $alias, string $type)` | JOIN 절 추가 | +| `innerJoin(string $table, string $condition, string $alias)` | INNER JOIN 추가 | +| `leftJoin(string $table, string $condition, string $alias)` | LEFT JOIN 추가 | +| `groupBy(string $groupBy)` | GROUP BY 절 추가 | +| `orderBy(string $orderBy)` | ORDER BY 절 추가 | +| `limit(int $limit, int $offset = 0)` | LIMIT과 OFFSET 추가 | +| `count(string $column = '*')` | COUNT 쿼리로 설정 | +| `insert(array $data)` | INSERT 쿼리로 설정 | +| `update(array $data)` | UPDATE 쿼리로 설정 | +| `delete()` | DELETE 쿼리로 설정 | +| `build()` | `['sql' => ..., 'params' => ...]` 빌드 및 반환 | +| `get()` | `build()`의 별칭 | + +--- + +## Tracy 디버거 통합 + +EasyQuery는 Tracy Debugger가 설치되어 있으면 자동으로 통합됩니다. 설정이 필요 없습니다! + +```bash +composer require tracy/tracy +``` + +```php +use Tracy\Debugger; + +Debugger::enable(); + +// 모든 쿼리가 자동으로 Tracy 패널에 기록됩니다 +$q = Builder::table('users')->where(['status' => 'active'])->build(); +``` + +Tracy 패널에서 보여주는 것: +- 총 쿼리 수와 타입별 분류 +- 생성된 SQL (구문 강조) +- 파라미터 배열 +- 쿼리 세부 정보 (테이블, where, join 등) + +전체 문서는 [GitHub 저장소](https://github.com/knifelemon/EasyQueryBuilder)를 참조하세요. diff --git a/content/v3/lv/awesome-plugins/awesome_plugins.md b/content/v3/lv/awesome-plugins/awesome_plugins.md index 8fe779d7..6857af21 100644 --- a/content/v3/lv/awesome-plugins/awesome_plugins.md +++ b/content/v3/lv/awesome-plugins/awesome_plugins.md @@ -65,6 +65,7 @@ Datubāzes ir kodols lielākajai daļai aplikāciju. Tā ir veids, kā uzglabāt - novecojis [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Oficiālais Flight PDO Apvalks, kas ir kodola daļa (novecojis no v3.18.0). Izmantojiet SimplePdo vietā. - oficiāls [flightphp/active-record](/awesome-plugins/active-record) - Oficiālā Flight ActiveRecord ORM/Mapper. Lieliska maza bibliotēka, lai viegli izgūtu un uzglabātu datus jūsu datubāzē. - [byjg/php-migration](/awesome-plugins/migrations) - Spraudnis, lai sekotu visām datubāzes izmaiņām jūsu projektā. +- [knifelemon/easy-query](/awesome-plugins/easy-query) - Viegls, plūstošs SQL vaicājumu veidotājs, kas ģenerē SQL un parametrus prepared statements. Lieliski strādā ar [SimplePdo](/learn/simple-pdo). ## Šifrēšana diff --git a/content/v3/lv/awesome-plugins/easy_query.md b/content/v3/lv/awesome-plugins/easy_query.md new file mode 100644 index 00000000..b5f7d212 --- /dev/null +++ b/content/v3/lv/awesome-plugins/easy_query.md @@ -0,0 +1,569 @@ +# EasyQuery + +[knifelemon/easy-query](https://github.com/knifelemon/EasyQueryBuilder) ir viegls, plūstošs SQL vaicājumu veidotājs, kas ģenerē SQL un parametrus prepared statements. Strādā ar [SimplePdo](/learn/simple-pdo). + +## Iespējas + +- 🔗 **Plūstoša API** - Ķēdētas metodes lasāmai vaicājumu veidošanai +- 🛡️ **SQL injekcijas aizsardzība** - Automātiska parametru saistīšana ar prepared statements +- 🔧 **Raw SQL atbalsts** - Ievietojiet SQL izteiksmes tieši ar `raw()` +- 📝 **Vairāki vaicājumu tipi** - SELECT, INSERT, UPDATE, DELETE, COUNT +- 🔀 **JOIN atbalsts** - INNER, LEFT, RIGHT join ar aizstājvārdiem +- 🎯 **Paplašināti nosacījumi** - LIKE, IN, NOT IN, BETWEEN, salīdzināšanas operatori +- 🌐 **Datubāzes neatkarīgs** - Atgriež SQL + params, izmantojiet ar jebkuru DB savienojumu +- 🪶 **Viegls** - Minimāls izmērs bez atkarībām + +## Instalācija + +```bash +composer require knifelemon/easy-query +``` + +## Ātrais sākums + +```php +use KnifeLemon\EasyQuery\Builder; + +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit(10) + ->build(); + +// Izmantojiet ar Flight SimplePdo +$users = Flight::db()->fetchAll($q['sql'], $q['params']); +``` + +## Izpratne par build() + +`build()` metode atgriež masīvu ar `sql` un `params`. Šī atdalīšana aizsargā jūsu datubāzi, izmantojot prepared statements. + +```php +$q = Builder::table('users') + ->where(['email' => 'user@example.com']) + ->build(); + +// Atgriež: +// [ +// 'sql' => 'SELECT * FROM users WHERE email = ?', +// 'params' => ['user@example.com'] +// ] +``` + +--- + +## Vaicājumu tipi + +### SELECT + +```php +// Atlasīt visas kolonnas +$q = Builder::table('users')->build(); +// SELECT * FROM users + +// Atlasīt konkrētas kolonnas +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->build(); +// SELECT id, name, email FROM users + +// Ar tabulas aizstājvārdu +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name']) + ->build(); +// SELECT u.id, u.name FROM users AS u +``` + +### INSERT + +```php +$q = Builder::table('users') + ->insert([ + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'status' => 'active' + ]) + ->build(); +// INSERT INTO users SET name = ?, email = ?, status = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +$userId = Flight::db()->lastInsertId(); +``` + +### UPDATE + +```php +$q = Builder::table('users') + ->update(['status' => 'inactive', 'updated_at' => date('Y-m-d H:i:s')]) + ->where(['id' => 123]) + ->build(); +// UPDATE users SET status = ?, updated_at = ? WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### DELETE + +```php +$q = Builder::table('users') + ->delete() + ->where(['id' => 123]) + ->build(); +// DELETE FROM users WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### COUNT + +```php +$q = Builder::table('users') + ->count() + ->where(['status' => 'active']) + ->build(); +// SELECT COUNT(*) AS cnt FROM users WHERE status = ? + +$count = Flight::db()->fetchField($q['sql'], $q['params']); +``` + +--- + +## WHERE nosacījumi + +### Vienkārša vienādība + +```php +$q = Builder::table('users') + ->where(['id' => 123, 'status' => 'active']) + ->build(); +// WHERE id = ? AND status = ? +``` + +### Salīdzināšanas operatori + +```php +$q = Builder::table('users') + ->where([ + 'age' => ['>=', 18], + 'score' => ['<', 100], + 'name' => ['!=', 'admin'] + ]) + ->build(); +// WHERE age >= ? AND score < ? AND name != ? +``` + +### LIKE + +```php +$q = Builder::table('users') + ->where(['name' => ['LIKE', '%john%']]) + ->build(); +// WHERE name LIKE ? +``` + +### IN / NOT IN + +```php +// IN +$q = Builder::table('users') + ->where(['id' => ['IN', [1, 2, 3, 4, 5]]]) + ->build(); +// WHERE id IN (?, ?, ?, ?, ?) + +// NOT IN +$q = Builder::table('users') + ->where(['status' => ['NOT IN', ['banned', 'deleted']]]) + ->build(); +// WHERE status NOT IN (?, ?) +``` + +### BETWEEN + +```php +$q = Builder::table('products') + ->where(['price' => ['BETWEEN', [100, 500]]]) + ->build(); +// WHERE price BETWEEN ? AND ? +``` + +### OR nosacījumi + +Izmantojiet `orWhere()`, lai pievienotu OR grupētos nosacījumus: + +```php +$q = Builder::table('users') + ->where(['status' => 'active']) + ->orWhere([ + 'role' => 'admin', + 'permissions' => ['LIKE', '%manage%'] + ]) + ->build(); +// WHERE status = ? AND (role = ? OR permissions LIKE ?) +``` + +--- + +## JOIN + +### INNER JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name', 'p.title']) + ->innerJoin('posts', 'u.id = p.user_id', 'p') + ->build(); +// SELECT u.id, u.name, p.title FROM users AS u INNER JOIN posts AS p ON u.id = p.user_id +``` + +### LEFT JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.name', 'o.total']) + ->leftJoin('orders', 'u.id = o.user_id', 'o') + ->build(); +// ... LEFT JOIN orders AS o ON u.id = o.user_id +``` + +### Vairāki JOIN + +```php +$q = Builder::table('orders') + ->alias('o') + ->select(['o.id', 'u.name AS customer', 'p.title AS product']) + ->innerJoin('users', 'o.user_id = u.id', 'u') + ->leftJoin('order_items', 'o.id = oi.order_id', 'oi') + ->leftJoin('products', 'oi.product_id = p.id', 'p') + ->where(['o.status' => 'completed']) + ->build(); +``` + +--- + +## Kārtošana, grupēšana un limiti + +### ORDER BY + +```php +$q = Builder::table('users') + ->orderBy('created_at DESC') + ->build(); +// ORDER BY created_at DESC +``` + +### GROUP BY + +```php +$q = Builder::table('orders') + ->select(['user_id', 'COUNT(*) as order_count']) + ->groupBy('user_id') + ->build(); +// SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id +``` + +### LIMIT un OFFSET + +```php +$q = Builder::table('users') + ->limit(10) + ->build(); +// LIMIT 10 + +$q = Builder::table('users') + ->limit(10, 20) // limit, offset + ->build(); +// LIMIT 10 OFFSET 20 +``` + +--- + +## Raw SQL izteiksmes + +Izmantojiet `raw()`, kad nepieciešamas SQL funkcijas vai izteiksmes, kas nedrīkst tikt apstrādātas kā saistītie parametri. + +### Pamata Raw + +```php +$q = Builder::table('users') + ->update([ + 'login_count' => Builder::raw('login_count + 1'), + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => 123]) + ->build(); +// SET login_count = login_count + 1, updated_at = NOW() +``` + +### Raw ar saistītiem parametriem + +```php +$q = Builder::table('orders') + ->update([ + 'total' => Builder::raw('COALESCE(subtotal, ?) + ?', [0, 10]) + ]) + ->where(['id' => 1]) + ->build(); +// SET total = COALESCE(subtotal, ?) + ? +// params: [0, 10, 1] +``` + +### Raw WHERE (apakšvaicājums) + +```php +$q = Builder::table('products') + ->where([ + 'price' => ['>', Builder::raw('(SELECT AVG(price) FROM products)')] + ]) + ->build(); +// WHERE price > (SELECT AVG(price) FROM products) +``` + +### Droši identifikatori lietotāja ievadei + +Kad kolonnu nosaukumi nāk no lietotāja ievades, izmantojiet `safeIdentifier()`, lai novērstu SQL injekciju: + +```php +$sortColumn = $_GET['sort']; // piem.: 'created_at' +$safeColumn = Builder::safeIdentifier($sortColumn); + +$q = Builder::table('users') + ->orderBy($safeColumn . ' DESC') + ->build(); + +// Ja lietotājs mēģina: "name; DROP TABLE users--" +// Izmet InvalidArgumentException +``` + +### rawSafe lietotāja kolonnu nosaukumiem + +```php +$userColumn = $_GET['aggregate_column']; + +$q = Builder::table('orders') + ->select([ + Builder::rawSafe('SUM({col})', ['col' => $userColumn])->value . ' AS total' + ]) + ->build(); +// Validē kolonnas nosaukumu, izmet izņēmumu, ja nederīgs +``` + +> **Brīdinājums:** Nekad nekonkatenējiet lietotāja ievadi tieši `raw()`. Vienmēr izmantojiet saistītos parametrus vai `safeIdentifier()`. + +--- + +## Query Builder atkārtota izmantošana + +### Clear metodes + +Notīriet konkrētas daļas, lai atkārtoti izmantotu builder: + +```php +$query = Builder::table('users') + ->select(['id', 'name']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Pirmais vaicājums +$q1 = $query->limit(10)->build(); + +// Notīrīt un izmantot atkārtoti +$query->clearWhere()->clearLimit(); + +// Otrais vaicājums ar citiem nosacījumiem +$q2 = $query + ->where(['status' => 'pending']) + ->limit(5) + ->build(); +``` + +### Pieejamās Clear metodes + +| Metode | Apraksts | +|--------|----------| +| `clearWhere()` | Notīrīt WHERE nosacījumus un parametrus | +| `clearSelect()` | Atiestatīt SELECT kolonnas uz noklusējuma '*' | +| `clearJoin()` | Notīrīt visas JOIN klauzulas | +| `clearGroupBy()` | Notīrīt GROUP BY klauzulu | +| `clearOrderBy()` | Notīrīt ORDER BY klauzulu | +| `clearLimit()` | Notīrīt LIMIT un OFFSET | +| `clearAll()` | Atiestatīt builder sākuma stāvoklī | + +### Lapošanas piemērs + +```php +$baseQuery = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Iegūt kopējo skaitu +$countQuery = clone $baseQuery; +$countResult = $countQuery->clearSelect()->count()->build(); +$total = Flight::db()->fetchField($countResult['sql'], $countResult['params']); + +// Iegūt lapotus rezultātus +$page = 1; +$perPage = 20; +$listResult = $baseQuery->limit($perPage, ($page - 1) * $perPage)->build(); +$users = Flight::db()->fetchAll($listResult['sql'], $listResult['params']); +``` + +--- + +## Dinamiska vaicājumu veidošana + +```php +$query = Builder::table('products')->alias('p'); + +if (!empty($categoryId)) { + $query->where(['p.category_id' => $categoryId]); +} + +if (!empty($minPrice)) { + $query->where(['p.price' => ['>=', $minPrice]]); +} + +if (!empty($maxPrice)) { + $query->where(['p.price' => ['<=', $maxPrice]]); +} + +if (!empty($searchTerm)) { + $query->where(['p.name' => ['LIKE', "%{$searchTerm}%"]]); +} + +$result = $query->orderBy('p.created_at DESC')->limit(20)->build(); +$products = Flight::db()->fetchAll($result['sql'], $result['params']); +``` + +--- + +## Pilns FlightPHP piemērs + +```php +use KnifeLemon\EasyQuery\Builder; + +// Lietotāju saraksts ar lapošanu +Flight::route('GET /users', function() { + $page = (int) (Flight::request()->query['page'] ?? 1); + $perPage = 20; + + $q = Builder::table('users') + ->select(['id', 'name', 'email', 'created_at']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit($perPage, ($page - 1) * $perPage) + ->build(); + + $users = Flight::db()->fetchAll($q['sql'], $q['params']); + Flight::json(['users' => $users, 'page' => $page]); +}); + +// Izveidot lietotāju +Flight::route('POST /users', function() { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->insert([ + 'name' => $data->name, + 'email' => $data->email, + 'created_at' => Builder::raw('NOW()') + ]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['id' => Flight::db()->lastInsertId()]); +}); + +// Atjaunināt lietotāju +Flight::route('PUT /users/@id', function($id) { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->update([ + 'name' => $data->name, + 'email' => $data->email, + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); + +// Dzēst lietotāju +Flight::route('DELETE /users/@id', function($id) { + $q = Builder::table('users') + ->delete() + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); +``` + +--- + +## API atsauce + +### Statiskās metodes + +| Metode | Apraksts | +|--------|----------| +| `Builder::table(string $table)` | Izveidot jaunu builder instanci tabulai | +| `Builder::raw(string $sql, array $bindings = [])` | Izveidot raw SQL izteiksmi | +| `Builder::rawSafe(string $expr, array $identifiers, array $bindings = [])` | Raw izteiksme ar drošu identifikatoru aizstāšanu | +| `Builder::safeIdentifier(string $identifier)` | Validēt un atgriezt drošu kolonnas/tabulas nosaukumu | + +### Instances metodes + +| Metode | Apraksts | +|--------|----------| +| `alias(string $alias)` | Iestatīt tabulas aizstājvārdu | +| `select(string\|array $columns)` | Iestatīt atlasāmās kolonnas (noklusējums: '*') | +| `where(array $conditions)` | Pievienot WHERE nosacījumus (AND) | +| `orWhere(array $conditions)` | Pievienot OR WHERE nosacījumus | +| `join(string $table, string $condition, string $alias, string $type)` | Pievienot JOIN klauzulu | +| `innerJoin(string $table, string $condition, string $alias)` | Pievienot INNER JOIN | +| `leftJoin(string $table, string $condition, string $alias)` | Pievienot LEFT JOIN | +| `groupBy(string $groupBy)` | Pievienot GROUP BY klauzulu | +| `orderBy(string $orderBy)` | Pievienot ORDER BY klauzulu | +| `limit(int $limit, int $offset = 0)` | Pievienot LIMIT un OFFSET | +| `count(string $column = '*')` | Iestatīt vaicājumu uz COUNT | +| `insert(array $data)` | Iestatīt vaicājumu uz INSERT | +| `update(array $data)` | Iestatīt vaicājumu uz UPDATE | +| `delete()` | Iestatīt vaicājumu uz DELETE | +| `build()` | Izveidot un atgriezt `['sql' => ..., 'params' => ...]` | +| `get()` | Aizstājvārds `build()` | + +--- + +## Tracy atkļūdotāja integrācija + +EasyQuery automātiski integrējas ar Tracy Debugger, ja tas ir instalēts. Nav nepieciešama konfigurācija! + +```bash +composer require tracy/tracy +``` + +```php +use Tracy\Debugger; + +Debugger::enable(); + +// Visi vaicājumi automātiski tiek reģistrēti Tracy panelī +$q = Builder::table('users')->where(['status' => 'active'])->build(); +``` + +Tracy panelis rāda: +- Kopējo vaicājumu skaitu un sadalījumu pa tipiem +- Ģenerēto SQL (sintakses izcelšana) +- Parametru masīvu +- Vaicājuma detaļas (tabula, where, join utt.) + +Pilnai dokumentācijai apmeklējiet [GitHub repozitoriju](https://github.com/knifelemon/EasyQueryBuilder). diff --git a/content/v3/pt/awesome-plugins/awesome_plugins.md b/content/v3/pt/awesome-plugins/awesome_plugins.md index 6d3b57b2..cc2c957b 100644 --- a/content/v3/pt/awesome-plugins/awesome_plugins.md +++ b/content/v3/pt/awesome-plugins/awesome_plugins.md @@ -65,6 +65,7 @@ Bancos de dados são o núcleo da maioria das aplicações. É assim que você a - deprecado [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Wrapper PDO oficial do Flight que faz parte do núcleo (deprecado a partir da v3.18.0). Use SimplePdo em vez disso. - oficial [flightphp/active-record](/awesome-plugins/active-record) - ORM/Mapper ActiveRecord oficial do Flight. Ótima biblioteca pequena para recuperar e armazenar dados facilmente em seu banco de dados. - [byjg/php-migration](/awesome-plugins/migrations) - Plugin para rastrear todas as alterações de banco de dados para seu projeto. +- [knifelemon/easy-query](/awesome-plugins/easy-query) - Construtor de consultas SQL leve e fluente que gera SQL e parâmetros para prepared statements. Funciona muito bem com [SimplePdo](/learn/simple-pdo). ## Criptografia diff --git a/content/v3/pt/awesome-plugins/easy_query.md b/content/v3/pt/awesome-plugins/easy_query.md new file mode 100644 index 00000000..33890ce4 --- /dev/null +++ b/content/v3/pt/awesome-plugins/easy_query.md @@ -0,0 +1,569 @@ +# EasyQuery + +[knifelemon/easy-query](https://github.com/knifelemon/EasyQueryBuilder) é um construtor de consultas SQL leve e fluente que gera SQL e parâmetros para prepared statements. Funciona com [SimplePdo](/learn/simple-pdo). + +## Recursos + +- 🔗 **API Fluente** - Métodos encadeados para construção de consultas legíveis +- 🛡️ **Proteção contra SQL Injection** - Vinculação automática de parâmetros com prepared statements +- 🔧 **Suporte Raw SQL** - Inserir expressões SQL diretamente com `raw()` +- 📝 **Múltiplos Tipos de Consulta** - SELECT, INSERT, UPDATE, DELETE, COUNT +- 🔀 **Suporte JOIN** - INNER, LEFT, RIGHT joins com aliases +- 🎯 **Condições Avançadas** - LIKE, IN, NOT IN, BETWEEN, operadores de comparação +- 🌐 **Agnóstico de Banco de Dados** - Retorna SQL + params, use com qualquer conexão DB +- 🪶 **Leve** - Footprint mínimo sem dependências + +## Instalação + +```bash +composer require knifelemon/easy-query +``` + +## Início Rápido + +```php +use KnifeLemon\EasyQuery\Builder; + +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit(10) + ->build(); + +// Usar com SimplePdo do Flight +$users = Flight::db()->fetchAll($q['sql'], $q['params']); +``` + +## Entendendo build() + +O método `build()` retorna um array com `sql` e `params`. Esta separação mantém seu banco de dados seguro usando prepared statements. + +```php +$q = Builder::table('users') + ->where(['email' => 'user@example.com']) + ->build(); + +// Retorna: +// [ +// 'sql' => 'SELECT * FROM users WHERE email = ?', +// 'params' => ['user@example.com'] +// ] +``` + +--- + +## Tipos de Consulta + +### SELECT + +```php +// Selecionar todas as colunas +$q = Builder::table('users')->build(); +// SELECT * FROM users + +// Selecionar colunas específicas +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->build(); +// SELECT id, name, email FROM users + +// Com alias de tabela +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name']) + ->build(); +// SELECT u.id, u.name FROM users AS u +``` + +### INSERT + +```php +$q = Builder::table('users') + ->insert([ + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'status' => 'active' + ]) + ->build(); +// INSERT INTO users SET name = ?, email = ?, status = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +$userId = Flight::db()->lastInsertId(); +``` + +### UPDATE + +```php +$q = Builder::table('users') + ->update(['status' => 'inactive', 'updated_at' => date('Y-m-d H:i:s')]) + ->where(['id' => 123]) + ->build(); +// UPDATE users SET status = ?, updated_at = ? WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### DELETE + +```php +$q = Builder::table('users') + ->delete() + ->where(['id' => 123]) + ->build(); +// DELETE FROM users WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### COUNT + +```php +$q = Builder::table('users') + ->count() + ->where(['status' => 'active']) + ->build(); +// SELECT COUNT(*) AS cnt FROM users WHERE status = ? + +$count = Flight::db()->fetchField($q['sql'], $q['params']); +``` + +--- + +## Condições WHERE + +### Igualdade Simples + +```php +$q = Builder::table('users') + ->where(['id' => 123, 'status' => 'active']) + ->build(); +// WHERE id = ? AND status = ? +``` + +### Operadores de Comparação + +```php +$q = Builder::table('users') + ->where([ + 'age' => ['>=', 18], + 'score' => ['<', 100], + 'name' => ['!=', 'admin'] + ]) + ->build(); +// WHERE age >= ? AND score < ? AND name != ? +``` + +### LIKE + +```php +$q = Builder::table('users') + ->where(['name' => ['LIKE', '%john%']]) + ->build(); +// WHERE name LIKE ? +``` + +### IN / NOT IN + +```php +// IN +$q = Builder::table('users') + ->where(['id' => ['IN', [1, 2, 3, 4, 5]]]) + ->build(); +// WHERE id IN (?, ?, ?, ?, ?) + +// NOT IN +$q = Builder::table('users') + ->where(['status' => ['NOT IN', ['banned', 'deleted']]]) + ->build(); +// WHERE status NOT IN (?, ?) +``` + +### BETWEEN + +```php +$q = Builder::table('products') + ->where(['price' => ['BETWEEN', [100, 500]]]) + ->build(); +// WHERE price BETWEEN ? AND ? +``` + +### Condições OR + +Use `orWhere()` para adicionar condições agrupadas com OR: + +```php +$q = Builder::table('users') + ->where(['status' => 'active']) + ->orWhere([ + 'role' => 'admin', + 'permissions' => ['LIKE', '%manage%'] + ]) + ->build(); +// WHERE status = ? AND (role = ? OR permissions LIKE ?) +``` + +--- + +## JOIN + +### INNER JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name', 'p.title']) + ->innerJoin('posts', 'u.id = p.user_id', 'p') + ->build(); +// SELECT u.id, u.name, p.title FROM users AS u INNER JOIN posts AS p ON u.id = p.user_id +``` + +### LEFT JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.name', 'o.total']) + ->leftJoin('orders', 'u.id = o.user_id', 'o') + ->build(); +// ... LEFT JOIN orders AS o ON u.id = o.user_id +``` + +### Múltiplos JOINs + +```php +$q = Builder::table('orders') + ->alias('o') + ->select(['o.id', 'u.name AS customer', 'p.title AS product']) + ->innerJoin('users', 'o.user_id = u.id', 'u') + ->leftJoin('order_items', 'o.id = oi.order_id', 'oi') + ->leftJoin('products', 'oi.product_id = p.id', 'p') + ->where(['o.status' => 'completed']) + ->build(); +``` + +--- + +## Ordenação, Agrupamento e Limites + +### ORDER BY + +```php +$q = Builder::table('users') + ->orderBy('created_at DESC') + ->build(); +// ORDER BY created_at DESC +``` + +### GROUP BY + +```php +$q = Builder::table('orders') + ->select(['user_id', 'COUNT(*) as order_count']) + ->groupBy('user_id') + ->build(); +// SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id +``` + +### LIMIT e OFFSET + +```php +$q = Builder::table('users') + ->limit(10) + ->build(); +// LIMIT 10 + +$q = Builder::table('users') + ->limit(10, 20) // limit, offset + ->build(); +// LIMIT 10 OFFSET 20 +``` + +--- + +## Expressões Raw SQL + +Use `raw()` quando precisar de funções SQL ou expressões que não devem ser tratadas como parâmetros vinculados. + +### Raw Básico + +```php +$q = Builder::table('users') + ->update([ + 'login_count' => Builder::raw('login_count + 1'), + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => 123]) + ->build(); +// SET login_count = login_count + 1, updated_at = NOW() +``` + +### Raw com Parâmetros Vinculados + +```php +$q = Builder::table('orders') + ->update([ + 'total' => Builder::raw('COALESCE(subtotal, ?) + ?', [0, 10]) + ]) + ->where(['id' => 1]) + ->build(); +// SET total = COALESCE(subtotal, ?) + ? +// params: [0, 10, 1] +``` + +### Raw em WHERE (Subconsulta) + +```php +$q = Builder::table('products') + ->where([ + 'price' => ['>', Builder::raw('(SELECT AVG(price) FROM products)')] + ]) + ->build(); +// WHERE price > (SELECT AVG(price) FROM products) +``` + +### Identificadores Seguros para Entrada do Usuário + +Quando nomes de colunas vêm de entrada do usuário, use `safeIdentifier()` para prevenir SQL injection: + +```php +$sortColumn = $_GET['sort']; // ex: 'created_at' +$safeColumn = Builder::safeIdentifier($sortColumn); + +$q = Builder::table('users') + ->orderBy($safeColumn . ' DESC') + ->build(); + +// Se o usuário tentar: "name; DROP TABLE users--" +// Lança InvalidArgumentException +``` + +### rawSafe para Nomes de Colunas do Usuário + +```php +$userColumn = $_GET['aggregate_column']; + +$q = Builder::table('orders') + ->select([ + Builder::rawSafe('SUM({col})', ['col' => $userColumn])->value . ' AS total' + ]) + ->build(); +// Valida o nome da coluna, lança exceção se inválido +``` + +> **Aviso:** Nunca concatene entrada do usuário diretamente em `raw()`. Sempre use parâmetros vinculados ou `safeIdentifier()`. + +--- + +## Reutilização do Query Builder + +### Métodos Clear + +Limpe partes específicas para reutilizar o builder: + +```php +$query = Builder::table('users') + ->select(['id', 'name']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Primeira consulta +$q1 = $query->limit(10)->build(); + +// Limpar e reutilizar +$query->clearWhere()->clearLimit(); + +// Segunda consulta com condições diferentes +$q2 = $query + ->where(['status' => 'pending']) + ->limit(5) + ->build(); +``` + +### Métodos Clear Disponíveis + +| Método | Descrição | +|--------|-----------| +| `clearWhere()` | Limpar condições WHERE e parâmetros | +| `clearSelect()` | Resetar colunas SELECT para padrão '*' | +| `clearJoin()` | Limpar todas as cláusulas JOIN | +| `clearGroupBy()` | Limpar cláusula GROUP BY | +| `clearOrderBy()` | Limpar cláusula ORDER BY | +| `clearLimit()` | Limpar LIMIT e OFFSET | +| `clearAll()` | Resetar builder ao estado inicial | + +### Exemplo de Paginação + +```php +$baseQuery = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Obter contagem total +$countQuery = clone $baseQuery; +$countResult = $countQuery->clearSelect()->count()->build(); +$total = Flight::db()->fetchField($countResult['sql'], $countResult['params']); + +// Obter resultados paginados +$page = 1; +$perPage = 20; +$listResult = $baseQuery->limit($perPage, ($page - 1) * $perPage)->build(); +$users = Flight::db()->fetchAll($listResult['sql'], $listResult['params']); +``` + +--- + +## Construção Dinâmica de Consultas + +```php +$query = Builder::table('products')->alias('p'); + +if (!empty($categoryId)) { + $query->where(['p.category_id' => $categoryId]); +} + +if (!empty($minPrice)) { + $query->where(['p.price' => ['>=', $minPrice]]); +} + +if (!empty($maxPrice)) { + $query->where(['p.price' => ['<=', $maxPrice]]); +} + +if (!empty($searchTerm)) { + $query->where(['p.name' => ['LIKE', "%{$searchTerm}%"]]); +} + +$result = $query->orderBy('p.created_at DESC')->limit(20)->build(); +$products = Flight::db()->fetchAll($result['sql'], $result['params']); +``` + +--- + +## Exemplo Completo FlightPHP + +```php +use KnifeLemon\EasyQuery\Builder; + +// Listar usuários com paginação +Flight::route('GET /users', function() { + $page = (int) (Flight::request()->query['page'] ?? 1); + $perPage = 20; + + $q = Builder::table('users') + ->select(['id', 'name', 'email', 'created_at']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit($perPage, ($page - 1) * $perPage) + ->build(); + + $users = Flight::db()->fetchAll($q['sql'], $q['params']); + Flight::json(['users' => $users, 'page' => $page]); +}); + +// Criar usuário +Flight::route('POST /users', function() { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->insert([ + 'name' => $data->name, + 'email' => $data->email, + 'created_at' => Builder::raw('NOW()') + ]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['id' => Flight::db()->lastInsertId()]); +}); + +// Atualizar usuário +Flight::route('PUT /users/@id', function($id) { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->update([ + 'name' => $data->name, + 'email' => $data->email, + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); + +// Deletar usuário +Flight::route('DELETE /users/@id', function($id) { + $q = Builder::table('users') + ->delete() + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); +``` + +--- + +## Referência API + +### Métodos Estáticos + +| Método | Descrição | +|--------|-----------| +| `Builder::table(string $table)` | Criar nova instância do builder para a tabela | +| `Builder::raw(string $sql, array $bindings = [])` | Criar expressão SQL bruta | +| `Builder::rawSafe(string $expr, array $identifiers, array $bindings = [])` | Expressão raw com substituição segura de identificadores | +| `Builder::safeIdentifier(string $identifier)` | Validar e retornar nome seguro de coluna/tabela | + +### Métodos de Instância + +| Método | Descrição | +|--------|-----------| +| `alias(string $alias)` | Definir alias da tabela | +| `select(string\|array $columns)` | Definir colunas a selecionar (padrão: '*') | +| `where(array $conditions)` | Adicionar condições WHERE (AND) | +| `orWhere(array $conditions)` | Adicionar condições OR WHERE | +| `join(string $table, string $condition, string $alias, string $type)` | Adicionar cláusula JOIN | +| `innerJoin(string $table, string $condition, string $alias)` | Adicionar INNER JOIN | +| `leftJoin(string $table, string $condition, string $alias)` | Adicionar LEFT JOIN | +| `groupBy(string $groupBy)` | Adicionar cláusula GROUP BY | +| `orderBy(string $orderBy)` | Adicionar cláusula ORDER BY | +| `limit(int $limit, int $offset = 0)` | Adicionar LIMIT e OFFSET | +| `count(string $column = '*')` | Definir consulta para COUNT | +| `insert(array $data)` | Definir consulta para INSERT | +| `update(array $data)` | Definir consulta para UPDATE | +| `delete()` | Definir consulta para DELETE | +| `build()` | Construir e retornar `['sql' => ..., 'params' => ...]` | +| `get()` | Alias para `build()` | + +--- + +## Integração Tracy Debugger + +EasyQuery se integra automaticamente com Tracy Debugger se instalado. Sem configuração necessária! + +```bash +composer require tracy/tracy +``` + +```php +use Tracy\Debugger; + +Debugger::enable(); + +// Todas as consultas são automaticamente registradas no painel Tracy +$q = Builder::table('users')->where(['status' => 'active'])->build(); +``` + +O painel Tracy mostra: +- Total de consultas e detalhamento por tipo +- SQL gerado (destaque de sintaxe) +- Array de parâmetros +- Detalhes da consulta (tabela, where, joins, etc.) + +Para documentação completa, visite o [repositório GitHub](https://github.com/knifelemon/EasyQueryBuilder). diff --git a/content/v3/ru/awesome-plugins/awesome_plugins.md b/content/v3/ru/awesome-plugins/awesome_plugins.md index b11921ce..71173f6c 100644 --- a/content/v3/ru/awesome-plugins/awesome_plugins.md +++ b/content/v3/ru/awesome-plugins/awesome_plugins.md @@ -64,8 +64,7 @@ CLI-приложения — отличный способ взаимодейс - official [flightphp/core SimplePdo](/learn/simple-pdo) — Официальный помощник Flight PDO, который является частью ядра. Это современная обёртка с удобными методами, такими как `insert()`, `update()`, `delete()` и `transaction()`, для упрощения операций с базой данных. Все результаты возвращаются как Collections для гибкого доступа к массивам/объектам. Не ORM, просто лучший способ работать с PDO. - deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) — Официальная обёртка Flight PDO, которая является частью ядра (устарела с версии 3.18.0). Используйте SimplePdo вместо неё. - official [flightphp/active-record](/awesome-plugins/active-record) — Официальный ORM/Mapper Flight ActiveRecord. Отличная маленькая библиотека для лёгкого извлечения и хранения данных в вашей базе данных. -- [byjg/php-migration](/awesome-plugins/migrations) — Плагин для отслеживания всех изменений базы данных в вашем проекте. - +- [byjg/php-migration](/awesome-plugins/migrations) — Плагин для отслеживания всех изменений базы данных в вашем проекте.- [knifelemon/easy-query](/awesome-plugins/easy-query) - Лёгкий, fluent SQL-конструктор запросов, который генерирует SQL и параметры для prepared statements. Отлично работает с [SimplePdo](/learn/simple-pdo). ## Шифрование Шифрование крайне важно для любого приложения, которое хранит конфиденциальные данные. Шифрование и дешифрование данных не так уж сложно, но правильное хранение ключа шифрования [может](https://stackoverflow.com/questions/6767839/where-should-i-store-an-encryption-key-for-php#:~:text=Write%20a%20php%20config%20file%20and%20store%20it,folder%20is%20not%20accessible%20to%20the%20end%20user.) [быть](https://www.reddit.com/r/PHP/comments/luqsn/the_encryption_key_where_do_you_store_it/) [сложным](https://security.stackexchange.com/questions/48047/location-to-store-an-encryption-key). Самое важное — никогда не хранить ключ шифрования в публичной директории или коммитить его в репозиторий кода. diff --git a/content/v3/ru/awesome-plugins/easy_query.md b/content/v3/ru/awesome-plugins/easy_query.md new file mode 100644 index 00000000..e08254f2 --- /dev/null +++ b/content/v3/ru/awesome-plugins/easy_query.md @@ -0,0 +1,569 @@ +# EasyQuery + +[knifelemon/easy-query](https://github.com/knifelemon/EasyQueryBuilder) — это легковесный, fluent SQL-конструктор запросов, который генерирует SQL и параметры для prepared statements. Работает с [SimplePdo](/learn/simple-pdo). + +## Возможности + +- 🔗 **Fluent API** - Цепочные методы для читаемого построения запросов +- 🛡️ **Защита от SQL Injection** - Автоматическое связывание параметров с prepared statements +- 🔧 **Поддержка Raw SQL** - Вставка SQL-выражений напрямую через `raw()` +- 📝 **Различные типы запросов** - SELECT, INSERT, UPDATE, DELETE, COUNT +- 🔀 **Поддержка JOIN** - INNER, LEFT, RIGHT joins с псевдонимами +- 🎯 **Расширенные условия** - LIKE, IN, NOT IN, BETWEEN, операторы сравнения +- 🌐 **Независимость от БД** - Возвращает SQL + params, используйте с любым соединением +- 🪶 **Легкий** - Минимальный размер без зависимостей + +## Установка + +```bash +composer require knifelemon/easy-query +``` + +## Быстрый старт + +```php +use KnifeLemon\EasyQuery\Builder; + +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit(10) + ->build(); + +// Использование с SimplePdo Flight +$users = Flight::db()->fetchAll($q['sql'], $q['params']); +``` + +## Понимание build() + +Метод `build()` возвращает массив с `sql` и `params`. Это разделение защищает вашу базу данных через использование prepared statements. + +```php +$q = Builder::table('users') + ->where(['email' => 'user@example.com']) + ->build(); + +// Возвращает: +// [ +// 'sql' => 'SELECT * FROM users WHERE email = ?', +// 'params' => ['user@example.com'] +// ] +``` + +--- + +## Типы запросов + +### SELECT + +```php +// Выбрать все колонки +$q = Builder::table('users')->build(); +// SELECT * FROM users + +// Выбрать конкретные колонки +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->build(); +// SELECT id, name, email FROM users + +// С псевдонимом таблицы +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name']) + ->build(); +// SELECT u.id, u.name FROM users AS u +``` + +### INSERT + +```php +$q = Builder::table('users') + ->insert([ + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'status' => 'active' + ]) + ->build(); +// INSERT INTO users SET name = ?, email = ?, status = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +$userId = Flight::db()->lastInsertId(); +``` + +### UPDATE + +```php +$q = Builder::table('users') + ->update(['status' => 'inactive', 'updated_at' => date('Y-m-d H:i:s')]) + ->where(['id' => 123]) + ->build(); +// UPDATE users SET status = ?, updated_at = ? WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### DELETE + +```php +$q = Builder::table('users') + ->delete() + ->where(['id' => 123]) + ->build(); +// DELETE FROM users WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### COUNT + +```php +$q = Builder::table('users') + ->count() + ->where(['status' => 'active']) + ->build(); +// SELECT COUNT(*) AS cnt FROM users WHERE status = ? + +$count = Flight::db()->fetchField($q['sql'], $q['params']); +``` + +--- + +## Условия WHERE + +### Простое равенство + +```php +$q = Builder::table('users') + ->where(['id' => 123, 'status' => 'active']) + ->build(); +// WHERE id = ? AND status = ? +``` + +### Операторы сравнения + +```php +$q = Builder::table('users') + ->where([ + 'age' => ['>=', 18], + 'score' => ['<', 100], + 'name' => ['!=', 'admin'] + ]) + ->build(); +// WHERE age >= ? AND score < ? AND name != ? +``` + +### LIKE + +```php +$q = Builder::table('users') + ->where(['name' => ['LIKE', '%john%']]) + ->build(); +// WHERE name LIKE ? +``` + +### IN / NOT IN + +```php +// IN +$q = Builder::table('users') + ->where(['id' => ['IN', [1, 2, 3, 4, 5]]]) + ->build(); +// WHERE id IN (?, ?, ?, ?, ?) + +// NOT IN +$q = Builder::table('users') + ->where(['status' => ['NOT IN', ['banned', 'deleted']]]) + ->build(); +// WHERE status NOT IN (?, ?) +``` + +### BETWEEN + +```php +$q = Builder::table('products') + ->where(['price' => ['BETWEEN', [100, 500]]]) + ->build(); +// WHERE price BETWEEN ? AND ? +``` + +### Условия OR + +Используйте `orWhere()` для добавления сгруппированных условий с OR: + +```php +$q = Builder::table('users') + ->where(['status' => 'active']) + ->orWhere([ + 'role' => 'admin', + 'permissions' => ['LIKE', '%manage%'] + ]) + ->build(); +// WHERE status = ? AND (role = ? OR permissions LIKE ?) +``` + +--- + +## JOIN + +### INNER JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name', 'p.title']) + ->innerJoin('posts', 'u.id = p.user_id', 'p') + ->build(); +// SELECT u.id, u.name, p.title FROM users AS u INNER JOIN posts AS p ON u.id = p.user_id +``` + +### LEFT JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.name', 'o.total']) + ->leftJoin('orders', 'u.id = o.user_id', 'o') + ->build(); +// ... LEFT JOIN orders AS o ON u.id = o.user_id +``` + +### Множественные JOIN + +```php +$q = Builder::table('orders') + ->alias('o') + ->select(['o.id', 'u.name AS customer', 'p.title AS product']) + ->innerJoin('users', 'o.user_id = u.id', 'u') + ->leftJoin('order_items', 'o.id = oi.order_id', 'oi') + ->leftJoin('products', 'oi.product_id = p.id', 'p') + ->where(['o.status' => 'completed']) + ->build(); +``` + +--- + +## Сортировка, группировка и лимиты + +### ORDER BY + +```php +$q = Builder::table('users') + ->orderBy('created_at DESC') + ->build(); +// ORDER BY created_at DESC +``` + +### GROUP BY + +```php +$q = Builder::table('orders') + ->select(['user_id', 'COUNT(*) as order_count']) + ->groupBy('user_id') + ->build(); +// SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id +``` + +### LIMIT и OFFSET + +```php +$q = Builder::table('users') + ->limit(10) + ->build(); +// LIMIT 10 + +$q = Builder::table('users') + ->limit(10, 20) // limit, offset + ->build(); +// LIMIT 10 OFFSET 20 +``` + +--- + +## Raw SQL выражения + +Используйте `raw()` когда нужны SQL-функции или выражения, которые не должны обрабатываться как связанные параметры. + +### Базовый Raw + +```php +$q = Builder::table('users') + ->update([ + 'login_count' => Builder::raw('login_count + 1'), + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => 123]) + ->build(); +// SET login_count = login_count + 1, updated_at = NOW() +``` + +### Raw со связанными параметрами + +```php +$q = Builder::table('orders') + ->update([ + 'total' => Builder::raw('COALESCE(subtotal, ?) + ?', [0, 10]) + ]) + ->where(['id' => 1]) + ->build(); +// SET total = COALESCE(subtotal, ?) + ? +// params: [0, 10, 1] +``` + +### Raw в WHERE (подзапрос) + +```php +$q = Builder::table('products') + ->where([ + 'price' => ['>', Builder::raw('(SELECT AVG(price) FROM products)')] + ]) + ->build(); +// WHERE price > (SELECT AVG(price) FROM products) +``` + +### Безопасные идентификаторы для пользовательского ввода + +Когда имена колонок приходят от пользователя, используйте `safeIdentifier()` для предотвращения SQL injection: + +```php +$sortColumn = $_GET['sort']; // например: 'created_at' +$safeColumn = Builder::safeIdentifier($sortColumn); + +$q = Builder::table('users') + ->orderBy($safeColumn . ' DESC') + ->build(); + +// Если пользователь попробует: "name; DROP TABLE users--" +// Выбрасывает InvalidArgumentException +``` + +### rawSafe для пользовательских имен колонок + +```php +$userColumn = $_GET['aggregate_column']; + +$q = Builder::table('orders') + ->select([ + Builder::rawSafe('SUM({col})', ['col' => $userColumn])->value . ' AS total' + ]) + ->build(); +// Валидирует имя колонки, выбрасывает исключение если невалидное +``` + +> **Предупреждение:** Никогда не конкатенируйте пользовательский ввод напрямую в `raw()`. Всегда используйте связанные параметры или `safeIdentifier()`. + +--- + +## Повторное использование Query Builder + +### Методы Clear + +Очистите конкретные части для повторного использования builder: + +```php +$query = Builder::table('users') + ->select(['id', 'name']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Первый запрос +$q1 = $query->limit(10)->build(); + +// Очистить и использовать повторно +$query->clearWhere()->clearLimit(); + +// Второй запрос с другими условиями +$q2 = $query + ->where(['status' => 'pending']) + ->limit(5) + ->build(); +``` + +### Доступные методы Clear + +| Метод | Описание | +|-------|----------| +| `clearWhere()` | Очистить условия WHERE и параметры | +| `clearSelect()` | Сбросить колонки SELECT к '*' по умолчанию | +| `clearJoin()` | Очистить все JOIN клаузы | +| `clearGroupBy()` | Очистить GROUP BY клаузу | +| `clearOrderBy()` | Очистить ORDER BY клаузу | +| `clearLimit()` | Очистить LIMIT и OFFSET | +| `clearAll()` | Сбросить builder в начальное состояние | + +### Пример пагинации + +```php +$baseQuery = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Получить общее количество +$countQuery = clone $baseQuery; +$countResult = $countQuery->clearSelect()->count()->build(); +$total = Flight::db()->fetchField($countResult['sql'], $countResult['params']); + +// Получить результаты с пагинацией +$page = 1; +$perPage = 20; +$listResult = $baseQuery->limit($perPage, ($page - 1) * $perPage)->build(); +$users = Flight::db()->fetchAll($listResult['sql'], $listResult['params']); +``` + +--- + +## Динамическое построение запросов + +```php +$query = Builder::table('products')->alias('p'); + +if (!empty($categoryId)) { + $query->where(['p.category_id' => $categoryId]); +} + +if (!empty($minPrice)) { + $query->where(['p.price' => ['>=', $minPrice]]); +} + +if (!empty($maxPrice)) { + $query->where(['p.price' => ['<=', $maxPrice]]); +} + +if (!empty($searchTerm)) { + $query->where(['p.name' => ['LIKE', "%{$searchTerm}%"]]); +} + +$result = $query->orderBy('p.created_at DESC')->limit(20)->build(); +$products = Flight::db()->fetchAll($result['sql'], $result['params']); +``` + +--- + +## Полный пример FlightPHP + +```php +use KnifeLemon\EasyQuery\Builder; + +// Список пользователей с пагинацией +Flight::route('GET /users', function() { + $page = (int) (Flight::request()->query['page'] ?? 1); + $perPage = 20; + + $q = Builder::table('users') + ->select(['id', 'name', 'email', 'created_at']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit($perPage, ($page - 1) * $perPage) + ->build(); + + $users = Flight::db()->fetchAll($q['sql'], $q['params']); + Flight::json(['users' => $users, 'page' => $page]); +}); + +// Создать пользователя +Flight::route('POST /users', function() { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->insert([ + 'name' => $data->name, + 'email' => $data->email, + 'created_at' => Builder::raw('NOW()') + ]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['id' => Flight::db()->lastInsertId()]); +}); + +// Обновить пользователя +Flight::route('PUT /users/@id', function($id) { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->update([ + 'name' => $data->name, + 'email' => $data->email, + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); + +// Удалить пользователя +Flight::route('DELETE /users/@id', function($id) { + $q = Builder::table('users') + ->delete() + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); +``` + +--- + +## API справочник + +### Статические методы + +| Метод | Описание | +|-------|----------| +| `Builder::table(string $table)` | Создать новый экземпляр builder для таблицы | +| `Builder::raw(string $sql, array $bindings = [])` | Создать raw SQL выражение | +| `Builder::rawSafe(string $expr, array $identifiers, array $bindings = [])` | Raw выражение с безопасной заменой идентификаторов | +| `Builder::safeIdentifier(string $identifier)` | Валидировать и вернуть безопасное имя колонки/таблицы | + +### Методы экземпляра + +| Метод | Описание | +|-------|----------| +| `alias(string $alias)` | Установить псевдоним таблицы | +| `select(string\|array $columns)` | Установить колонки для выборки (по умолчанию: '*') | +| `where(array $conditions)` | Добавить условия WHERE (AND) | +| `orWhere(array $conditions)` | Добавить условия OR WHERE | +| `join(string $table, string $condition, string $alias, string $type)` | Добавить JOIN клаузу | +| `innerJoin(string $table, string $condition, string $alias)` | Добавить INNER JOIN | +| `leftJoin(string $table, string $condition, string $alias)` | Добавить LEFT JOIN | +| `groupBy(string $groupBy)` | Добавить GROUP BY клаузу | +| `orderBy(string $orderBy)` | Добавить ORDER BY клаузу | +| `limit(int $limit, int $offset = 0)` | Добавить LIMIT и OFFSET | +| `count(string $column = '*')` | Установить запрос на COUNT | +| `insert(array $data)` | Установить запрос на INSERT | +| `update(array $data)` | Установить запрос на UPDATE | +| `delete()` | Установить запрос на DELETE | +| `build()` | Построить и вернуть `['sql' => ..., 'params' => ...]` | +| `get()` | Псевдоним для `build()` | + +--- + +## Интеграция Tracy Debugger + +EasyQuery автоматически интегрируется с Tracy Debugger, если он установлен. Настройка не требуется! + +```bash +composer require tracy/tracy +``` + +```php +use Tracy\Debugger; + +Debugger::enable(); + +// Все запросы автоматически логируются в панель Tracy +$q = Builder::table('users')->where(['status' => 'active'])->build(); +``` + +Панель Tracy показывает: +- Общее количество запросов и разбивку по типу +- Сгенерированный SQL (подсветка синтаксиса) +- Массив параметров +- Детали запроса (таблица, where, join и т.д.) + +Для полной документации посетите [GitHub репозиторий](https://github.com/knifelemon/EasyQueryBuilder). diff --git a/content/v3/uk/awesome-plugins/awesome_plugins.md b/content/v3/uk/awesome-plugins/awesome_plugins.md index 19975f65..fe620fc6 100644 --- a/content/v3/uk/awesome-plugins/awesome_plugins.md +++ b/content/v3/uk/awesome-plugins/awesome_plugins.md @@ -65,6 +65,7 @@ CLI-додатки є чудовим способом взаємодіяти з - deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) - Офіційна обгортка Flight PDO, яка є частиною ядра (застаріла з v3.18.0). Використовуйте SimplePdo замість. - official [flightphp/active-record](/awesome-plugins/active-record) - Офіційний ORM/Mapper Flight ActiveRecord. Чудова маленька бібліотека для легкого отримання та зберігання даних у вашій базі даних. - [byjg/php-migration](/awesome-plugins/migrations) - Плагін для відстеження всіх змін бази даних для вашого проєкту. +- [knifelemon/easy-query](/awesome-plugins/easy-query) - Легкий, fluent SQL-конструктор запитів, який генерує SQL та параметри для prepared statements. Чудово працює з [SimplePdo](/learn/simple-pdo). ## Шифрування diff --git a/content/v3/uk/awesome-plugins/easy_query.md b/content/v3/uk/awesome-plugins/easy_query.md new file mode 100644 index 00000000..37c93bcb --- /dev/null +++ b/content/v3/uk/awesome-plugins/easy_query.md @@ -0,0 +1,569 @@ +# EasyQuery + +[knifelemon/easy-query](https://github.com/knifelemon/EasyQueryBuilder) — це легкий, fluent SQL-конструктор запитів, який генерує SQL та параметри для prepared statements. Працює з [SimplePdo](/learn/simple-pdo). + +## Можливості + +- 🔗 **Fluent API** - Ланцюгові методи для читабельної побудови запитів +- 🛡️ **Захист від SQL Injection** - Автоматичне зв'язування параметрів з prepared statements +- 🔧 **Підтримка Raw SQL** - Вставка SQL-виразів напряму через `raw()` +- 📝 **Різні типи запитів** - SELECT, INSERT, UPDATE, DELETE, COUNT +- 🔀 **Підтримка JOIN** - INNER, LEFT, RIGHT joins з псевдонімами +- 🎯 **Розширені умови** - LIKE, IN, NOT IN, BETWEEN, оператори порівняння +- 🌐 **Незалежність від БД** - Повертає SQL + params, використовуйте з будь-яким з'єднанням +- 🪶 **Легкий** - Мінімальний розмір без залежностей + +## Встановлення + +```bash +composer require knifelemon/easy-query +``` + +## Швидкий старт + +```php +use KnifeLemon\EasyQuery\Builder; + +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit(10) + ->build(); + +// Використання з SimplePdo Flight +$users = Flight::db()->fetchAll($q['sql'], $q['params']); +``` + +## Розуміння build() + +Метод `build()` повертає масив з `sql` та `params`. Це розділення захищає вашу базу даних через використання prepared statements. + +```php +$q = Builder::table('users') + ->where(['email' => 'user@example.com']) + ->build(); + +// Повертає: +// [ +// 'sql' => 'SELECT * FROM users WHERE email = ?', +// 'params' => ['user@example.com'] +// ] +``` + +--- + +## Типи запитів + +### SELECT + +```php +// Вибрати всі колонки +$q = Builder::table('users')->build(); +// SELECT * FROM users + +// Вибрати конкретні колонки +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->build(); +// SELECT id, name, email FROM users + +// З псевдонімом таблиці +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name']) + ->build(); +// SELECT u.id, u.name FROM users AS u +``` + +### INSERT + +```php +$q = Builder::table('users') + ->insert([ + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'status' => 'active' + ]) + ->build(); +// INSERT INTO users SET name = ?, email = ?, status = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +$userId = Flight::db()->lastInsertId(); +``` + +### UPDATE + +```php +$q = Builder::table('users') + ->update(['status' => 'inactive', 'updated_at' => date('Y-m-d H:i:s')]) + ->where(['id' => 123]) + ->build(); +// UPDATE users SET status = ?, updated_at = ? WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### DELETE + +```php +$q = Builder::table('users') + ->delete() + ->where(['id' => 123]) + ->build(); +// DELETE FROM users WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### COUNT + +```php +$q = Builder::table('users') + ->count() + ->where(['status' => 'active']) + ->build(); +// SELECT COUNT(*) AS cnt FROM users WHERE status = ? + +$count = Flight::db()->fetchField($q['sql'], $q['params']); +``` + +--- + +## Умови WHERE + +### Проста рівність + +```php +$q = Builder::table('users') + ->where(['id' => 123, 'status' => 'active']) + ->build(); +// WHERE id = ? AND status = ? +``` + +### Оператори порівняння + +```php +$q = Builder::table('users') + ->where([ + 'age' => ['>=', 18], + 'score' => ['<', 100], + 'name' => ['!=', 'admin'] + ]) + ->build(); +// WHERE age >= ? AND score < ? AND name != ? +``` + +### LIKE + +```php +$q = Builder::table('users') + ->where(['name' => ['LIKE', '%john%']]) + ->build(); +// WHERE name LIKE ? +``` + +### IN / NOT IN + +```php +// IN +$q = Builder::table('users') + ->where(['id' => ['IN', [1, 2, 3, 4, 5]]]) + ->build(); +// WHERE id IN (?, ?, ?, ?, ?) + +// NOT IN +$q = Builder::table('users') + ->where(['status' => ['NOT IN', ['banned', 'deleted']]]) + ->build(); +// WHERE status NOT IN (?, ?) +``` + +### BETWEEN + +```php +$q = Builder::table('products') + ->where(['price' => ['BETWEEN', [100, 500]]]) + ->build(); +// WHERE price BETWEEN ? AND ? +``` + +### Умови OR + +Використовуйте `orWhere()` для додавання згрупованих умов з OR: + +```php +$q = Builder::table('users') + ->where(['status' => 'active']) + ->orWhere([ + 'role' => 'admin', + 'permissions' => ['LIKE', '%manage%'] + ]) + ->build(); +// WHERE status = ? AND (role = ? OR permissions LIKE ?) +``` + +--- + +## JOIN + +### INNER JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name', 'p.title']) + ->innerJoin('posts', 'u.id = p.user_id', 'p') + ->build(); +// SELECT u.id, u.name, p.title FROM users AS u INNER JOIN posts AS p ON u.id = p.user_id +``` + +### LEFT JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.name', 'o.total']) + ->leftJoin('orders', 'u.id = o.user_id', 'o') + ->build(); +// ... LEFT JOIN orders AS o ON u.id = o.user_id +``` + +### Множинні JOIN + +```php +$q = Builder::table('orders') + ->alias('o') + ->select(['o.id', 'u.name AS customer', 'p.title AS product']) + ->innerJoin('users', 'o.user_id = u.id', 'u') + ->leftJoin('order_items', 'o.id = oi.order_id', 'oi') + ->leftJoin('products', 'oi.product_id = p.id', 'p') + ->where(['o.status' => 'completed']) + ->build(); +``` + +--- + +## Сортування, групування та ліміти + +### ORDER BY + +```php +$q = Builder::table('users') + ->orderBy('created_at DESC') + ->build(); +// ORDER BY created_at DESC +``` + +### GROUP BY + +```php +$q = Builder::table('orders') + ->select(['user_id', 'COUNT(*) as order_count']) + ->groupBy('user_id') + ->build(); +// SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id +``` + +### LIMIT та OFFSET + +```php +$q = Builder::table('users') + ->limit(10) + ->build(); +// LIMIT 10 + +$q = Builder::table('users') + ->limit(10, 20) // limit, offset + ->build(); +// LIMIT 10 OFFSET 20 +``` + +--- + +## Raw SQL вирази + +Використовуйте `raw()` коли потрібні SQL-функції або вирази, які не повинні оброблятися як зв'язані параметри. + +### Базовий Raw + +```php +$q = Builder::table('users') + ->update([ + 'login_count' => Builder::raw('login_count + 1'), + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => 123]) + ->build(); +// SET login_count = login_count + 1, updated_at = NOW() +``` + +### Raw зі зв'язаними параметрами + +```php +$q = Builder::table('orders') + ->update([ + 'total' => Builder::raw('COALESCE(subtotal, ?) + ?', [0, 10]) + ]) + ->where(['id' => 1]) + ->build(); +// SET total = COALESCE(subtotal, ?) + ? +// params: [0, 10, 1] +``` + +### Raw у WHERE (підзапит) + +```php +$q = Builder::table('products') + ->where([ + 'price' => ['>', Builder::raw('(SELECT AVG(price) FROM products)')] + ]) + ->build(); +// WHERE price > (SELECT AVG(price) FROM products) +``` + +### Безпечні ідентифікатори для користувацького вводу + +Коли імена колонок надходять від користувача, використовуйте `safeIdentifier()` для запобігання SQL injection: + +```php +$sortColumn = $_GET['sort']; // наприклад: 'created_at' +$safeColumn = Builder::safeIdentifier($sortColumn); + +$q = Builder::table('users') + ->orderBy($safeColumn . ' DESC') + ->build(); + +// Якщо користувач спробує: "name; DROP TABLE users--" +// Викидає InvalidArgumentException +``` + +### rawSafe для користувацьких імен колонок + +```php +$userColumn = $_GET['aggregate_column']; + +$q = Builder::table('orders') + ->select([ + Builder::rawSafe('SUM({col})', ['col' => $userColumn])->value . ' AS total' + ]) + ->build(); +// Валідує ім'я колонки, викидає виняток якщо невалідне +``` + +> **Увага:** Ніколи не конкатенуйте користувацький ввід напряму в `raw()`. Завжди використовуйте зв'язані параметри або `safeIdentifier()`. + +--- + +## Повторне використання Query Builder + +### Методи Clear + +Очистіть конкретні частини для повторного використання builder: + +```php +$query = Builder::table('users') + ->select(['id', 'name']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Перший запит +$q1 = $query->limit(10)->build(); + +// Очистити та використати повторно +$query->clearWhere()->clearLimit(); + +// Другий запит з іншими умовами +$q2 = $query + ->where(['status' => 'pending']) + ->limit(5) + ->build(); +``` + +### Доступні методи Clear + +| Метод | Опис | +|-------|------| +| `clearWhere()` | Очистити умови WHERE та параметри | +| `clearSelect()` | Скинути колонки SELECT до '*' за замовчуванням | +| `clearJoin()` | Очистити всі JOIN клаузи | +| `clearGroupBy()` | Очистити GROUP BY клаузу | +| `clearOrderBy()` | Очистити ORDER BY клаузу | +| `clearLimit()` | Очистити LIMIT та OFFSET | +| `clearAll()` | Скинути builder до початкового стану | + +### Приклад пагінації + +```php +$baseQuery = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// Отримати загальну кількість +$countQuery = clone $baseQuery; +$countResult = $countQuery->clearSelect()->count()->build(); +$total = Flight::db()->fetchField($countResult['sql'], $countResult['params']); + +// Отримати результати з пагінацією +$page = 1; +$perPage = 20; +$listResult = $baseQuery->limit($perPage, ($page - 1) * $perPage)->build(); +$users = Flight::db()->fetchAll($listResult['sql'], $listResult['params']); +``` + +--- + +## Динамічна побудова запитів + +```php +$query = Builder::table('products')->alias('p'); + +if (!empty($categoryId)) { + $query->where(['p.category_id' => $categoryId]); +} + +if (!empty($minPrice)) { + $query->where(['p.price' => ['>=', $minPrice]]); +} + +if (!empty($maxPrice)) { + $query->where(['p.price' => ['<=', $maxPrice]]); +} + +if (!empty($searchTerm)) { + $query->where(['p.name' => ['LIKE', "%{$searchTerm}%"]]); +} + +$result = $query->orderBy('p.created_at DESC')->limit(20)->build(); +$products = Flight::db()->fetchAll($result['sql'], $result['params']); +``` + +--- + +## Повний приклад FlightPHP + +```php +use KnifeLemon\EasyQuery\Builder; + +// Список користувачів з пагінацією +Flight::route('GET /users', function() { + $page = (int) (Flight::request()->query['page'] ?? 1); + $perPage = 20; + + $q = Builder::table('users') + ->select(['id', 'name', 'email', 'created_at']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit($perPage, ($page - 1) * $perPage) + ->build(); + + $users = Flight::db()->fetchAll($q['sql'], $q['params']); + Flight::json(['users' => $users, 'page' => $page]); +}); + +// Створити користувача +Flight::route('POST /users', function() { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->insert([ + 'name' => $data->name, + 'email' => $data->email, + 'created_at' => Builder::raw('NOW()') + ]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['id' => Flight::db()->lastInsertId()]); +}); + +// Оновити користувача +Flight::route('PUT /users/@id', function($id) { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->update([ + 'name' => $data->name, + 'email' => $data->email, + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); + +// Видалити користувача +Flight::route('DELETE /users/@id', function($id) { + $q = Builder::table('users') + ->delete() + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); +``` + +--- + +## API довідник + +### Статичні методи + +| Метод | Опис | +|-------|------| +| `Builder::table(string $table)` | Створити новий екземпляр builder для таблиці | +| `Builder::raw(string $sql, array $bindings = [])` | Створити raw SQL вираз | +| `Builder::rawSafe(string $expr, array $identifiers, array $bindings = [])` | Raw вираз з безпечною заміною ідентифікаторів | +| `Builder::safeIdentifier(string $identifier)` | Валідувати та повернути безпечне ім'я колонки/таблиці | + +### Методи екземпляра + +| Метод | Опис | +|-------|------| +| `alias(string $alias)` | Встановити псевдонім таблиці | +| `select(string\|array $columns)` | Встановити колонки для вибору (за замовчуванням: '*') | +| `where(array $conditions)` | Додати умови WHERE (AND) | +| `orWhere(array $conditions)` | Додати умови OR WHERE | +| `join(string $table, string $condition, string $alias, string $type)` | Додати JOIN клаузу | +| `innerJoin(string $table, string $condition, string $alias)` | Додати INNER JOIN | +| `leftJoin(string $table, string $condition, string $alias)` | Додати LEFT JOIN | +| `groupBy(string $groupBy)` | Додати GROUP BY клаузу | +| `orderBy(string $orderBy)` | Додати ORDER BY клаузу | +| `limit(int $limit, int $offset = 0)` | Додати LIMIT та OFFSET | +| `count(string $column = '*')` | Встановити запит на COUNT | +| `insert(array $data)` | Встановити запит на INSERT | +| `update(array $data)` | Встановити запит на UPDATE | +| `delete()` | Встановити запит на DELETE | +| `build()` | Побудувати та повернути `['sql' => ..., 'params' => ...]` | +| `get()` | Псевдонім для `build()` | + +--- + +## Інтеграція Tracy Debugger + +EasyQuery автоматично інтегрується з Tracy Debugger, якщо він встановлений. Налаштування не потрібне! + +```bash +composer require tracy/tracy +``` + +```php +use Tracy\Debugger; + +Debugger::enable(); + +// Всі запити автоматично логуються в панель Tracy +$q = Builder::table('users')->where(['status' => 'active'])->build(); +``` + +Панель Tracy показує: +- Загальну кількість запитів та розбивку за типом +- Згенерований SQL (підсвітка синтаксису) +- Масив параметрів +- Деталі запиту (таблиця, where, join тощо) + +Для повної документації відвідайте [GitHub репозиторій](https://github.com/knifelemon/EasyQueryBuilder). diff --git a/content/v3/zh/awesome-plugins/awesome_plugins.md b/content/v3/zh/awesome-plugins/awesome_plugins.md index c7349f0d..3bb6c76a 100644 --- a/content/v3/zh/awesome-plugins/awesome_plugins.md +++ b/content/v3/zh/awesome-plugins/awesome_plugins.md @@ -65,6 +65,7 @@ Cookie 是存储客户端小量数据的绝佳方式。它们可用于存储用 - deprecated [flightphp/core PdoWrapper](/learn/pdo-wrapper) - 官方 Flight PDO 包装器,是核心的一部分(自 v3.18.0 起已弃用)。请改用 SimplePdo。 - official [flightphp/active-record](/awesome-plugins/active-record) - 官方 Flight ActiveRecord ORM/映射器。一个优秀的库,便于轻松检索和存储数据库中的数据。 - [byjg/php-migration](/awesome-plugins/migrations) - 用于跟踪项目所有数据库变更的插件。 +- [knifelemon/easy-query](/awesome-plugins/easy-query) - 轻量级、流畅的SQL查询构建器,生成SQL和参数用于预处理语句。与 [SimplePdo](/learn/simple-pdo) 配合使用效果很好。 ## 加密 diff --git a/content/v3/zh/awesome-plugins/easy_query.md b/content/v3/zh/awesome-plugins/easy_query.md new file mode 100644 index 00000000..35c9a0a1 --- /dev/null +++ b/content/v3/zh/awesome-plugins/easy_query.md @@ -0,0 +1,569 @@ +# EasyQuery + +[knifelemon/easy-query](https://github.com/knifelemon/EasyQueryBuilder) 是一个轻量级的流畅式 SQL 查询构建器,用于生成 SQL 和参数。可与 [SimplePdo](/learn/simple-pdo) 配合使用。 + +## 特性 + +- 🔗 **流畅 API** - 链式方法构建可读性高的查询 +- 🛡️ **SQL 注入防护** - 通过预处理语句自动参数绑定 +- 🔧 **原生 SQL 支持** - 使用 `raw()` 插入 SQL 表达式 +- 📝 **多种查询类型** - SELECT, INSERT, UPDATE, DELETE, COUNT +- 🔀 **JOIN 支持** - INNER, LEFT, RIGHT 连接和别名 +- 🎯 **高级条件** - LIKE, IN, NOT IN, BETWEEN, 比较运算符 +- 🌐 **数据库无关** - 返回 SQL + params,可用于任何数据库连接 +- 🪶 **轻量级** - 零依赖,最小体积 + +## 安装 + +```bash +composer require knifelemon/easy-query +``` + +## 快速开始 + +```php +use KnifeLemon\EasyQuery\Builder; + +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit(10) + ->build(); + +// 与 Flight 的 SimplePdo 配合使用 +$users = Flight::db()->fetchAll($q['sql'], $q['params']); +``` + +## 理解 build() + +`build()` 方法返回包含 `sql` 和 `params` 的数组。这种分离通过使用预处理语句来保护数据库安全。 + +```php +$q = Builder::table('users') + ->where(['email' => 'user@example.com']) + ->build(); + +// 返回: +// [ +// 'sql' => 'SELECT * FROM users WHERE email = ?', +// 'params' => ['user@example.com'] +// ] +``` + +--- + +## 查询类型 + +### SELECT + +```php +// 选择所有列 +$q = Builder::table('users')->build(); +// SELECT * FROM users + +// 选择特定列 +$q = Builder::table('users') + ->select(['id', 'name', 'email']) + ->build(); +// SELECT id, name, email FROM users + +// 使用表别名 +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name']) + ->build(); +// SELECT u.id, u.name FROM users AS u +``` + +### INSERT + +```php +$q = Builder::table('users') + ->insert([ + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'status' => 'active' + ]) + ->build(); +// INSERT INTO users SET name = ?, email = ?, status = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +$userId = Flight::db()->lastInsertId(); +``` + +### UPDATE + +```php +$q = Builder::table('users') + ->update(['status' => 'inactive', 'updated_at' => date('Y-m-d H:i:s')]) + ->where(['id' => 123]) + ->build(); +// UPDATE users SET status = ?, updated_at = ? WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### DELETE + +```php +$q = Builder::table('users') + ->delete() + ->where(['id' => 123]) + ->build(); +// DELETE FROM users WHERE id = ? + +Flight::db()->runQuery($q['sql'], $q['params']); +``` + +### COUNT + +```php +$q = Builder::table('users') + ->count() + ->where(['status' => 'active']) + ->build(); +// SELECT COUNT(*) AS cnt FROM users WHERE status = ? + +$count = Flight::db()->fetchField($q['sql'], $q['params']); +``` + +--- + +## WHERE 条件 + +### 简单相等 + +```php +$q = Builder::table('users') + ->where(['id' => 123, 'status' => 'active']) + ->build(); +// WHERE id = ? AND status = ? +``` + +### 比较运算符 + +```php +$q = Builder::table('users') + ->where([ + 'age' => ['>=', 18], + 'score' => ['<', 100], + 'name' => ['!=', 'admin'] + ]) + ->build(); +// WHERE age >= ? AND score < ? AND name != ? +``` + +### LIKE + +```php +$q = Builder::table('users') + ->where(['name' => ['LIKE', '%john%']]) + ->build(); +// WHERE name LIKE ? +``` + +### IN / NOT IN + +```php +// IN +$q = Builder::table('users') + ->where(['id' => ['IN', [1, 2, 3, 4, 5]]]) + ->build(); +// WHERE id IN (?, ?, ?, ?, ?) + +// NOT IN +$q = Builder::table('users') + ->where(['status' => ['NOT IN', ['banned', 'deleted']]]) + ->build(); +// WHERE status NOT IN (?, ?) +``` + +### BETWEEN + +```php +$q = Builder::table('products') + ->where(['price' => ['BETWEEN', [100, 500]]]) + ->build(); +// WHERE price BETWEEN ? AND ? +``` + +### OR 条件 + +使用 `orWhere()` 添加 OR 分组条件: + +```php +$q = Builder::table('users') + ->where(['status' => 'active']) + ->orWhere([ + 'role' => 'admin', + 'permissions' => ['LIKE', '%manage%'] + ]) + ->build(); +// WHERE status = ? AND (role = ? OR permissions LIKE ?) +``` + +--- + +## JOIN + +### INNER JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.id', 'u.name', 'p.title']) + ->innerJoin('posts', 'u.id = p.user_id', 'p') + ->build(); +// SELECT u.id, u.name, p.title FROM users AS u INNER JOIN posts AS p ON u.id = p.user_id +``` + +### LEFT JOIN + +```php +$q = Builder::table('users') + ->alias('u') + ->select(['u.name', 'o.total']) + ->leftJoin('orders', 'u.id = o.user_id', 'o') + ->build(); +// ... LEFT JOIN orders AS o ON u.id = o.user_id +``` + +### 多个 JOIN + +```php +$q = Builder::table('orders') + ->alias('o') + ->select(['o.id', 'u.name AS customer', 'p.title AS product']) + ->innerJoin('users', 'o.user_id = u.id', 'u') + ->leftJoin('order_items', 'o.id = oi.order_id', 'oi') + ->leftJoin('products', 'oi.product_id = p.id', 'p') + ->where(['o.status' => 'completed']) + ->build(); +``` + +--- + +## 排序、分组和限制 + +### ORDER BY + +```php +$q = Builder::table('users') + ->orderBy('created_at DESC') + ->build(); +// ORDER BY created_at DESC +``` + +### GROUP BY + +```php +$q = Builder::table('orders') + ->select(['user_id', 'COUNT(*) as order_count']) + ->groupBy('user_id') + ->build(); +// SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id +``` + +### LIMIT 和 OFFSET + +```php +$q = Builder::table('users') + ->limit(10) + ->build(); +// LIMIT 10 + +$q = Builder::table('users') + ->limit(10, 20) // limit, offset + ->build(); +// LIMIT 10 OFFSET 20 +``` + +--- + +## 原生 SQL 表达式 + +当需要不应作为绑定参数处理的 SQL 函数或表达式时,使用 `raw()`。 + +### 基本 Raw + +```php +$q = Builder::table('users') + ->update([ + 'login_count' => Builder::raw('login_count + 1'), + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => 123]) + ->build(); +// SET login_count = login_count + 1, updated_at = NOW() +``` + +### 带绑定参数的 Raw + +```php +$q = Builder::table('orders') + ->update([ + 'total' => Builder::raw('COALESCE(subtotal, ?) + ?', [0, 10]) + ]) + ->where(['id' => 1]) + ->build(); +// SET total = COALESCE(subtotal, ?) + ? +// params: [0, 10, 1] +``` + +### WHERE 中的 Raw(子查询) + +```php +$q = Builder::table('products') + ->where([ + 'price' => ['>', Builder::raw('(SELECT AVG(price) FROM products)')] + ]) + ->build(); +// WHERE price > (SELECT AVG(price) FROM products) +``` + +### 用户输入的安全标识符 + +当列名来自用户输入时,使用 `safeIdentifier()` 防止 SQL 注入: + +```php +$sortColumn = $_GET['sort']; // 例如: 'created_at' +$safeColumn = Builder::safeIdentifier($sortColumn); + +$q = Builder::table('users') + ->orderBy($safeColumn . ' DESC') + ->build(); + +// 如果用户尝试: "name; DROP TABLE users--" +// 抛出 InvalidArgumentException +``` + +### 用户提供列名的 rawSafe + +```php +$userColumn = $_GET['aggregate_column']; + +$q = Builder::table('orders') + ->select([ + Builder::rawSafe('SUM({col})', ['col' => $userColumn])->value . ' AS total' + ]) + ->build(); +// 验证列名,无效时抛出异常 +``` + +> **警告:** 永远不要直接将用户输入连接到 `raw()`。始终使用绑定参数或 `safeIdentifier()`。 + +--- + +## 查询构建器重用 + +### Clear 方法 + +清除特定部分以重用构建器: + +```php +$query = Builder::table('users') + ->select(['id', 'name']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// 第一个查询 +$q1 = $query->limit(10)->build(); + +// 清除并重用 +$query->clearWhere()->clearLimit(); + +// 使用不同条件的第二个查询 +$q2 = $query + ->where(['status' => 'pending']) + ->limit(5) + ->build(); +``` + +### 可用的 Clear 方法 + +| 方法 | 描述 | +|------|------| +| `clearWhere()` | 清除 WHERE 条件和参数 | +| `clearSelect()` | 将 SELECT 列重置为默认 '*' | +| `clearJoin()` | 清除所有 JOIN 子句 | +| `clearGroupBy()` | 清除 GROUP BY 子句 | +| `clearOrderBy()` | 清除 ORDER BY 子句 | +| `clearLimit()` | 清除 LIMIT 和 OFFSET | +| `clearAll()` | 将构建器重置为初始状态 | + +### 分页示例 + +```php +$baseQuery = Builder::table('users') + ->select(['id', 'name', 'email']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC'); + +// 获取总数 +$countQuery = clone $baseQuery; +$countResult = $countQuery->clearSelect()->count()->build(); +$total = Flight::db()->fetchField($countResult['sql'], $countResult['params']); + +// 获取分页结果 +$page = 1; +$perPage = 20; +$listResult = $baseQuery->limit($perPage, ($page - 1) * $perPage)->build(); +$users = Flight::db()->fetchAll($listResult['sql'], $listResult['params']); +``` + +--- + +## 动态查询构建 + +```php +$query = Builder::table('products')->alias('p'); + +if (!empty($categoryId)) { + $query->where(['p.category_id' => $categoryId]); +} + +if (!empty($minPrice)) { + $query->where(['p.price' => ['>=', $minPrice]]); +} + +if (!empty($maxPrice)) { + $query->where(['p.price' => ['<=', $maxPrice]]); +} + +if (!empty($searchTerm)) { + $query->where(['p.name' => ['LIKE', "%{$searchTerm}%"]]); +} + +$result = $query->orderBy('p.created_at DESC')->limit(20)->build(); +$products = Flight::db()->fetchAll($result['sql'], $result['params']); +``` + +--- + +## FlightPHP 完整示例 + +```php +use KnifeLemon\EasyQuery\Builder; + +// 带分页的用户列表 +Flight::route('GET /users', function() { + $page = (int) (Flight::request()->query['page'] ?? 1); + $perPage = 20; + + $q = Builder::table('users') + ->select(['id', 'name', 'email', 'created_at']) + ->where(['status' => 'active']) + ->orderBy('created_at DESC') + ->limit($perPage, ($page - 1) * $perPage) + ->build(); + + $users = Flight::db()->fetchAll($q['sql'], $q['params']); + Flight::json(['users' => $users, 'page' => $page]); +}); + +// 创建用户 +Flight::route('POST /users', function() { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->insert([ + 'name' => $data->name, + 'email' => $data->email, + 'created_at' => Builder::raw('NOW()') + ]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['id' => Flight::db()->lastInsertId()]); +}); + +// 更新用户 +Flight::route('PUT /users/@id', function($id) { + $data = Flight::request()->data; + + $q = Builder::table('users') + ->update([ + 'name' => $data->name, + 'email' => $data->email, + 'updated_at' => Builder::raw('NOW()') + ]) + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); + +// 删除用户 +Flight::route('DELETE /users/@id', function($id) { + $q = Builder::table('users') + ->delete() + ->where(['id' => $id]) + ->build(); + + Flight::db()->runQuery($q['sql'], $q['params']); + Flight::json(['success' => true]); +}); +``` + +--- + +## API 参考 + +### 静态方法 + +| 方法 | 描述 | +|------|------| +| `Builder::table(string $table)` | 为表创建新的构建器实例 | +| `Builder::raw(string $sql, array $bindings = [])` | 创建原生 SQL 表达式 | +| `Builder::rawSafe(string $expr, array $identifiers, array $bindings = [])` | 带安全标识符替换的原生表达式 | +| `Builder::safeIdentifier(string $identifier)` | 验证并返回安全的列/表名 | + +### 实例方法 + +| 方法 | 描述 | +|------|------| +| `alias(string $alias)` | 设置表别名 | +| `select(string\|array $columns)` | 设置要选择的列(默认: '*') | +| `where(array $conditions)` | 添加 WHERE 条件(AND) | +| `orWhere(array $conditions)` | 添加 OR WHERE 条件 | +| `join(string $table, string $condition, string $alias, string $type)` | 添加 JOIN 子句 | +| `innerJoin(string $table, string $condition, string $alias)` | 添加 INNER JOIN | +| `leftJoin(string $table, string $condition, string $alias)` | 添加 LEFT JOIN | +| `groupBy(string $groupBy)` | 添加 GROUP BY 子句 | +| `orderBy(string $orderBy)` | 添加 ORDER BY 子句 | +| `limit(int $limit, int $offset = 0)` | 添加 LIMIT 和 OFFSET | +| `count(string $column = '*')` | 设置为 COUNT 查询 | +| `insert(array $data)` | 设置为 INSERT 查询 | +| `update(array $data)` | 设置为 UPDATE 查询 | +| `delete()` | 设置为 DELETE 查询 | +| `build()` | 构建并返回 `['sql' => ..., 'params' => ...]` | +| `get()` | `build()` 的别名 | + +--- + +## Tracy 调试器集成 + +如果安装了 Tracy Debugger,EasyQuery 会自动集成。无需配置! + +```bash +composer require tracy/tracy +``` + +```php +use Tracy\Debugger; + +Debugger::enable(); + +// 所有查询自动记录到 Tracy 面板 +$q = Builder::table('users')->where(['status' => 'active'])->build(); +``` + +Tracy 面板显示: +- 总查询数和类型分类 +- 生成的 SQL(语法高亮) +- 参数数组 +- 查询详情(表、where、join 等) + +完整文档请访问 [GitHub 仓库](https://github.com/knifelemon/EasyQueryBuilder)。